📄 startup.s
字号:
;// <e> AT91M55800A APMC Clock Setup
;// <o1.14..15> CSS: Clock Source Selection
;// <0=> Low-Frequency Clock
;// <1=> Main Oscillator or External Clock
;// <2=> Phase Lock Loop Output
;// <o1.0> MOSCBYP: Main Oscillator Bypass
;// <0=> No: Crystal (XIN, XOUT)
;// <1=> Yes: External Clock (XIN)
;// <q1.1> MOSCEN: Main Oscillator Enable <0-1>
;// <i> Must be disabled in Bypass Mode
;// <o1.4..6> PRES: Prescaler
;// <0=> None
;// <1=> Clock / 2 <2=> Clock / 4
;// <3=> Clock / 8 <4=> Clock / 16
;// <5=> Clock / 32 <6=> Clock / 64
;// <o1.8..13> MUL: Phase Lock Loop Factor <0-63>
;// <i> PLL Output is multiplied by MUL+1
;// <o1.16..23> OSCOUNT: Main Oscillator Counter <0x0-0xFF>
;// <i> Oscillator Startup Timer
;// <o1.24..29> PLLCOUNT: PLL Lock Counter <0x0-0x3F>
;// <i> PLL Lock Timer
;// <q1.2> MCKODS: Master Clock Output Disable <0-1>
;// </e>
APMC_SETUP EQU 1
APMC_CGMR_Val EQU 0x032F4002
; 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 (before Remap)
; Mapped to Address 0 before Remap Command.
; Relative addressing mode must be used.
Reset_Vec B Reset_Handler
Undef_Vec B Undef_Vec
SWI_Vec B SWI_Vec
PAbt_Vec B PAbt_Vec
DAbt_Vec B DAbt_Vec
NOP
IRQ_Vec B IRQ_Vec
FIQ_Vec B FIQ_Vec
; Exception Vectors (after Remap)
; Mapped to Address 0 after Remap Command.
; 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, [PC, #-0xF20] ; Vector from AIC_IVR
; LDR PC, FIQ_Addr
LDR PC, [PC, #-0xF20] ; Vector from AIC_FVR
Reset_Addr DCD Soft_Reset
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
Soft_Reset B Soft_Reset
Undef_Handler B Undef_Handler
SWI_Handler B SWI_Handler
PAbt_Handler B PAbt_Handler
DAbt_Handler B DAbt_Handler
IRQ_Handler B IRQ_Handler
FIQ_Handler B FIQ_Handler
; Reset Handler
EXPORT Reset_Handler
Reset_Handler
; Setup PMC System Clock
IF PMC_SETUP <> 0
LDR R0, =PMC_BASE
; Setup the PLL
IF (PMC_CGMR_Val:AND:PMC_MUL) <> 0
LDR R1, =(PMC_CGMR_Val:AND:(:NOT:PMC_CSS))
STR R1, [R0, #PMC_CGMR]
; Wait until PLL stabilized
PLL_Loop LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_PLL_LOCK
BEQ PLL_Loop
ENDIF
; Switch from Slow Clock to Selected Clock
LDR R1, =PMC_CGMR_Val
STR R1, [R0, #PMC_CGMR]
ENDIF ; PMC_SETUP
; Setup APMC System Clock
IF APMC_SETUP <> 0
LDR R0, =APMC_BASE
; Enable Main Oscillator
IF (APMC_CGMR_Val:AND:APMC_MOSC_EN) <> 0
LDR R1, =(APMC_CGMR_Val:AND:(:NOT:(APMC_CSS:OR:APMC_MUL)))
STR R1, [R0, #APMC_CGMR]
; Wait until Oscillator stabilized
MOSCS_Loop LDR R2, [R0, #APMC_SR]
ANDS R2, R2, #APMC_MOSCS
BEQ MOSCS_Loop
ENDIF
; Setup the PLL
IF (APMC_CGMR_Val:AND:APMC_MUL) <> 0
LDR R1, =(APMC_CGMR_Val:AND:(:NOT:APMC_CSS))
STR R1, [R0, #APMC_CGMR]
; Wait until PLL stabilized
PLL_Loop LDR R2, [R0, #APMC_SR]
ANDS R2, R2, #APMC_PLL_LOCK
BEQ PLL_Loop
ENDIF
; Switch from Slow Clock to Selected Clock
LDR R1, =APMC_CGMR_Val
STR R1, [R0, #APMC_CGMR]
ENDIF ; APMC_SETUP
; Copy Exception Vectors to Internal RAM before Remap
ADR R8, Vectors
IF :DEF:REMAPPED
MOV R9, #RAM_Base
ELSE
MOV R9, #RAM_Base_Boot
ENDIF
LDMIA R8!, {R0-R7} ; Load Vectors
STMIA R9!, {R0-R7} ; Store Vectors
LDMIA R8!, {R0-R7} ; Load Handler Addresses
STMIA R9!, {R0-R7} ; Store Handler Addresses
; Initialise EBI and execute Remap
LDR R12, AfterRemapAdr ; Get the Real Jump Address
ADR R11, EBI_Table
LDMIA R11, {R0-R10} ; Load EBI Data
STMIA R10, {R0-R9} ; Store EBI Data with Remap
BX R12 ; Jump and flush Pipeline
EBI_Table DCD EBI_CSR0_Val
DCD EBI_CSR1_Val
DCD EBI_CSR2_Val
DCD EBI_CSR3_Val
DCD EBI_CSR4_Val
DCD EBI_CSR5_Val
DCD EBI_CSR6_Val
DCD EBI_CSR7_Val
DCD 0x00000001 ; Remap Command
DCD EBI_MCR_Val
DCD EBI_BASE
AfterRemapAdr DCD AfterRemap
AfterRemap
; Initialise Interrupt System
; ...
; 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
MOV R1,#0x3F
LDR R0,=0x0FFFEC000
STR R1,[R0,#0x00]
; // PIOA_OER = 0x0000003F (PA 0-5 Output Enable)
STR R1,[R0,#0x10]
; // PIOA_SODR = 0x00000015 (Set PA 0,2,4)
MOV R1,#0x15
STR R1,[R0,#0x30]
; // PIOB_PER = 0x0000FF0F (PB 0,1,8-15 Controllable)
LDR R1,=0xFF0F
LDR R0,=0x0FFFF0000
STR R1,[R0,#0x00]
; // PIOB_OER = 0x0000FF0F (PB 0,1,8-15 Output Enable)
STR R1,[R0,#0x10]
; // PIOB_SODR = 0x00005500 (Set PB 8,10,12,14)
MOV R1,#0x5500
STR R1,[R0,#0x30]
; // PIOB_CODR = 0x00000003 (Clear PB 0,1)
MOV R1,#0x03
STR R1,[R0,#0x34]
here
NOP
B here
; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -