📄 cstartup.s
字号:
;- That's important to perform this operation before Remap in order to guarantee
;- that the core has valid vectors at any time during the remap operation.
;- Note: There are only 5 offsets as the vectoring is used.
;- ICE note : In this code only the start address value is changed if you use
;- without Semihosting.
;- Before Remap the internal RAM it's 0x300000
;- After Remap the internal RAM it's 0x000000
;- Remap it's already executed it's no possible to write to 0x300000.
;------------------------------------------------------------------------------
;- Copy the ARM exception vectors
movs r0, pc, LSR #20 ; if 12 highest pc bits are not 0
movne r8, #0 ; @ of the hard vector in internal RAM
moveq r8, #RAM_BASE ; @ of the hard vector in internal RAM
add r9, pc,#-(8+.-VectorTable) ; @ where to read values (relative)
ldmia r9!, {r0-r7} ; read 8 vectors
stmia r8!, {r0-r7} ; store them
ldmia r9!, {r0-r4} ; read 5 absolute handler addresses
stmia r8!, {r0-r4} ; store them
;------------------------------------------------------------------------------
;- Initialise the Memory Controller
;----------------------------------
;- That's principaly the Remap Command. Actually, all the External Bus
;- Interface is configured with some instructions and the User Interface Image
;- as described above. The jump "mov pc, r12" could be unread as it is after
;- located after the Remap but actually it is thanks to the Arm core pipeline.
;- The IniTableEBI addressing must be relative .
;- The PtInitRemap must be absolute as the processor jumps at this address
;- immediatly after the Remap is performed.
;- Note also that the EBI base address is loaded in r11 by the "ldmia".
;- ICE note :For ICE debug these values already set by the boot function and the
;- Remap it's already executed it's no need to set still.
;------------------------------------------------------------------------------
;- Copy the Image of the Memory Controller
sub r10, pc,#(8+.-InitTableEBI) ; get the address of the chip select register image
ldr r12, PtInitRemap ; get the real jump address ( after remap )
IF :DEF:AT91_DEBUG_NONE ; remap address
ldr r0,= 0x000FFFFF ; this code run to the flash adress but linked
and r12,r12,r0 ; at Ram adress
ldr r0,= FLASH_BASE
add r12,r12,r0
ENDIF
;- Copy Chip Select Register Image to Memory Controller and command remap
ldmia r10!, {r0-r9,r11} ; load the complete image and the EBI base
stmia r11!, {r0-r9} ; store the complete image with the remap command
;- Jump to ROM at its new address
mov pc, r12 ; jump and break the pipeline
PtInitRemap
DCD InitRemap ; address where to jump after REMAP
;------------------------------------------------------------------------------
;- The Reset Handler after Remap
;-------------------------------
;- From here, the code is continous execute from its link address.
;------------------------------------------------------------------------------
InitRemap
;------------------------------------------------------------------------------
;- Stack Sizes Definition
;------------------------
;- Interrupt Stack requires 3 words x 8 priority level x 4 bytes when using
;- the vectoring. This assume that the IRQ_ENTRY/IRQ_EXIT macro are used.
;- The Interrupt Stack must be adjusted depending on the interrupt handlers.
;- Fast Interrupt is the same than Interrupt without priority level.
;- Other stacks are defined by default to save one word each.
;- The System stack size is not defined and is limited by the free internal
;- SRAM.
;- User stack size is not defined and is limited by the free external SRAM.
;------------------------------------------------------------------------------
IRQ_STACK_SIZE EQU (3*8*4) ; 3 words per interrupt priority level
FIQ_STACK_SIZE EQU (3*4) ; 3 words
ABT_STACK_SIZE EQU (1*4) ; 1 word
UND_STACK_SIZE EQU (1*4) ; 1 word
;------------------------------------------------------------------------------
;- Top of Stack Definition
;-------------------------
;- Fast Interrupt, Interrupt, Abort, Undefined and Supervisor Stack are located
;- at the top of internal memory in order to speed the exception handling
;- context saving and restoring.
;- User (Application, C) Stack is located at the top of the external memory.
;------------------------------------------------------------------------------
TOP_APPLICATION_STACK_63_55 EQU 0x2040000 ; Defined in Target
TOP_APPLICATION_STACK_40 EQU 0x2080000 ; Defined in Target
;------------------------------------------------------------------------------
;- Setup the stack for each mode
;-------------------------------
ldr r2, =SF_BASE ; Get the SF_BASE.SF_CIDR
ldr r2, [R2,#SF_CIDR]
ldr r1, =SF_VDSIZ_MASK_SHIFT ; Get Mask Ram size
and r0,R1,R2, lsr #6 ; Get the Internal Ram size
;- Set up Fast Interrupt Mode and set FIQ Mode Stack
msr CPSR_c, #ARM_MODE_FIQ:OR:I_BIT:OR:F_BIT
mov r13, r0 ; Init stack FIQ
sub r0, r0, #FIQ_STACK_SIZE
;- Set up Interrupt Mode and set IRQ Mode Stack
msr CPSR_c, #ARM_MODE_IRQ:OR:I_BIT:OR:F_BIT
mov r13, r0 ; Init stack IRQ
sub r0, r0, #IRQ_STACK_SIZE
;- Set up Abort Mode and set Abort Mode Stack
msr CPSR_c, #ARM_MODE_ABORT:OR:I_BIT:OR:F_BIT
mov r13, r0 ; Init stack Abort
sub r0, r0, #ABT_STACK_SIZE
;- Set up Undefined Instruction Mode and set Undef Mode Stack
msr CPSR_c, #ARM_MODE_UNDEF:OR:I_BIT:OR:F_BIT
mov r13, r0 ; Init stack Undef
sub r0, r0, #UND_STACK_SIZE
;- Set up Supervisor Mode and set Supervisor Mode Stack
msr CPSR_c, #ARM_MODE_SVC:OR:I_BIT:OR:F_BIT
mov r13, r0 ; Init stack Sup
;------------------------------------------------------------------------------
;- Setup Application Operating Mode and Enable the interrupts
;------------------------------------------------------------
;- System Mode is selected first and the stack is setup. This allows to prevent
;- any interrupt occurence while the User is not initialized. System Mode is
;- used as the interrupt enabling would be avoided from User Mode (CPSR cannot
;- be written while the core is in User Mode).
;------------------------------------------------------------------------------
msr CPSR_c, #ARM_MODE_USER ; set User mode
ldr r13, =TOP_APPLICATION_STACK_63_55 ; Init stack User
ldr r2, =SF_BASE ; Get the SF_BASE.SF_CIDR
ldr r2, [R2,#SF_CIDR]
ldr r1, =SF_ARCH ; Get Architecture Mask
and r1,R1,R2 ; Get the Internal Ram size
ldr R2, =SF_ARCH_AT91x40
cmp R1,R2
ldreq r13, =TOP_APPLICATION_STACK_40
; Get Mask Ram size
;------------------------------------------------------------------------------
;- Copy the code in external RAM
;--------------------------------
;- Following labels are automatically generated by the linker.
;- RO: Read-only = the code
;- RW: Read Write = the data pre-initialized and zero-initialized.
;- ZI: Zero-Initialized.
;------------------------------------------------------------------------------
; Application kinked and run in RAM copy Flash to RAM
IMPORT |C$$code$$Base|
IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)
IMPORT |Image$$RW$$Base| ; Base of RAM to initialise
IMPORT |Image$$ZI$$Base| ; Base and limit of area
ldr r0,=EXT_SRAM_BASE
ldr r1,=FLASH_BASE ; Flash address before remap
ldr r3,= |Image$$ZI$$Base|
ldr r2,= |Image$$RW$$Base|
sub r3,r3,r2 ; r3 = size const char
ldr r2,= |Image$$RO$$Limit|
add r3,r2,r3 ; r3 Total data size
IF :DEF:AT91_DEBUG_NONE ; Copy flash to RAM
LoopCode cmp r0, r3
ldrcc r2, [r1], #4
strcc r2, [r0], #4
bcc LoopCode
ENDIF
;------------------------------------------------------------------------------
;- Initialise C variables
;------------------------
;- Following labels are automatically generated by the linker.
;- RO: Read-only = the code
;- RW: Read Write = the data pre-initialized and zero-initialized.
;- ZI: Zero-Initialized.
;- Pre-initialization values are located after the code area in the image.
;- Zero-initialized datas are mapped after the pre-initialized.
;- Note on the Data position :
;- If using the ARMSDT, when no -rw-base option is used for the linker, the
;- data area is mapped after the code. You can map the data either in internal
;- SRAM ( -rw-base=0x40 or 0x34) or in external SRAM ( -rw-base=0x2000000 ).
;- Note also that to improve the code density, the pre_initialized data must
;- be limited to a minimum.
;------------------------------------------------------------------------------
IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)
IMPORT |Image$$RW$$Base| ; Base of RAM to initialise
IMPORT |Image$$ZI$$Base| ; Base and limit of area
IMPORT |Image$$ZI$$Limit| ; to zero initialise
ldr r0, =|Image$$RO$$Limit| ; Get pointer to ROM data
ldr r1, =|Image$$RW$$Base| ; and RAM copy
ldr r3, =|Image$$ZI$$Base| ; Zero init base => top of initialised data
cmp r0, r1 ; Check that they are different
beq NoRW
LoopRw cmp r1, r3 ; Copy init data
ldrcc r2, [r0], #4
strcc r2, [r1], #4
bcc LoopRw
NoRW ldr r1, =|Image$$ZI$$Limit| ; Top of zero init segment
mov r2, #0
LoopZI cmp r3, r1 ; Zero init
strcc r2, [r3], #4
bcc LoopZI
;------------------------------------------------------------------------------
;- Branch on C code Main function (with interworking)
;----------------------------------------------------
;- Branch must be performed by an interworking call as either an ARM or Thumb
;- main C function must be supported. This makes the code not position-
;- independant. A Branch with link would generate errors
;------------------------------------------------------------------------------
IMPORT main
ldr r0, =main
mov lr, pc
bx r0
;------------------------------------------------------------------------------
;- Loop for ever
;---------------
;- End of application. Normally, never occur.
;- Could jump on Software Reset ( B 0x0 ).
;------------------------------------------------------------------------------
End
b End
; Call __low_level_init to perform initialization before initializing
; AIC and calling main.
; Pll Initialization
;----------------------------------------------------------------------
__low_level_init
;- Speed up the System Frequency.
;---------------------------------
ldr r0, =0x002F0002 ; MOSCEN = 1, OSCOUNT = 47 (1.4ms/30祍)
ldr r1, =APMC_BASE ; Get the APMC Base Address
str r0, [r1, #APMC_CGMR] ; Store the configuration of the Clock Generator
;- Reading the APMC Status register to detect when the oscillator is stabilized
;------------------------------------------------------------------------------
mov r4, #APMC_MOSCS
MoscsLoop
ldr r2, [r1, #APMC_SR]
and r2, r4,r2
cmp r2, #APMC_MOSCS
bne MoscsLoop
;- Commuting from Slow Clock to Main Oscillator (16Mhz)
;------------------------------------------------------
ldr r0, =0x002F4002 ; MOSCEN = 1, OSCOUNT = 47 (1.4ms/30祍)
str r0, [r1, #APMC_CGMR] ; Store the configuration of the Clock Generator
;-Setup the PLL
;---------------
ldr r0, =0x032F4102 ; MUL = 1, PLLCOUNT = 3, CSS = 1
str r0, [r1, #APMC_CGMR] ; Store the configuration of the Clock Generator
;- Reading the APMC Status register to detect when the PLL is stabilized
;-----------------------------------------------------------------------
mov r4, #APMC_PLL_LOCK
Pll_Loop
ldr r3, [r1, #APMC_SR]
and r3, r4,r3
cmp r3, #APMC_PLL_LOCK
bne Pll_Loop
;- Commuting from 16Mhz to PLL @ 32MHz
;--------------------------------------
ldr r0, =0x032F8102 ; CSS = 2, MUL = 1
str r0, [r1, #APMC_CGMR] ; Store the configuration of the Clock Generator
;- Now the Master clock is the output of PLL @ 32MHz
;----------------------------------------------------
mov pc,r14 ; Return
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -