这里我用到的汇编代码是来自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
这里先贴出代码,下一篇将对其进行分析。