ARM7(三星44B0)启动代码分析

来源:互联网 发布:windows管理员权限获取 编辑:程序博客网 时间:2024/05/10 19:07

Written By Benny_Cen

 

  44B0启动代码隔一段时间没看,趁今天有空温习一下!!

 

最初的头文件:    

     INCLUDE option.inc
    INCLUDE memcfg.inc

1.前面包括的头文件,是关于存储器的控制参数和汇编程序设置

2.然后是存储器空间地址的定义, 外设和存器空间信息: 中断控制、看门狗定时器、系统时钟、存储器控制、BDMA目的寄存器、7种模式预定义常数

3.然后这一段:

  GBLL    THUMBCODE
    [ {CONFIG} = 16 
THUMBCODE SETL {TRUE}
    CODE32
    |  
THUMBCODE SETL {FALSE}
    ]

    [ THUMBCODE
    CODE32   ;for start-up code for Thumb mode
    ]

这段检查是否使用tasm.exe进行编译,既是thumb指令编译了;

4.

中断向量宏定义:这里先熟悉两个ARM汇编指令,LDM(加载)和STM(存储),配置类型:IA 传送后地址+1,IB传送前地址+1,DA传送后地址-1,DB传送前地址-1,FD满递减,ED空递减,FA满递增,EA空递增,!为数据传送完毕后最后地址写入基址寄存器,简单说,STM第二功能是PUSH,LDM第二功能是POP

STMFD R13!,{R0,R4-R12,LR}   ;R0,R4-R12,LR放入R13指向的堆栈,放一次R13内容减一

LDMFD R13!,{R0,R4-R12,LR}  ;将栈内容恢复至R0,R4-R12,LR 中注意并不是原来内容了,R13放一次内容加一

宏源码如下:

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

    MACRO                                ;中断向量宏定义 

$HandlerLabel HANDLER $HandleLabel

 

$HandlerLabel                           

 sub          sp,sp,#4                                     ;SP指针为存跳转地址 sp=sp-4

    stmfd   sp!,{r0}                                 ;ro入栈    push r0

    ldr        r0,=$HandleLabel             ;装载处理地址到ro(中断服务入口地址)

    ldr                r0,[r0]                                   ;装载处理地址内容到r0,即是将HandleLabel的内容传给r0

    str        r0,[sp,#4]                                     ;存储r0到栈中,r0放到[sp+4]

    ldmfd   sp!,{r0,pc}                                 ;出栈并跳到r0指向的地址

    MEND   

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

                   上面程序就是将中断服务程序地址装载到pc上,r0没变化

5.声明地址

                            IMPORT   |Image$$RO$$Base|      ; ROM code start 开始地址  

                            IMPORT   |Image$$RO$$Limit|      ; RAM data starts after ROM program结束地址

                            IMPORT   |Image$$RW$$Base|     ; Pre-initialised variables

                            IMPORT   |Image$$ZI$$Base|        ; uninitialised variables

                            IMPORT   |Image$$ZI$$Limit|        ; End of variable RAM space

                  6.

                 

      代码段入口 AREA    Init,CODE,READONLY 段标识,段名称,代码段,只读

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

                         AREA    Init,CODE,READONLY           ;初始人代码段

                         ENTRY                                ;程序入口

 

ResetEntry                                                      ;定义各种模式处理程序

                         b ResetHandler                                           ;复位处理

                         b HandlerUndef                                          ;未定义处理

                         b HandlerSWI                                              ;SWI中断处理

                         b HandlerPabort                                         ;指令中止处理

                         b HandlerDabort                                        ;数据中止处理

                       b .                                                                      ;保留

                          b HandlerIRQ                         ;中断处理

                       b HandlerFIQ                         ;快速中断处理

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

其中比较重要的是复位处理函数ResetHandlerb.是保留,该处地址存放空数据,具体看ARM 芯片手册

             7.ResetHandler分析

      ResetHandler是44B0在复位时首先调用的,看一下作了什么:

             

      首先进行一系列寄存器复位,看门狗、时钟、锁相环置频率等,把初始值放到相应的空间,然后这一段:

                   ;****************************************************

             ;设定存储器控制寄存器                                                         *     

             ;****************************************************

                  adr   r0, ResetHandler                        ;和下面一样

                  ldr    r1, =ResetHandler                     ;r1ResetHandler

                  sub   r0, r1, r0                                       ;其实是r0清0

                   ldr    r1, =SMRDATA                             ;r1取地址,SMRDATA   寄存着很重要的数据

                  sub   r0, r1, r0                                      ;其实是传给r0

                  ldmia   r0, {r1-r13}                           ;r0开始的连续数据空间传给r1-r13

                  ldr        r0, =0x01c80000                         ;BWSCON Address

                  stmia   r0, {r1-r13}                           ;r1-r13传到BWSCON Address指向内容

                  

                   来来去去,就是把SMRDATA数据传到0x01c80000中去

         然后看SMRDATA数据:是数据空间的分配,bank0-bank7数据空间进行配置,DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))     ;GCS0

         置位看另一个头文件,总之是一些初始分配数据。

再看初始化堆栈:

;****************************************************

    ;初始化堆栈                                                                              *

    ;****************************************************

    ldr        sp, =SVCStack           ;复位后位SVC模式

    bl          InitStacks                            ;跳转至InitStacks

 

                8.InitStacks函数

                

;****************************************************

;*      The function for initializing stack                                 *

;****************************************************

InitStacks

         ;Do not use DRAM,such as stmfd,ldmfd......

         ;SVCstack is initialized before

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

 

    mrs      r0,cpsr                                 ;传送cpsrr0

    bic        r0,r0,#MODEMASK                    ;清除r0中某些位

    orr        r1,r0,#UNDEFMODE|NOINT

    msr      cpsr_cxsf,r1                        ;UndefMode

    ldr        sp,=UndefStack

就是把cpsr中某些位修改后保存,sp指向堆栈,初始化堆栈空间

         后面连续语句都是对其余模式进行堆栈初始化,最后mov     pc,lr,函数返回

 

好了,执行完堆栈初始化,然后是设置中断处理了:

         ;****************************************************

    ;设置中断处理                                                                                     *

    ;****************************************************

    ldr        r0,=HandleIRQ                   ;This routine is needed

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

    str        r1,[r0]                          ;就是将IsrIRQ函数地址给HandleIRQ

         HandleIRQ是中断向量地址,ldr      r0,=HandleIRQ         是把中断地址给r0,

         HandlerIRQ               HANDLER HandleIRQ

         先前进行了宏定义,向量表是进行宏替换,中断时跳入处理

         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;中断向量表                                                                                 

;Example: HandlerADC    HANDLE HandleADC 解为

;HandlerADC                                                  ;HandlerADC为中断向量表的入口               

;   sub        sp,sp,#4                     ;sp减少一个字节,使其在堆栈高端留出存储返回地址,因为pc在寄存器组中的的位置大于r0,出栈时装入的是栈的高端的内容        

;   stmfd   sp!,{r0}                         ;保存r0                                                                             

;   ldr         r0,=HandleADC                 ;装载中断处理函数的指针                              

;   ldr         r0,[r0]                                   ;装载中断处理函数的地址                              

;   str         r0,[sp,#4]                            ;将中断处理函数的地址存入刚才预留的位置,r0的上面                                   

;   ldmfd   sp!,{r0,pc}                    ;出栈后,pc指向的既是中断处理函数的地址            ;        INTCON^2 == 0,vector table使能                                                                                  

;        发生中断->HandlerADC->HandleADC(pISR_ADC,:_ISR_STARTADDRESS+0x20);                       

;        若要在程序中处理此中断,只要将中断服务函数的指针赋给pISR_ADC,如:pISR_ADC = (int)ADCIsr                     ;

设置中断处理,把IsrIRQ函数(服务程序)传到HandleIRQ

          

 

           9.数据拷贝

         设置中段处理后,接下来进行数据拷贝,是把flash中数据拷贝到RAM中。

         BaseOfROM     DCD |Image$$RO$$Base|ROM基址

         TopOfROM       DCD |Image$$RO$$Limit|ROM结束地址

BaseOfBSS        DCD |Image$$RW$$Base|已初始地址

BaseOfZero      DCD |Image$$ZI$$Base|;未初始化基址

EndOfBSS DCD |Image$$ZI$$Limit|        ; 未初始化结束地址

 

然后看开始一段: 

         ;****************************************************

    ;拷贝并粘贴 RW data/zero initialized data              *

    ;****************************************************

         adr            r0, ResetEntry                             ;装载入口地址                          

         ldr              r1,    BaseOfROM                       ;r1装载flash基址

         cmp           r0,    r1                                           ;比较是否地址重叠

         ldreq         r0, TopOfROM                             ;是的就装RAM data starts after

         beq            InitRamData                                ;同时调用RAM初始化

 

         执行后,r0为入口地址,r1装载Flash起始地址

 

         ;****************************************************

         ;计算拷贝程序在flash中的实际位置                                           *

         ;****************************************************

         ldr              r2,    =CopyProcBeg          ;装载CopyProcBeg入口所在地址

         sub            r1, r2, r1                              ;r1flash基址,计算偏移相对地址

         add            r0, r0, r1                              ;r0是入口地址

         ldr              r3,    =CopyProcEnd          ;r3装载CopyProcBeg结束所在地址

 

执行后,r2保存着CopyProcBeg入口所在地址,r1得到相对地址,然后加上入口地址,r0保存RAM中应在地址,r3保存CopyProcBeg结束所在地址

 

 

               10.RAM初始化

       11.跳到主程序Main运行

         [ :LNOT:THUMBCODE

         BL              Main             ;从汇编进入C语言代码空间,不要使用main()

         B       .                                                     

    ]

    [ THUMBCODE                      ;for start-up code for Thumb mode

         orr     lr,pc,#1

         bx      lr

         CODE16

         bl      Main     ;从汇编进入C语言代码空间,不要使用main()

         b       .

         CODE32

]

   然后就从C程序中的Main程序执行!

 

原创粉丝点击