单片机
返回首页

S3C2440启动代码中应用程序执行环境的初始化

2016-03-03 来源:eefocus

一、基础知识

          我们编写的源文件(.c 或.s)经过ARM 编译器的编译生成ELF 格式的目标文件(后缀名为.o),目标文件经过ARM 连接器连接以后生成ELF 格式的映像文件(后缀名为.axf),此时的映像文件还包含一些调试信息,我们还需要通过fromelf 工具将其转换成适合在ROM 或RAM 中运行的二进制代码(后缀名为.bin),这时生成的二进制映像文件就可以被烧写入目标板的ROM 或FLASH 中,当目标板上电后可以通过各种方式在ROM 或RAM 中运行。
一个可执行程序的映像文件由一个或多个域组成,域分为两种:一种是映像文件在存储器中存放的地址,称为加载域;另一种是映像文件运行时的地址,称为运行域。每个域由一个或3 个输出段组成,每个输出段则由一个或多个输入段组成。输入段包含程序代码、已经初始化的数据、未经初始化的存储区、被初始化为0 的存储区,输入段据此可分为三种属性:RO(只读,包括代码和常量)、RW(可读可写,包括已经初始化的全局变量和静态变量)、ZI(未初始化的变量,需初始化为0), 连接器根据属性将输入段分组,组成不同的输出段。一个输出段是有具有相同属性的输入段组成的,输出段的属性与其中输入段的属性相同,因而输出段也分为三种。域由不同属性的输出段组成,输出段在域中的排列顺序为RO 输出段排在最前,然后是RW 输出段,RW 输出段和RO 输出段可以不连续,最后是ZI 输出段,ZI 输出段是紧接着RW 输出段的(加载域只包含RO、RW 输出段,原因见后述)。
可执行镜像一开始一般是存储在系统的ROM 或FLASH 中,RO 段是只读的,在运行的时候我们不能改变它,所以RO 段在运行的时候可以驻留在ROM 或FLASH 中,也可以拷贝到运行速度更快的RAM 中;RW 段在运行的时候,我们需要对其读写,在运行前这一段必须被拷贝至RAM 中;ZI 段为未初始化的全局变量段,只需要在程序运行之前建立ZI 并将其所在区域全部清零即可,因此镜像装载域不必包含ZI 输出段,但在运行域需要包含ZI,并且ZI 必须处于RAM。
通过以上说明,我们知道如果某个镜像只有RO 段的话,程序可以不必拷贝至RAM,但是如果程序包含RW 段的话,RW 段是必需要拷贝至RAM 中的,如果有必要的话还需在RAM 中创建ZI 段,并将其清零。为保证程序的正确执行,而进行必要的数据拷贝和清零,就是应用程序执行环境的初始化。

view plain copy
 
 print?

  1. ;一个arm 程序是由R0,RW,ZI 三个段组成。其中R0 为代码段,RW 是已经初始化的全局变量,ZI 是未  
  2. ;初始化的全局变量,启动代码要将RO段和RW段复制到RAM 中并将ZI 段清零。编译器使用下列变量  
  3. ;来记录各段的起始地址和结束地址。这些标号的值是通过编译器的设定来确定的如ADS中对ro-base 和  
  4. ;rw-base 的设定。  
  5. IMPORT  |Image$RO$Base| ; Base of ROM code  
  6. IMPORT  |Image$RO$Limit|  ; End of ROM code (=start of ROM data)  
  7. IMPORT  |Image$RW$Base|   ; Base of RAM to initialise  
  8. IMPORT  |Image$ZI$Base|   ; Base and limit of area  
  9. IMPORT  |Image$ZI$Limit|  ; to zero initialise  
  10.   
  11.   
  12. ;===========================================================  
  13.       
  14.     ldr r0, =BWSCON  
  15.     ldr r0, [r0]  
  16.     ands    r0, r0, #6  ;通过判断OM[1:0] != 0, 得知是NOR FLash boot  
  17.     bne copy_proc_beg   ;不用读取 nand flash  
  18.     adr r0, ResetEntry  ;OM[1:0] == 0, 从NAND FLash 启动  
  19.     cmp r0, #0      ;再比较入口是否为0地址处,如果不是则用了仿真器  
  20.     bne copy_proc_beg   ;用仿真器的情况也不要用 nand flash启动  
  21.     ;nop  
  22. ;===========================================================  
  23. nand_boot_beg  ;这一段代码完成从NAND读代码到RAM  
  24.     [ {TRUE}  
  25.         bl RdNF2SDRAM  
  26.     ]  
  27.   
  28.   
  29.     ldr pc, =copy_proc_beg  ;此时的PC已经在0x30000000以后,是copy_proc_beg连接时的地址  
  30. ;这个标号下面的代码完成的功能就是把nor flash 的内容拷贝到ram 当中。  
  31. ;===========================================================  
  32. copy_proc_beg  
  33.     adr r0, ResetEntry       ;装载地址,ResetEntry值->r0  
  34.     ldr r2, BaseOfROM        ;BaseOfROM值  
  35.     cmp r0, r2               ;比较RO,R2  
  36.     ldreq   r0, TopOfROM     ;如果相等的话(说明在内存中运行),TopOfROM->r0   当从Nand Flash中启动时r0=r2,当从Nor Flash启动时则不相等  
  37.     beq InitRam                  ;同时跳到InitRam     
  38. ;下面这个是针对代码在NOR FLASH时的拷贝方法  
  39. ;功能为把从ResetEntry起,TopOfROM-BaseOfROM大小的数据拷到BaseOfROM  
  40. ;TopOfROM和BaseOfROM为|Image$RO$Limit|和|Image$RO$Base|  
  41. ;|Image$RO$Limit|和|Image$RO$Base|由连接器生成为生成的代码的代码段运行时的起启和终止地址  
  42. ;BaseOfBSS和BaseOfZero为|Image$RW$Base|和|Image$ZI$Base|  
  43. ;|Image$RW$Base|和|Image$ZI$Base|也是由连接器生成,两者之间就是初始化数据的存放地放  
  44.     ldr r3, TopOfROM  
  45. 0     
  46.     ldmia   r0!, {r4-r7}  
  47.     stmia   r2!, {r4-r7}  
  48.     cmp r2, r3  
  49.     bcc %B0  
  50.       
  51.     sub r2, r2, r3  ;这两句代码是修正字非对齐的情况,因为是按4个字节拷贝的,但RO段大小不一定是4个字节对齐的  
  52.     sub r0, r0, r2                
  53.           
  54. InitRam   
  55.     ldr r2, BaseOfBSS  
  56.     ldr r3, BaseOfZero    
  57. 0  
  58.     cmp r2, r3  
  59.     ldrcc   r1, [r0], #4  
  60.     strcc   r1, [r2], #4  
  61.     bcc %B0 ;这一段是对ResetEntry 里面定义好的数据拷贝到RW 段。  
  62.   
  63.   
  64.     mov r0, #0  
  65.     ldr r3, EndOfBSS  
  66. 1     
  67.     cmp r2, r3  
  68.     strcc   r0, [r2], #4  
  69.     bcc %B1    ;初始化ZI段  
  70.       
  71.     ldr pc, =%F2        ;goto compiler address  
  72. 2  
  73.       
  74. ;   [ CLKDIV_VAL>1       ; means Fclk:Hclk is not 1:1.  
  75. ;   bl  MMU_SetAsyncBusMode  
  76. ;   |  
  77. ;   bl MMU_SetFastBusMode   ; default value.  
  78. ;   ]  
  79.   
  80.   
  81.     [ :LNOT:THUMBCODE  
  82.         bl  Main    ;不要用main()因为main()是ADS默认入口,编译器会添加其他代码  
  83.         b   .      ;跳转到Main不成功则挂起  
  84.     ]  
  85.   
  86.   
  87.     [ THUMBCODE  ;for start-up code for Thumb mode  
  88.         orr lr,pc,#1  
  89.         bx  lr  
  90.         CODE16  
  91.         bl  Main    ;Do not use main() because ......  
  92.         b   .  
  93.         CODE32  
  94.     ]  
  95.   
  96.   
  97. BaseOfROM   DCD |Image$RO$Base|  
  98. TopOfROM    DCD |Image$RO$Limit|  
  99. BaseOfBSS   DCD |Image$RW$Base|  
  100. BaseOfZero  DCD |Image$ZI$Base|  
  101. EndOfBSS    DCD |Image$ZI$Limit|  

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 离子检测器电路分析

  • 非常简单的150W功放电路图

  • 如何使用LED驱动器LM3915制作振动计

  • 分享一个电网倾角计电路

  • 使用NE555和磁簧开关的橱柜照明电路

  • 电谐波图形均衡器示意图

    相关电子头条文章