AT91RM9200启动代码start.s解读与学习笔记(1)
这里我用到的汇编代码是来自YL9200开发板的资料,先提出该汇编文件:
INCLUDE AT91RM9200.inc _STACK_BASEADDRESS EQU 0x21ff8000 _MMUTT_STARTADDRESS EQU 0x21ff8000 _ISR_STARTADDRESS EQU 0x21ffff00 ;Pre-defined constants USERMODE EQU 0x10 FIQMODE EQU 0x11 IRQMODE EQU 0x12 SVCMODE EQU 0x13 ABORTMODE EQU 0x17 UNDEFMODE EQU 0x1b MODEMASK EQU 0x1f NOINT EQU 0xc0 I_BIT EQU 0x80 F_BIT EQU 0x40 T_BIT EQU 0x20 AREA reset, CODE, READONLY ENTRY EXPORT __ENTRY __ENTRY ResetEntry b ResetHandler ldr pc, =HandlerUndef ;handler for Undefined mode ldr pc, =HandlerSWI ;handler for SWI interrupt ldr pc, =HandlerPabort ;handler for PAbort ldr pc, =HandlerDabort ;handler for DAbort ldr pc, =. ;reserved ldr pc, =HandlerIRQ ;handler for IRQ interrupt ;ldr pc, [pc,#-0xF20] ;IRQ : read the AIC ldr pc, =HandlerFIQ ;handler for FIQ interrupt EXPORT this_machine_ip this_machine_ip DCD (192<<24)|(168<<16)|(2<<8)|(223) MACRO $HandlerLabel HANDLER $HandleLabel $HandlerLabel sub sp, sp, #4 ;decrement sp(to store jump address) stmfd sp!, {r0} ;PUSH the work register to stack(lr does't push because it return to original address) ldr r0, =$HandleLabel ;load the address of HandleXXX to r0 ldr r0, [r0] ;load the contents(service routine start address) of HandleXXX str r0, [sp, #4] ;store the contents(ISR) of HandleXXX to stack ldmfd sp!, {r0, pc} ;POP the work register and pc(jump to ISR) MEND LTORG HandlerFIQ HANDLER HandleFIQ HandlerIRQ HANDLER HandleIRQ HandlerUndef HANDLER HandleUndef HandlerSWI HANDLER HandleSWI HandlerDabort HANDLER HandleDabort HandlerPabort HANDLER HandlePabort IsrIRQ sub sp, sp, #4 ;reserved for PC stmfd sp!,{r8-r9} ldr r9, =AT91C_BASE_AIC mov r8, r9 ldr r9, [r9, #AIC_ISR] and r9, r9, #0x1f add r8, r8, r9, lsl #2 ldr r8, [r8, #AIC_SVR] str r8, [sp, #8] ldmfd sp!,{r8-r9,pc} ; * the actual reset code ResetHandler ;Set up User Mode, set User Mode Stack and disable interrupts msr CPSR_c, #(SVCMODE|I_BIT|F_BIT) ;------------------------------------------------------------------------------ ;Step 1. ;------------------------------------------------------------------------------ ;-Enabling the Main Oscillator ;-Normally First instruction in PMC initialisation ;------------------------------------------------------------------------------ ;-Main oscillator Enable register APMC_MOR : Enable main oscillator , OSCOUNT = 0xFF ldr r1, = AT91C_BASE_CKGR ; Get the CKGR Base Address ldr r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT str r0, [r1, #CKGR_MOR] ; set the cpu to SVC32 mode ; mrs r0, cpsr ; bic r0, r0, #0x1f ; orr r0, r0, #0x13 ; msr cpsr_cf, r0 ; relocate exeception table adr r0, ResetEntry mov r1, #0 mov r2, #16 copyex subs r2, r2, #1 ldr r3, [r0], #4 str r3, [r1], #4 bne copyex IMPORT LowLevelInit ; ldr r1, =0x204000;=SVCStack ; bic r1, r1, #3 ; Insure word alignement ; mov sp, r1 ; Init stack SYS mov sp, #0x204000 bl LowLevelInit ;Initialize stacks bl InitStacks copy_proc_beg adr r0, ResetEntry ldr r2, BaseOfROM cmp r0, r2 ldreq r0, TopOfROM beq InitRam ldr r3, TopOfROM 0 ldmia r0!, {r4-r7} stmia r2!, {r4-r7} cmp r2, r3 bcc %B0 sub r2, r2, r3 sub r0, r0, r2 InitRam ldr r2, BaseOfBSS ldr r3, BaseOfZero 0 cmp r2, r3 ldrcc r1, [r0], #4 strcc r1, [r2], #4 bcc %B0 mov r0, #0 ldr r3, EndOfBSS 1 cmp r2, r3 strcc r0, [r2], #4 bcc %B1 IMPORT irq_handler ; Setup IRQ handler ldr r0, =HandleIRQ ;This routine is needed ;ldr r1, =IsrIRQ ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c ldr r1, =irq_handler str r1, [r0] IMPORT main _main __main EXPORT _main EXPORT __main ; swi 0x1234 ;test swi ldr r0, =main mov lr, pc bx r0 b . ;=========================================================== ;The location of stacks UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~ SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~ UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~ AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~ IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~ FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~ ;function initializing stacks InitStacks ;Don't use DRAM,such as stmfd,ldmfd...... ;SVCstack is initialized before ;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1' mrs r0,cpsr bic r0,r0,#MODEMASK orr r1,r0,#UNDEFMODE|NOINT msr cpsr_cxsf,r1 ;UndefMode ldr sp,=UndefStack orr r1,r0,#ABORTMODE|NOINT msr cpsr_cxsf,r1 ;AbortMode ldr sp,=AbortStack orr r1,r0,#IRQMODE|NOINT msr cpsr_cxsf,r1 ;IRQMode ldr sp,=IRQStack orr r1,r0,#FIQMODE|NOINT msr cpsr_cxsf,r1 ;FIQMode ldr sp,=FIQStack bic r0,r0,#MODEMASK|NOINT orr r1,r0,#SVCMODE msr cpsr_cxsf,r1 ;SVCMode ldr sp,=SVCStack ;USER mode has not be initialized. mov pc,lr ;The LR register won't be valid if the current mode is not SVC mode. ;=========================================================== IMPORT |Image$$RO$$Base| ; Base of ROM code 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 BaseOfROM DCD |Image$$RO$$Base| TopOfROM DCD |Image$$RO$$Limit| BaseOfBSS DCD |Image$$RW$$Base| BaseOfZero DCD |Image$$ZI$$Base| EndOfBSS DCD |Image$$ZI$$Limit| ALIGN EXPORT DisableInt DisableInt mrs r0, cpsr orr r0, r0, #0xc0 msr cpsr_cf, r0 mov pc, lr AREA RamData, DATA, READWRITE ^ _ISR_STARTADDRESS HandleReset # 4 HandleUndef # 4 HandleSWI # 4 HandlePabort # 4 HandleDabort # 4 HandleReserved # 4 HandleIRQ # 4 HandleFIQ # 4 ;Don't use the label 'IntVectorTable', ;The value of IntVectorTable is different with the address you think it may be. ;IntVectorTable HandleEINT0 # 4 HandleEINT1 # 4 HandleEINT2 # 4 HandleEINT3 # 4 HandleEINT4_7 # 4 HandleEINT8_23 # 4 HandleRSV6 # 4 HandleBATFLT # 4 HandleTICK # 4 HandleWDT # 4 HandleTIMER0 # 4 HandleTIMER1 # 4 HandleTIMER2 # 4 HandleTIMER3 # 4 HandleTIMER4 # 4 HandleUART2 # 4 HandleLCD # 4 HandleDMA0 # 4 HandleDMA1 # 4 HandleDMA2 # 4 HandleDMA3 # 4 HandleMMC # 4 HandleSPI0 # 4 HandleUART1 # 4 HandleRSV24 # 4 HandleUSBD # 4 HandleUSBH # 4 HandleIIC # 4 HandleUART0 # 4 HandleSPI1 # 4 HandleRTC # 4 HandleADC # 4 END
这里先贴出代码,下一篇将对其进行分析。