原创 AT91RM9200启动代码start.s解读与学习笔记

2010-9-2 10:35 1639 1 1 分类: MCU/ 嵌入式

这里我用到的汇编代码是来自YL9200开发板的资料,先提出该汇编文件:


view source





print


?





001


    INCLUDE   AT91RM9200.inc




002


  




003


_STACK_BASEADDRESS  EQU 0x21ff8000




004


_MMUTT_STARTADDRESS EQU 0x21ff8000




005


_ISR_STARTADDRESS   EQU 0x21ffff00




006


  




007


;Pre-defined constants




008


USERMODE    EQU     0x10




009


FIQMODE     EQU     0x11




010


IRQMODE     EQU     0x12




011


SVCMODE     EQU     0x13




012


ABORTMODE   EQU     0x17




013


UNDEFMODE   EQU     0x1b




014


MODEMASK    EQU     0x1f




015


NOINT       EQU     0xc0




016


I_BIT   EQU 0x80




017


F_BIT   EQU 0x40




018


T_BIT   EQU 0x20




019


  




020


    AREA    reset, CODE, READONLY




021


      




022


    ENTRY




023


      




024


    EXPORT  __ENTRY




025


__ENTRY 




026


ResetEntry




027


    b   ResetHandler




028


    ldr pc, =HandlerUndef       ;handler for Undefined mode




029


    ldr pc, =HandlerSWI         ;handler for SWI interrupt




030


    ldr pc, =HandlerPabort      ;handler for PAbort




031


    ldr pc, =HandlerDabort      ;handler for DAbort




032


    ldr pc, =.                  ;reserved




033


    ldr pc, =HandlerIRQ         ;handler for IRQ interrupt




034


    ;ldr    pc, [pc,#-0xF20]        ;IRQ : read the AIC




035


    ldr pc, =HandlerFIQ         ;handler for FIQ interrupt




036


      




037


    EXPORT  this_machine_ip




038


this_machine_ip DCD (192<<24)|(168<<16)|(2<<8)|(223)




039


  




040


        MACRO




041


$HandlerLabel HANDLER $HandleLabel




042


  




043


$HandlerLabel




044


    sub sp, sp, #4          ;decrement sp(to store jump address)




045


    stmfd   sp!, {r0}       ;PUSH the work register to stack(lr does't push because it return to original address)




046


    ldr r0, =$HandleLabel   ;load the address of HandleXXX to r0




047


    ldr r0, [r0]            ;load the contents(service routine start address) of HandleXXX




048


    str r0, [sp, #4]        ;store the contents(ISR) of HandleXXX to stack




049


    ldmfd   sp!, {r0, pc}   ;POP the work register and pc(jump to ISR)




050


    MEND




051


  




052


    LTORG   




053


HandlerFIQ      HANDLER HandleFIQ




054


HandlerIRQ      HANDLER HandleIRQ




055


HandlerUndef    HANDLER HandleUndef




056


HandlerSWI      HANDLER HandleSWI




057


HandlerDabort   HANDLER HandleDabort




058


HandlerPabort   HANDLER HandlePabort




059


  




060


IsrIRQ




061


    sub sp, sp, #4       ;reserved for PC




062


    stmfd   sp!,{r8-r9}




063


      




064


    ldr r9, =AT91C_BASE_AIC




065


    mov r8, r9




066


    ldr r9, [r9, #AIC_ISR]




067


    and r9, r9, #0x1f




068


    add r8, r8, r9, lsl #2




069


    ldr r8, [r8, #AIC_SVR]




070


    str r8, [sp, #8]




071


    ldmfd   sp!,{r8-r9,pc}  




072


  




073


; * the actual reset code




074


  




075


ResetHandler




076


    ;Set up User Mode, set User Mode Stack and disable interrupts   




077


    msr CPSR_c, #(SVCMODE|I_BIT|F_BIT)




078


      




079


;------------------------------------------------------------------------------




080


;Step 1.




081


;------------------------------------------------------------------------------




082


;-Enabling the Main Oscillator




083


;-Normally First instruction in PMC initialisation




084


;------------------------------------------------------------------------------




085


;-Main oscillator Enable register   APMC_MOR : Enable main oscillator , OSCOUNT = 0xFF




086


    ldr     r1, = AT91C_BASE_CKGR   ; Get the CKGR Base Address




087


    ldr     r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT




088


    str     r0, [r1, #CKGR_MOR]




089


      




090


    ; set the cpu to SVC32 mode 




091


;   mrs r0, cpsr




092


;   bic r0, r0, #0x1f




093


;   orr r0, r0, #0x13




094


;   msr cpsr_cf, r0




095


          




096


    ; relocate exeception table  




097


    adr r0, ResetEntry




098


    mov r1, #0




099


    mov r2, #16




100


copyex




101


    subs    r2, r2, #1




102


    ldr r3, [r0], #4




103


    str r3, [r1], #4




104


    bne copyex  




105


      




106


    IMPORT  LowLevelInit




107


      




108


;   ldr r1, =0x204000;=SVCStack




109


;   bic r1, r1, #3              ; Insure word alignement




110


;   mov sp, r1                  ; Init stack SYS




111


    mov sp, #0x204000




112


      




113


    bl  LowLevelInit




114


      




115


    ;Initialize stacks




116


    bl  InitStacks




117


      




118


copy_proc_beg




119


    adr r0, ResetEntry




120


    ldr r2, BaseOfROM




121


    cmp r0, r2




122


    ldreq   r0, TopOfROM




123


    beq InitRam 




124


    ldr r3, TopOfROM




125


0   




126


    ldmia   r0!, {r4-r7}




127


    stmia   r2!, {r4-r7}




128


    cmp r2, r3




129


    bcc %B0




130


      




131


    sub r2, r2, r3




132


    sub r0, r0, r2              




133


          




134


InitRam 




135


    ldr r2, BaseOfBSS




136


    ldr r3, BaseOfZero  




137


0




138


    cmp r2, r3




139


    ldrcc   r1, [r0], #4




140


    strcc   r1, [r2], #4




141


    bcc %B0 




142


  




143


    mov r0, #0




144


    ldr r3, EndOfBSS




145


1   




146


    cmp r2, r3




147


    strcc   r0, [r2], #4




148


    bcc %B1




149


      




150


    IMPORT  irq_handler




151


    ; Setup IRQ handler




152


    ldr r0, =HandleIRQ          ;This routine is needed




153


    ;ldr    r1, =IsrIRQ         ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c




154


    ldr r1, =irq_handler




155


    str r1, [r0]




156


  




157


    IMPORT  main




158


_main




159


__main




160


    EXPORT  _main




161


    EXPORT  __main




162


;   swi 0x1234      ;test swi




163


    ldr r0, =main




164


    mov lr, pc




165


    bx  r0  




166


    b   .




167


  




168


;===========================================================




169


;The location of stacks




170


UserStack   EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~ 




171


SVCStack    EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~




172


UndefStack  EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~




173


AbortStack  EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~




174


IRQStack    EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~




175


FIQStack    EQU (_STACK_BASEADDRESS-0x0)    ;0x33ff8000 ~ 




176


  




177


;function initializing stacks




178


InitStacks




179


    ;Don't use DRAM,such as stmfd,ldmfd......




180


    ;SVCstack is initialized before




181


    ;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'




182


    mrs r0,cpsr




183


    bic r0,r0,#MODEMASK




184


    orr r1,r0,#UNDEFMODE|NOINT




185


    msr cpsr_cxsf,r1        ;UndefMode




186


    ldr sp,=UndefStack




187


      




188


    orr r1,r0,#ABORTMODE|NOINT




189


    msr cpsr_cxsf,r1        ;AbortMode




190


    ldr sp,=AbortStack




191


  




192


    orr r1,r0,#IRQMODE|NOINT




193


    msr cpsr_cxsf,r1        ;IRQMode




194


    ldr sp,=IRQStack




195


      




196


    orr r1,r0,#FIQMODE|NOINT




197


    msr cpsr_cxsf,r1        ;FIQMode




198


    ldr sp,=FIQStack




199


  




200


    bic r0,r0,#MODEMASK|NOINT




201


    orr r1,r0,#SVCMODE




202


    msr cpsr_cxsf,r1        ;SVCMode




203


    ldr sp,=SVCStack




204


      




205


    ;USER mode has not be initialized.




206


      




207


    mov pc,lr 




208


    ;The LR register won't be valid if the current mode is not SVC mode.




209


  




210


;===========================================================    




211


    IMPORT  |Image$$RO$$Base|   ; Base of ROM code




212


    IMPORT  |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data)




213


    IMPORT  |Image$$RW$$Base|   ; Base of RAM to initialise




214


    IMPORT  |Image$$ZI$$Base|   ; Base and limit of area




215


    IMPORT  |Image$$ZI$$Limit|  ; to zero initialise    




216


  




217


BaseOfROM   DCD |Image$$RO$$Base|




218


TopOfROM    DCD |Image$$RO$$Limit|




219


BaseOfBSS   DCD |Image$$RW$$Base|




220


BaseOfZero  DCD |Image$$ZI$$Base|




221


EndOfBSS    DCD |Image$$ZI$$Limit|




222


  




223


        ALIGN




224


          




225


    EXPORT DisableInt




226


DisableInt




227


    mrs r0, cpsr




228


    orr r0, r0, #0xc0




229


    msr cpsr_cf, r0




230


    mov pc, lr      




231


  




232


        AREA RamData, DATA, READWRITE




233


  




234


        ^   _ISR_STARTADDRESS




235


HandleReset     #   4




236


HandleUndef     #   4




237


HandleSWI       #   4




238


HandlePabort    #   4




239


HandleDabort    #   4




240


HandleReserved  #   4




241


HandleIRQ       #   4




242


HandleFIQ       #   4




243


  




244


;Don't use the label 'IntVectorTable',




245


;The value of IntVectorTable is different with the address you think it may be.




246


;IntVectorTable




247


HandleEINT0     #   4




248


HandleEINT1     #   4




249


HandleEINT2     #   4




250


HandleEINT3     #   4




251


HandleEINT4_7   #   4




252


HandleEINT8_23  #   4




253


HandleRSV6  #   4




254


HandleBATFLT    #   4




255


HandleTICK      #   4




256


HandleWDT   #   4




257


HandleTIMER0    #   4




258


HandleTIMER1    #   4




259


HandleTIMER2    #   4




260


HandleTIMER3    #   4




261


HandleTIMER4    #   4




262


HandleUART2     #   4




263


HandleLCD   #   4




264


HandleDMA0  #   4




265


HandleDMA1  #   4




266


HandleDMA2  #   4




267


HandleDMA3  #   4




268


HandleMMC   #   4




269


HandleSPI0  #   4




270


HandleUART1 #   4




271


HandleRSV24 #   4




272


HandleUSBD  #   4




273


HandleUSBH  #   4




274


HandleIIC       #   4




275


HandleUART0     #   4




276


HandleSPI1  #   4




277


HandleRTC   #   4




278


HandleADC   #   4




279


  




280


    END


 


 


 


 


 


相信有很多人和我一样,刚刚入手arm的时候非常忙然,无知得连问题都问不出来,其实我现在就是这样,所以才决定做一个这样的分析,一是记录自己的学习过程,一是把成果与大家共享。


9200的资料不多,至少文字版的资料不多,我们学校图书馆关于ARM的书几乎全是三星2410和2440,让像我这样上手就是工业级的9200芯片学习者有点苦恼。不过网上有很多共享者们提供了很多信息,所以只要善于学习,还是能够学好的,至少我是这么认为呢,虽然现在我还不是很懂。


说说我的情况,我刚做完自己的一个9200硬件电路板,有时间也把相关经历共享一下。现在开始学习软件,虽然对汇编,c语言等都有一定的基础,但是读起相关的代码还是有很多困难,所以我决定记录一下,以防以后笔记丢失,当然共享才是我的真正目的,呵呵~~~


好,进入正题。


先正题分析一下9200的这个启动代码包含的功能模块:


1:定义程序入口地址


2:系统时钟初始化


3:定义中断向量表


4:堆栈初始化


5:映像文件运行域初始化


6:进入主程序


这个顺序有点乱,分析的时候会给出对应的代码



接着讲,这次让我们来具体分析一下,我们就按照该文件的执行顺序来进行分析:


首先,程序入口地址进入后,第一条指令便是

b	ResetHandler

 


直接跳到标号ResetHandler处,执行复位后的处理程序,这段程序是:

ResetHandler
;Set up User Mode, set User Mode Stack and disable interrupts
msr CPSR_c, #(SVCMODE|I_BIT|F_BIT)

 


这句代码做了一件事,让系统进入管理模式,并且屏蔽IRQ和FIQ中断,这里用到了cpsr寄存器,该寄存器是程序状态寄存器,具体用法我的博客的另外一篇文章有简单的介绍。用到的汇编指令msr是将寄存器的值或者立即数放入程序状态寄存器中。


接下来,程序将顺序执行,有如下代码:

	ldr     r1, = AT91C_BASE_CKGR	; Get the CKGR Base Address
ldr r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT
str r0, [r1, #CKGR_MOR]

 


该段代码的作用是使能主振荡器,并制定慢时钟的周期数作为主振荡器的启动时间。


接下来,重定向异常向量表:

; 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

 


adr指令是获取ReserEntry标号地址赋予r0,接下来进行的是一个循环,目的是将ResetEntry地址对应的指令赋予地址0x0处,即起始地址处,同理,循环16次即把其他的中断服务程序首地址也放在起始地址处,每次地址加4,即一个字。而起始地址处是9200固定的中断跳转的地方。所以,本段代码实现了将中断服务程序的首地址放到中断向量表中,有中断的时候会执行跳转,到中断服务程序继续执行。


接下来进行基本的初始化:

IMPORT	LowLevelInit
; ldr r1, =0x204000;=SVCStack
; bic r1, r1, #3 ; Insure word alignement
; mov sp, r1 ; Init stack SYS
mov sp, #0x204000
bl LowLevelInit

 


先声明lowlevelinit函数来自外部,实际上来自init.c文件中,然后初始化了管理模式的堆栈,然后进行函数调用,执行一些初始化工作,该初始化工作的内容在这里就不多讲了,主要包含PLL初始化,中断控制器的初始化,SDRAM初始化,isr初始化,时钟计数器初始化,调试串口初始化,串口配置等工作。


然后进行的是堆栈初始化:

;Initialize stacks
bl InitStacks

 


也采用的是程序调用的方式,程序代码如下:


;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.

 


该段程序主要实现的是各种模式下的堆栈的初始化工作。学过单片机我们知道,我们在进行函数调用和中断的时候,都会用到堆栈,为什么我们用单片机的时候没有涉及到堆栈的初始化呢,那是因为我们在用单片机的时候,基本上只有一种模式,,一个堆栈,而ARM则有很多种模式,各个模式的堆栈是不一样的,所以就涉及到了各个模式要初始化不同的堆栈地址,这就是我们这段程序的目的。


根据第一个未定义模式的注释我们可以了解后面几种模式的操作,都是一样的,读取,修改,回写的方法。最后的一个mov指令进行子程序返回。


下一次再接着讲,今天先到这儿~~~~



PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
1
关闭 站长推荐上一条 /1 下一条