S3C2440啓動代碼中應用程序執行環境的初始化

S3C2440啓動代碼中應用程序執行環境的初始化

一、基礎知識

          我們編寫的源文件(.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 段,並將其清零。爲保證程序的正確執行,而進行必要的數據拷貝和清零,就是應用程序執行環境的初始化。

二、S3C2440啓動的基本原理

Nand Flash啓動

        當S3C2440 開發板採用的是Nand Flash 啓動,鏡像一開始是存儲在Nand Flash 中,而Nand Flash只能作爲存儲程序和數據之用,無法在其中運行程序,所以S3C2440 開發板啓動代碼中應用環境初始化這一步和上述步驟稍有不同。S3C2440 鏡像文件加載和運行時的地址映射關係如下圖所示:


0_1329566681JwkW.png 




        S3C2440 沒有上電之前映像文件存儲在Nand Flash 中,Nand Flash 由專門的控制器控制,不佔用存儲器BANK。當開發板上電時,Nand Flash 的前4K 被複制到S3C2440 芯片內部的一塊容量爲4K 的SRAM(被稱爲“Steppingstone”),然後這塊SRAM 被映射到地址0x00000000 處,程序從此處開始運行。因爲Nand Flash 中不能運行程序,所以在這4K 的代碼中必須包含一段代碼將Nand Flash 中的程序拷貝至S3C2440 的SDRAM 中(0x30000000 開始)。應用環境初始化應該包含這段代碼。

        Nand Flash 中的映像文件被拷貝至從0x30000000 開始的SDRAM,這時候映像文件還沒有真正被執行,此時是加載狀態,加載域如上圖所示,包括所有RO 屬性的輸出段和RW 屬性的輸出段,ZI 屬性的輸出段此時還不存在。在映像文件運行時,會生成3 個運行域,如上圖所示,RO 和RW 屬性的運行域的起始地址和加載時是相同的,所以在應用程序執行環境初始化中不需要對其進行拷貝,ZI 運行域則需要在映像開始被執行前建立並被初始化爲0,所以應用程序執行環境初始化中也要包含這類代碼。

Nor Flash啓動

當S3C2440採用Nor Flash啓動時,代碼可以在上面直接運行。但爲了運行的效率,還是把程序拷貝到SDRRAM中運行。加載時地址關係和運行時地址關係和Nand Flash的基本相似。Nand Flash啓動時,會將RO段和RW段同時拷貝到SDRAM中,然後再建立ZI段。從Nor Flash啓動時是先拷貝RO段,然後再拷貝RW段,最後建立ZI段。

三、相關啓動代碼分析




[plain] view plaincopy
  1. 01.;一個arm 程序是由R0,RW,ZI 三個段組成。其中R0 爲代碼段,RW 是已經初始化的全局變量,ZI 是未  
  2. 02.;初始化的全局變量,啓動代碼要將RO段和RW段複製到RAM 中並將ZI 段清零。編譯器使用下列變量  
  3. 03.;來記錄各段的起始地址和結束地址。這些標號的值是通過編譯器的設定來確定的如ADS中對ro-base 和  
  4. 04.;rw-base 的設定。  
  5. 05.IMPORT  |Image$RO$Base| ; Base of ROM code  
  6. 06.IMPORT  |Image$RO$Limit|  ; End of ROM code (=start of ROM data)  
  7. 07.IMPORT  |Image$RW$Base|   ; Base of RAM to initialise  
  8. 08.IMPORT  |Image$ZI$Base|   ; Base and limit of area  
  9. 09.IMPORT  |Image$ZI$Limit|  ; to zero initialise  
  10. 10.  
  11. 11.  
  12. 12.;===========================================================  
  13. 13.      
  14. 14.    ldr r0, =BWSCON  
  15. 15.    ldr r0, [r0]  
  16. 16.    ands    r0, r0, #6  ;通過判斷OM[1:0] != 0, 得知是NOR FLash boot  
  17. 17.    bne copy_proc_beg   ;不用讀取 nand flash  
  18. 18.    adr r0, ResetEntry  ;OM[1:0] == 0, 從NAND FLash 啓動  
  19. 19.    cmp r0, #0      ;再比較入口是否爲0地址處,如果不是則用了仿真器  
  20. 20.    bne copy_proc_beg   ;用仿真器的情況也不要用 nand flash啓動  
  21. 21.    ;nop  
  22. 22.;===========================================================  
  23. 23.nand_boot_beg  ;這一段代碼完成從NAND讀代碼到RAM  
  24. 24.    [ {TRUE}  
  25. 25.        bl RdNF2SDRAM  
  26. 26.    ]  
  27. 27.  
  28. 28.  
  29. 29.    ldr pc, =copy_proc_beg  ;此時的PC已經在0x30000000以後,是copy_proc_beg連接時的地址  
  30. 30.;這個標號下面的代碼完成的功能就是把nor flash 的內容拷貝到ram 當中。  
  31. 31.;===========================================================  
  32. 32.copy_proc_beg  
  33. 33.    adr r0, ResetEntry       ;裝載地址,ResetEntry值->r0  
  34. 34.    ldr r2, BaseOfROM        ;BaseOfROM值  
  35. 35.    cmp r0, r2               ;比較RO,R2  
  36. 36.    ldreq   r0, TopOfROM     ;如果相等的話(說明在內存中運行),TopOfROM->r0   當從Nand Flash中啓動時r0=r2,當從Nor Flash啓動時則不相等  
  37. 37.    beq InitRam                  ;同時跳到InitRam     
  38. 38.;下面這個是針對代碼在NOR FLASH時的拷貝方法  
  39. 39.;功能爲把從ResetEntry起,TopOfROM-BaseOfROM大小的數據拷到BaseOfROM  
  40. 40.;TopOfROM和BaseOfROM爲|Image$RO$Limit|和|Image$RO$Base|  
  41. 41.;|Image$RO$Limit|和|Image$RO$Base|由連接器生成爲生成的代碼的代碼段運行時的起啓和終止地址  
  42. 42.;BaseOfBSS和BaseOfZero爲|Image$RW$Base|和|Image$ZI$Base|  
  43. 43.;|Image$RW$Base|和|Image$ZI$Base|也是由連接器生成,兩者之間就是初始化數據的存放地放  
  44. 44.    ldr r3, TopOfROM  
  45. 45.0     
  46. 46.    ldmia   r0!, {r4-r7}  
  47. 47.    stmia   r2!, {r4-r7}  
  48. 48.    cmp r2, r3  
  49. 49.    bcc %B0  
  50. 50.      
  51. 51.    sub r2, r2, r3  ;這兩句代碼是修正字非對齊的情況,因爲是按4個字節拷貝的,但RO段大小不一定是4個字節對齊的  
  52. 52.    sub r0, r0, r2                
  53. 53.          
  54. 54.InitRam   
  55. 55.    ldr r2, BaseOfBSS  
  56. 56.    ldr r3, BaseOfZero    
  57. 57.0  
  58. 58.    cmp r2, r3  
  59. 59.    ldrcc   r1, [r0], #4  
  60. 60.    strcc   r1, [r2], #4  
  61. 61.    bcc %B0 ;這一段是對ResetEntry 裏面定義好的數據拷貝到RW 段。  
  62. 62.  
  63. 63.  
  64. 64.    mov r0, #0  
  65. 65.    ldr r3, EndOfBSS  
  66. 66.1     
  67. 67.    cmp r2, r3  
  68. 68.    strcc   r0, [r2], #4  
  69. 69.    bcc %B1    ;初始化ZI段  
  70. 70.      
  71. 71.    ldr pc, =%F2        ;goto compiler address  
  72. 72.2  
  73. 73.      
  74. 74.;   [ CLKDIV_VAL>1       ; means Fclk:Hclk is not 1:1.  
  75. 75.;   bl  MMU_SetAsyncBusMode  
  76. 76.;   |  
  77. 77.;   bl MMU_SetFastBusMode   ; default value.  
  78. 78.;   ]  
  79. 79.  
  80. 80.  
  81. 81.    [ :LNOT:THUMBCODE  
  82. 82.        bl  Main    ;不要用main()因爲main()是ADS默認入口,編譯器會添加其他代碼  
  83. 83.        b   .      ;跳轉到Main不成功則掛起  
  84. 84.    ]  
  85. 85.  
  86. 86.  
  87. 87.    [ THUMBCODE  ;for start-up code for Thumb mode  
  88. 88.        orr lr,pc,#1  
  89. 89.        bx  lr  
  90. 90.        CODE16  
  91. 91.        bl  Main    ;Do not use main() because ......  
  92. 92.        b   .  
  93. 93.        CODE32  
  94. 94.    ]  
  95. 95.  
  96. 96.  
  97. 97.BaseOfROM   DCD |Image$RO$Base|  
  98. 98.TopOfROM    DCD |Image$RO$Limit|  
  99. 99.BaseOfBSS   DCD |Image$RW$Base|  
  100. 100.BaseOfZero  DCD |Image$ZI$Base|  
  101. 101.EndOfBSS    DCD |Image$ZI$Limit|  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章