<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > bootloader和RO,RW,ZI在ARMC語言中

          bootloader和RO,RW,ZI在ARMC語言中

          作者: 時間:2016-11-10 來源:網絡 收藏
          Bootloader即引導加載程序,是系統(tǒng)加電后運行的第一段軟件代碼。簡單的說它們都是bootloader,所完成的任務也大同小異。

          熟悉x86體系結構的朋友肯定知道,x86平臺上bootloader是由BIOS和位于硬盤MBR中的OS Bootloader(比如Lilo和Grub)組成的。BIOS完成硬件的檢測和資源的分配后,將硬盤MBR中的bootloader讀到系統(tǒng)RAM中,之后此bootloader就會開始進行主導,將內核搬到內存中以及進行一些必要的初始化工作,之后跳到內核的入口地址來執(zhí)行,這樣內核就開始啟動,也就是系統(tǒng)就啟動起來了。
          這里不得不插入一個話題,通過上面的介紹,細心的朋友就會產生一個疑問:為什么要有bootloader?既然bootloader只是作硬件的初始化并將內核引導起來,那為什么不直接將這段代碼加到內核中,直接啟動內核就完成所有的工作?實際上要將bootloader與內核整合在一起是完全可以做到的,但是如果這樣作的話,內核就會失去他的通用性和靈活性,并且將bootloader與內核分開會更有利于開發(fā)和管理,將啟動過程中與平臺硬件相關的代碼集合成bootloader,內核就可以集中處理那些平臺通用的部分了(當然實際上并沒有這么嚴格的劃分,內核中還是會有一些平臺相關的代碼,不過已經算是比較通用的了)。
          =============================================================================================================================================================================
          一個ARM程序包含3部分:RO,RWZI
          RO是程序中的指令和常量;RO就是readonly,
          RW是程序中的已初始化變量; RW就是read/write,
          (2) ARM映像文件的組成
          所謂ARM映像文件就是指燒錄到ROM中的bin文件,也成為image文件。以下用Image文件來稱呼它。Image文件包含了RO和RW數(shù)據。之所以Image文件不包含ZI數(shù)據,是因為ZI數(shù)據都是0,沒必要包含,只要程序運行之前將ZI數(shù)據所在的區(qū)域一律清零即可。包含進去反而浪費存儲空間。
          Q:為什么Image中必須包含RO和RW?
          A:因為RO中的指令和常量以及RW中初始化過的變量是不能像ZI那樣“無中生有”的。
          實際上,ROM中的指令至少應該有這樣的功能:
          1. 將RW從ROM中搬到RAM中,因為RW是變量,變量不能存在ROM中。
          2. 將ZI所在的RAM區(qū)域全部清零,因為ZI區(qū)域并不在Image中,所以需要程序根據編譯器給出的ZI地址及大小來將相應得RAM區(qū)域清零。ZI中也是變量,同理:變量不能存在ROM中.在程序運行的最初階段,RO中的指令完成了這兩項工作后C程序才能正常訪問變量。否則只能運行不含變量的代碼。
          下面我將給出幾個例子,最直觀的來說明RO,RW,ZI在C中是什么意思。
          1; RO
          看下面兩段程序,他們之間差了一條語句,這條語句就是聲明一個字符常量。因此按照我們之前說的,他們之間應該只會在RO數(shù)據中相差一個字節(jié)(字符常量為1字節(jié))。
          Prog1:
          #include
          void main(void)
          {
          ;
          }

          Prog2:
          #include
          const char a = 5;
          void main(void)
          {
          ;
          }
          Prog1編譯出來后的信息如下:
          ================================================================================
          Code RO Data RW Data ZI Data Debug
          948 60 0 96 0 Grand Totals
          ================================================================================
          Total RO Size(Code + RO Data) 1008 ( 0.98kB)
          Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
          Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
          ================================================================================
          Prog2編譯出來后的信息如下:
          ================================================================================
          Code RO Data RW Data ZI Data Debug
          948 61 0 96 0 Grand Totals
          ================================================================================
          Total RO Size(Code + RO Data) 1009 ( 0.99kB)
          Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
          Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)
          ================================================================================
          以上兩個程序編譯出來后的信息可以看出:
          Prog1和Prog2的RO包含了Code和RO Data兩類數(shù)據。他們的唯一區(qū)別就是Prog2的RO Data比Prog1多了1個字節(jié)。這正和之前的推測一致。如果增加的是一條指令而不是一個常量,則結果應該是Code數(shù)據大小有差別。
          2; RW
          同樣再看兩個程序,他們之間只相差一個“已初始化的變量”,按照之前所講的,已初始化的變量應該是算在RW中的,所以兩個程序之間應該是RW大小有區(qū)別。
          Prog3:
          #include
          void main(void)
          {
          ;
          }
          Prog4:
          #include
          char a = 5;
          void main(void)
          {
          ;
          }
          Prog3編譯出來后的信息如下:
          ================================================================================
          Code RO Data RW Data ZI Data Debug
          948 60 0 96 0 Grand Totals
          ================================================================================
          Total RO Size(Code + RO Data) 1008 ( 0.98kB)
          Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
          Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
          ================================================================================
          Prog4編譯出來后的信息如下:
          ================================================================================
          Code RO Data RW Data ZI Data Debug
          948 60 1 96 0 Grand Totals
          ================================================================================
          Total RO Size(Code + RO Data) 1008 ( 0.98kB)
          Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)
          Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)
          ================================================================================
          可以看出Prog3和Prog4之間確實只有RW Data之間相差了1個字節(jié),這個字節(jié)正是被初始化過的一個字符型變量“a”所引起的。
          再看兩個程序,他們之間的差別是一個未初始化的變量“a”,從之前的了解中,應該可以推測,這兩個程序之間應該只有ZI大小有差別。
          Prog3:
          #include
          void main(void)
          {
          ;
          }
          Prog4:
          #include
          char a;
          void main(void)
          {
          ;
          }
          Prog3編譯出來后的信息如下:
          ================================================================================
          Code RO Data RW Data ZI Data Debug
          948 60 0 96 0 Grand Totals
          ================================================================================
          Total RO Size(Code + RO Data) 1008 ( 0.98kB)
          Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
          Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
          ================================================================================
          Prog4編譯出來后的信息如下:
          ================================================================================
          Code RO Data RW Data ZI Data Debug
          948 60 0 97 0 Grand Totals
          ================================================================================
          Total RO Size(Code + RO Data) 1008 ( 0.98kB)
          Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)
          Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
          ================================================================================
          編譯的結果完全符合推測,只有ZI數(shù)據相差了1個字節(jié)。這個字節(jié)正是未初始化的一個字符型變量“a”所引起的。
          注意:如果一個變量被初始化為0,則該變量的處理方法與未初始化華變量一樣放在ZI區(qū)域。
          即:ARM C程序中,所有的未初始化變量都會被自動初始化為0。
          總結: 1; C中的指令以及常量被編譯后是RO類型數(shù)據。
          2; C中的未被初始化或初始化為0的變量編譯后是ZI類型數(shù)據。
          3; C中的已被初始化成非0值的變量編譯后市RW類型數(shù)據。
          RAM主要指:PSRAM,SDRAM,SRAM,DDRAM
          (5) Image$$??$$Limit 的含義
          =0x0c100000+Tatal RO size+1
          = 0x0c200000+0x37(4的倍數(shù),0到55,共56個單元)

          本文引用地址:http://www.ex-cimer.com/article/201611/317191.htm

          vivi是mizi開發(fā)的用于s3c241x/s3c244x 的linux bootloader,友善之臂移植了USB 下載功能后就成了現(xiàn)在看到的supervivi;u-boot是一個廣泛用于ARM平臺的bootloader, 目前也支持s3c241x/s3c244x,可以用來啟動Linux;Eboot是WinCE平臺下的bootloader。uboot就是通過usb來下載os image文件的bootloader; eboot就是通過ethernet下載os image的bootloader。

          嵌入式平臺上就跟x86不一樣了,但是很類似,而且因為不同的平臺架構本身的特點,每種平臺對應的bootloader做得事情會有所不同,相對x86平臺,一般不會有bios(但是這些都不是絕對的,有一些平臺也會有內嵌類似bios的啟動程序),整個系統(tǒng)的引導加載都由存放在flash,rom等存儲設備特定位置的bootloader來完成。如arm平臺中的2410,2440,bootloader存在在flash中的0x0的地方,板子加電后,系統(tǒng)會將bootloader的最前面的4k代碼通過硬件邏輯自動的裝載到SRAM中,之后從SRAM中的0開始執(zhí)行,在這4k的程序中會完成基本的硬件的初始化,將完整的bootloader搬到內存中,并跳轉到ram中的bootloader來進行繼續(xù)執(zhí)行。

          回到之前所說的,bootloader啟動起來之后,通常會有兩種操作模式:

          啟動加載模式就是一上電,bootloader進行相關的初始化之后就馬上把內核啟動起來,注意關鍵的地方在整個過程中沒有用戶的參與,這種其實也就是bootloader的默認處理,一般的產品設計ok進行最后的發(fā)布時,就會處于此種狀態(tài)。

          下載模這種模式,大家肯定非常熟悉,就是大家在進行開發(fā)的時候所處的環(huán)境,我們經常使用的tftp, erase, cp.b等命令將相關的bin,img文件燒到板子上,這種情況下其實就是處于bootloader的執(zhí)行環(huán)境下,所以一定意義來說,大多的bootloader其實就是一個嵌入式操作系統(tǒng),只是它的功能不強,不像linux的結構那么復雜,而且也不會支持多進程多線程處理。

          bootloader種類和分類

          這里的分類實際上是依據上面的bootloader的操作模式來進行劃分的,根據一個系統(tǒng)是否支持上面的下載模式我們這里將bootloader劃分為bootloader和monitor(這不是我劃分的,恩,是從別人的文章中引述過來的,不過我覺得他說的很有道理),這里”bootloader”是指只是引導設備與執(zhí)行主程序的固件,而”monitor”是指不僅擁有bootloader功能的,還能夠進入下載模式的固件。

          (1)、ARM程序的組成

          此處所說的“ARM程序”是指在ARM系統(tǒng)中正在執(zhí)行的程序,而非保存在ROM中的bin映像(image)文件,這一點清注意區(qū)別。

          ZI是程序中的未初始化的變量;ZI就是zero;

          (3)ARM程序的執(zhí)行過程

          從以上兩點可以知道,燒錄到ROM中的image文件與實際運行時的ARM程序之間并不是完全一樣的。因此就有必要了解ARM程序是如何從ROM中的image到達實際運行狀態(tài)的。

          3; ZI

          (4) ROM主要指:NAND Flash,Nor Flash

          對于剛學習ARM的人來說,如果分析它的啟動代碼,往往不明白下面幾個變量的含義:|Image$$RO$$Limit|、|Image$$RW$$Base|、|Image$$ZI$$Base|。

          當把程序編寫好以后,就要進行編譯和鏈接了,在ADS1.2中選擇MAKE按鈕,會出現(xiàn)一個Errors and Warnings的對話框,在該欄中顯示編譯和鏈接的結果,如果沒有錯誤,在文件的最后應該能看到Image component sizes,后面緊跟的依次是Code,RO Data ,RW Data ,ZI Data ,Debug 各個項目的字節(jié)數(shù),最后會有他們的一個統(tǒng)計數(shù)據:

          Code 163632 ,RO Data 20939 ,RW Data 53 ,ZI Data 17028

          Tatal RO size (Code+ RO Data) 184571 (180.25kB)

          Tatal RW size(RW Data+ ZI Data) 17081(16.68 kB)

          Tatal ROM size(Code+ RO Data+ RW Data) 184624(180.30 kB)

          后面的字節(jié)數(shù)是根據用戶不同的程序而來的,下面就以上面的數(shù)據為例來介紹那幾個變量的計算。

          在ADS的Debug Settings中有一欄是Linker/ARM Linker,在output選項中有一個RO base選項,

          假如RO base設置為0x0c100000,后面的RW base 設置為0x0c200000,然后在Options選項中有Image entry point ,是一個初始程序的入口地址,設置為0x0c100000 。

          有了上面這些信息我們就可以完全知道這幾個變量是怎么來的了:

          |Image$$RO$$Base| = Image entry point =RO base =0x0c100000 ;表示程序代碼存放的起始地址

          |Image$$RO$$Limit|=程序代碼起始地址+代碼長度+1

          = 0x0c100000 + 184571 + 1 = 0x0c100000 +0x2D0FB + 1

          = 0x0c12d0fc

          |Image$$RW$$Base| = 0x0c200000=RW base 地址指定

          |Image$$RW$$Limit| =|Image$$RW$$Base|+ RW Data 53

          =0x0c200037

          |Image$$ZI$$Base| = |Image$$RW$$Limit| + 1 =0x0c200038

          |Image$$ZI$$Limit| = |Image$$ZI$$Base| + ZI Data 17028

          =0x0c200038 + 0x4284

          =0x0c2042bc

          也可以由此計算:

          |Image$$ZI$$Limit| = |Image$$RW$$Base| +TatalRWsize(RWData+ZIData) 17081

          =0x0c200000+0x42b9+3(要滿足4的倍數(shù))

          =0x0c2042bc



          關鍵詞: bootloaderRORWZIAR

          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();