; *** Startup Code (executed after Reset) ***
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
UND_Stack_Size EQU 0x00000000
SVC_Stack_Size EQU 0x00000008
ABT_Stack_Size EQU 0x00000000
FIQ_Stack_Size EQU 0x00000000
IRQ_Stack_Size EQU 0x00000080
USR_Stack_Size EQU 0x00000400
Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
FIQ_Stack_Size + IRQ_Stack_Size + USR_Stack_Size)
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
Stack_Top EQU Stack_Mem + Stack_Size
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
Heap_Mem SPACE Heap_Size
; Clock Management definitions
CLK_BASE EQU 0x4C000000 ; Clock Base Address
LOCKTIME_OFS EQU 0x00 ; LOCKTIME Offset
MPLLCON_OFS EQU 0x04 ; MPLLCON Offset
UPLLCON_OFS EQU 0X08 ; UPLLCON Offset
CLKCON_OFS EQU 0x0C ; CLKCON Offset
CLKSLOW_OFS EQU 0x10 ; CLKSLOW Offset
CLKDIVN_OFS EQU 0X14 ; CLDKIVN Offset
CAMDIVN_OFS EQU 0X18 ; CAMDIVN Offset
CLK_SETUP EQU 1
MPLLCON_Val EQU 0x0005C080
UPLLCON_Val EQU 0x00028080
CLKCON_Val EQU 0x0007FFF0
CLKSLOW_Val EQU 0x00000004
LOCKTIME_Val EQU 0x00FFFFFF
CLKDIVN_Val EQU 0X00000000
;Interrupt definitions
INTOFFSET EQU 0X4A000014 ;Address of Interrupt offset Register
IntVT_SETUP EQU 1
IntVTAddress EQU 0x33FFFF20
; Watchdog Timer definitions
WT_BASE EQU 0x53000000 ; WT Base Address
WTCON_OFS EQU 0x00 ; WTCON Offset
WTDAT_OFS EQU 0x04 ; WTDAT Offset
WTCNT_OFS EQU 0x08 ; WTCNT Offset
WT_SETUP EQU 1
WTCON_Val EQU 0x00008021
WTDAT_Val EQU 0x00008000
; Memory Controller definitions
MC_BASE EQU 0x48000000 ; Memory Controller Base Address
;// Memory Controller
MC_SETUP EQU 1
BANKCON0_Val EQU 0x00000700
BANKCON1_Val EQU 0x00000700
BANKCON2_Val EQU 0x00000700
BANKCON3_Val EQU 0x00000700
BANKCON4_Val EQU 0x00000700
BANKCON5_Val EQU 0x00000700
BANKCON6_Val EQU 0x00018008
BANKCON7_Val EQU 0x00018008
BWSCON_Val EQU 0x00000000
REFRESH_Val EQU 0x00ac0000
BANKSIZE_Val EQU 0x00000000
MRSRB6_Val EQU 0x00000020
MRSRB7_Val EQU 0x00000000
;// End of MC
; I/O Ports definitions
PIO_BASE EQU 0x56000000 ; PIO Base Address
PCONA_OFS EQU 0x00 ; PCONA Offset
PCONB_OFS EQU 0x10 ; PCONB Offset
PCONC_OFS EQU 0x20 ; PCONC Offset
PCOND_OFS EQU 0x30 ; PCOND Offset
PCONE_OFS EQU 0x40 ; PCONE Offset
PCONF_OFS EQU 0x50 ; PCONF Offset
PCONG_OFS EQU 0x60 ; PCONG Offset
PCONH_OFS EQU 0x70 ; PCONH Offset
PCONJ_OFS EQU 0xD0 ; PCONJ Offset
PUPB_OFS EQU 0x18 ; PUPB Offset
PUPC_OFS EQU 0x28 ; PUPC Offset
PUPD_OFS EQU 0x38 ; PUPD Offset
PUPE_OFS EQU 0x48 ; PUPE Offset
PUPF_OFS EQU 0x58 ; PUPF Offset
PUPG_OFS EQU 0x68 ; PUPG Offset
PUPH_OFS EQU 0x78 ; PUPH Offset
PUPJ_OFS EQU 0xD8 ; PUPJ Offset
;// I/O Configuration
PIO_SETUP EQU 1
PIOA_SETUP EQU 0
PCONA_Val EQU 0x000003FF
PIOB_SETUP EQU 0
PCONB_Val EQU 0x000007FF
PUPB_Val EQU 0x00000000
PIOC_SETUP EQU 0
PCONC_Val EQU 0xAAAAAAAA
PUPC_Val EQU 0x00000000
PIOD_SETUP EQU 0
PCOND_Val EQU 0x00000000
PUPD_Val EQU 0x00000000
PIOE_SETUP EQU 0
PCONE_Val EQU 0x00000000
PUPE_Val EQU 0x00000000
PIOF_SETUP EQU 1
PCONF_Val EQU 0x0000511A
PUPF_Val EQU 0x00000000
PIOG_SETUP EQU 0
PCONG_Val EQU 0x00000000
PUPG_Val EQU 0x00000000
PIOH_SETUP EQU 0
PCONH_Val EQU 0x000007FF
PUPH_Val EQU 0x00000000
PRESERVE8
; Area Definition and Entry Point
; Startup Code must be linked first at Address at which it expects to run.
AREA RESET, CODE, READONLY
ARM
; Exception Vectors
; Mapped to Address 0.
; Absolute addressing mode must be used.
; Dummy Handlers are implemented as infinite loops which can be modified.
Vectors LDR PC, Reset_Addr
LDR PC, Undef_Addr
LDR PC, SWI_Addr
LDR PC, PAbt_Addr
LDR PC, DAbt_Addr
NOP ; Reserved Vector
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
IF IntVT_SETUP <> 0
;Interrupt Vector Table Address
HandleEINT0
EQU IntVTAddress
HandleEINT1
EQU IntVTAddress +4
HandleEINT2
EQU IntVTAddress +4*2
HandleEINT3
EQU IntVTAddress +4*3
HandleEINT4_7
EQU IntVTAddress +4*4
HandleEINT8_23 EQU IntVTAddress +4*5
HandleReserved
EQU IntVTAddress +4*6
HandleBATFLT
EQU IntVTAddress +4*7
HandleTICK
EQU IntVTAddress +4*8
HandleWDT
EQU IntVTAddress +4*9
HandleTIMER0
EQU IntVTAddress +4*10
HandleTIMER1
EQU IntVTAddress +4*11
HandleTIMER2
EQU IntVTAddress +4*12
HandleTIMER3
EQU IntVTAddress +4*13
HandleTIMER4
EQU IntVTAddress +4*14
HandleUART2
EQU IntVTAddress +4*15
HandleLCD
EQU IntVTAddress +4*16
HandleDMA0
EQU IntVTAddress +4*17
HandleDMA1
EQU IntVTAddress +4*18
HandleDMA2
EQU IntVTAddress +4*19
HandleDMA3
EQU IntVTAddress +4*20
HandleMMC
EQU IntVTAddress +4*21
HandleSPI0
EQU IntVTAddress +4*22
HandleUART1
EQU IntVTAddress +4*23
;HandleReserved
EQU IntVTAddress +4*24
HandleUSBD
EQU IntVTAddress +4*25
HandleUSBH
EQU IntVTAddress +4*26
HandleIIC
EQU IntVTAddress +4*27
HandleUART0
EQU IntVTAddress +4*28
HandleSPI1
EQU IntVTAddress +4*39
HandleRTC
EQU IntVTAddress +4*30
HandleADC
EQU IntVTAddress +4*31
IRQ_Entry
sub
sp,sp,#4 ;reserved for PC
stmfd
sp!,{r8-r9}
ldr
r9,=INTOFFSET
ldr
r9,[r9]
ldr
r8,=HandleEINT0
add
r8,r8,r9,lsl #2
ldr
r8,[r8]
str
r8,[sp,#8]
ldmfd
sp!,{r8-r9,pc}
ENDIF
Reset_Addr DCD Reset_Handler
Undef_Addr DCD Undef_Handler
SWI_Addr DCD SWI_Handler
PAbt_Addr DCD PAbt_Handler
DAbt_Addr DCD DAbt_Handler
DCD 0 ; Reserved Address
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
Undef_Handler B Undef_Handler
SWI_Handler B SWI_Handler
PAbt_Handler B PAbt_Handler
DAbt_Handler B DAbt_Handler
IF IntVT_SETUP <> 1
IRQ_Handler B IRQ_Handler
ENDIF
IF IntVT_SETUP <> 0
IRQ_Handler B IRQ_Entry
ENDIF
FIQ_Handler B FIQ_Handler
; Memory Controller Configuration
IF MC_SETUP <> 0
MC_CFG
DCD BWSCON_Val
DCD BANKCON0_Val
DCD BANKCON1_Val
DCD BANKCON2_Val
DCD BANKCON3_Val
DCD BANKCON4_Val
DCD BANKCON5_Val
DCD BANKCON6_Val
DCD BANKCON7_Val
DCD REFRESH_Val
DCD BANKSIZE_Val
DCD MRSRB6_Val
DCD MRSRB7_Val
ENDIF
; Clock Management Configuration
IF CLK_SETUP <> 0
CLK_CFG
DCD LOCKTIME_Val
DCD CLKDIVN_Val
DCD MPLLCON_Val
DCD UPLLCON_Val
DCD CLKSLOW_Val
DCD CLKCON_Val
ENDIF
; Reset Handler
EXPORT Reset_Handler
Reset_Handler
IF WT_SETUP <> 0
LDR R0, =WT_BASE
LDR R1, =WTCON_Val
LDR R2, =WTDAT_Val
STR R2, [R0, #WTCNT_OFS]
STR R2, [R0, #WTDAT_OFS]
STR R1, [R0, #WTCON_OFS]
ENDIF
IF CLK_SETUP <> 0
LDR R0, =CLK_BASE
ADR R8, CLK_CFG
LDMIA R8, {R1-R6}
STR R1, [R0, #LOCKTIME_OFS]
STR R2, [R0, #CLKDIVN_OFS]
STR R3, [R0, #MPLLCON_OFS]
STR R4, [R0, #UPLLCON_OFS]
STR R5, [R0, #CLKSLOW_OFS]
STR R6, [R0, #CLKCON_OFS]
ENDIF
IF MC_SETUP <> 0
ADR R14, MC_CFG
LDMIA R14, {R0-R12}
LDR R14, =MC_BASE
STMIA R14, {R0-R12}
ENDIF
IF PIO_SETUP <> 0
LDR R14, =PIO_BASE
IF PIOA_SETUP <> 0
LDR R0, =PCONA_Val
STR R0, [R14, #PCONA_OFS]
ENDIF
IF PIOB_SETUP <> 0
LDR R0, =PCONB_Val
LDR R1, =PUPB_Val
STR R0, [R14, #PCONB_OFS]
STR R1, [R14, #PUPB_OFS]
ENDIF
IF PIOC_SETUP <> 0
LDR R0, =PCONC_Val
LDR R1, =PUPC_Val
STR R0, [R14, #PCONC_OFS]
STR R1, [R14, #PUPC_OFS]
ENDIF
IF PIOD_SETUP <> 0
LDR R0, =PCOND_Val
LDR R1, =PUPD_Val
STR R0, [R14, #PCOND_OFS]
STR R1, [R14, #PUPD_OFS]
ENDIF
IF PIOE_SETUP <> 0
LDR R0, =PCONE_Val
LDR R1, =PUPE_Val
STR R0, [R14, #PCONE_OFS]
STR R1, [R14, #PUPE_OFS]
ENDIF
IF PIOF_SETUP <> 0
LDR R0, =PCONF_Val
LDR R1, =PUPF_Val
STR R0, [R14, #PCONF_OFS]
STR R1, [R14, #PUPF_OFS]
ENDIF
IF PIOG_SETUP <> 0
LDR R0, =PCONG_Val
LDR R1, =PUPG_Val
STR R0, [R14, #PCONG_OFS]
STR R1, [R14, #PUPG_OFS]
ENDIF
IF PIOH_SETUP <> 0
LDR R0, =PCONH_Val
LDR R1, =PUPH_Val
STR R0, [R14, #PCONH_OFS]
STR R1, [R14, #PUPH_OFS]
ENDIF
ENDIF
; Setup Stack for each mode
LDR R0, =Stack_Top
; Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size
; Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size
; Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
; Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
; Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size
; Enter User Mode and set its Stack Pointer
MSR CPSR_c, #Mode_USR
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
; Enter the C code
IMPORT __main
LDR R0, =__main
BX R0
; User Initial Stack & Heap
AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + USR_Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
END