引用 ADS1.2下ARM映像文件
bin文件是真正的可執行文件,axf文件是ARM的調試文件,除了包含bin的內容之外,還附加了其他的調試信息,這些調試信息加在可執行的二進(jìn)制數據的前面,所以把axf文件寫(xiě)到ARM的指令執行地址(一般是0x0)將不能運行,因為在此地址前幾十個(gè)字節的數據不是可執行的二進(jìn)制數據,而是頭部的調試信息;而bin文件正是去掉了調試信息的可以執行的“精華”部分。
本文引用地址:http://dyxdggzs.com/article/201611/317261.htmARM映像文件的組成:ARM映像文件是一個(gè)層次性結構的文件,包括了域(region),輸出段(output section)和輸入段(input section)。一個(gè)映像文件由一個(gè)或者多個(gè)域組成;每個(gè)域最多由三個(gè)輸出段組成組成;每個(gè)輸出段又包含一個(gè)或者多個(gè)輸入段;各輸入端包含了目標文件中的代碼和數據。
相關(guān)術(shù)語(yǔ):
1。域 (region):一個(gè)映象文件由一個(gè)或多個(gè)域組成。反過(guò)來(lái)說(shuō)域是組成映象文件的最大的結構。所謂域,指的就是整個(gè)bin映像文件所處在的區域,它又分為加載域和運行域。加載域就是映像文件被靜態(tài)存放的工作區域,一般來(lái)說(shuō)flash里的整個(gè)bin文件所在的地址空間就是加載域,當然程序一般都不會(huì )放在flash里執行,一般都會(huì )搬到sdram里運行工作,它們在被搬到sdram里工作所處的地址空間就是運行域。一個(gè)域通常映射到一個(gè)物理存儲器上,如ROM和RAM等。
2。段(Section):一個(gè)域包含一個(gè)或多個(gè)輸出段,一個(gè)輸出段包含一個(gè)或多個(gè)輸入段。我們輸入的代碼,一般有代碼部分和數據部分,這就是所謂的輸入段,每個(gè)輸入段都有相應的屬性,可以為只讀(ro),可讀寫(xiě)的(rw)以及初始化成0的(zi)。
3。RO,RW,ZI:輸入段中包含4類(lèi)內容:代碼、已經(jīng)初始化的數據、未經(jīng)初始化的存儲區域、內容初始化為0的存儲區域。每個(gè)輸入段有相應的屬性,可以為只讀(RO)、可讀寫(xiě)(RW)以及初始化為0的(ZI)。ARM連接器根據各輸入段的屬性將這些輸入段分組,再組成對應屬性的輸出段。對于加載域中的輸出段,一般來(lái)說(shuō)ro段后面緊跟著(zhù)rw段,rw段后面緊跟著(zhù)zi段。在運行域中這些輸出段并不連續,但rw和zi一定是連著(zhù)的。zi段和rw段中的數據其實(shí)可以是rw屬性。
注:(1); C中的指令以及常量被編譯后是RO類(lèi)型數據。
(2); C中的未被初始化或初始化為0的變量編譯后是ZI類(lèi)型數據。
(3); C中的已被初始化成非0值的變量編譯后市RW類(lèi)型數據。
4。加載時(shí)地址:是映象文件位于存儲器(還沒(méi)有運行,一般在ROM中)時(shí)的地址
5。運行時(shí)地址:是映象文件運行時(shí)的地址。
通常一個(gè)映像文件中包含若干個(gè)域,各個(gè)域又包含若干的輸出段。ARM連接器就需要知道如下信息以決定生成相應的映像文件。燒錄到ROM中的image文件與實(shí)際運行時(shí)的ARM程序之間并不是完全一樣的。因此就有必要了解ARM程序是如何從ROM中的image到達實(shí)際運行狀態(tài)的。
*分組信息 :決定如何各將輸入段組織成相應的輸出段和域。
*定位信息 :決定各個(gè)域在存儲器空間中的起始地址。
根據映像文件中地址映射的復雜程度有兩種方法告訴ARM連接器這些相關(guān)的信息。
(1)當映像文件中最多包含兩個(gè)域,每個(gè)域最多有三個(gè)輸出段時(shí),可以使用連接器選項告訴連接器相關(guān)的地址映射關(guān)系。選項有-ropi,-rwpi,-ro_base,-rw_base,-split等。
(2)當映像文件地址映射關(guān)系更復雜時(shí),可以使用一個(gè)配置文件(分散加載文件)告訴連接器相關(guān)的地址映射關(guān)系。ARM映像文件
數據移動(dòng):
上面已經(jīng)提到了RW段加載地址一般在ROM中,運行時(shí)需要被搬運到RAM中。加載時(shí)狀態(tài)的映象文件中的RO、RW和ZI的地址都是臨時(shí)的,他們在運行時(shí)要被BootLoader程序搬運到真正的運行時(shí)地址。這個(gè)地址是連接時(shí)設置的地址。這個(gè)問(wèn)題很重要,如果在編譯前沒(méi)有正確的設置運行時(shí)地址,那么程序就不能被搬運到正確的RAM地址中運行。
了解了以上內容,那么就可以打開(kāi)ADS1.2來(lái)看一下具體的設置。
打開(kāi)ADS的一個(gè)工程后,點(diǎn)擊如下圖所示的Debug Settings按鈕打開(kāi)對話(huà)框。打開(kāi)Target Settings對話(huà)框后,在左邊列表中選擇Linker選項。點(diǎn)擊它下面的的ARM Linker。然后在右面的選項卡選擇Output選項卡。如下圖所示。
看看ADS 開(kāi)發(fā)文檔ARMDeveloper suite 1.2 的ADS_CodeWarriorIDEGuide.pdf 怎么說(shuō)的
RO Base This text field sets both the load address and execution address of the region containing the RO
section. If you do not enter a value, the value defaults to 0x8000.
意思是,這個(gè)文本框設置加載時(shí)地址和運行時(shí)地址。如果沒(méi)有設置值,默認時(shí)0x8000。這個(gè)值將會(huì )對應ADS的預定義變量Image$$RO$$Base,指定了RO的base。這個(gè)變量可以被初始化程序IMP
根據上面的1,2可知,如果要燒寫(xiě)FLASH 那么RO Base 應該設置成ARM片選的FLASH 的首地址;如果要調試那么RO Base要設置成RAM地址。
RW Base 這個(gè)文本框設定包含RW和ZI輸出段的運行時(shí)域地址。如果你在這里輸入一個(gè)值,連接器創(chuàng )建一個(gè)包含兩個(gè)運行時(shí)域的映象,這兩個(gè)域是:
包含RO輸出段的運行時(shí)域
包含RW和ZI輸出段的運行時(shí)域
如果你輸入了RW Base值并且選擇了Split image選項,連接器創(chuàng )建的映象文件分別包含RW輸出段和ZI輸出段的裝載時(shí)地址和運行時(shí)地址,并都由你輸入的RW Base值指定。
對于簡(jiǎn)單連接方式,當沒(méi)有輸入RW Base值時(shí),映象文件包含一個(gè)加載時(shí)域和一個(gè)運行時(shí)域。這時(shí),RO輸出段、RW輸出段、ZI輸出段都包含在一個(gè)域中。當輸入RW Base值時(shí),映象文件包含兩個(gè)運行時(shí)域,一個(gè)包含RO輸出段,一個(gè)包含RW輸出段和ZI輸出段。當指定了-split選項時(shí),映象文件又多包含兩個(gè)加載時(shí)域,一個(gè)包含RO輸出段,一個(gè)包含RW輸出段和ZI輸出段。
簡(jiǎn)單的初始化用戶(hù)程序的執行環(huán)境
ARM映像文件一開(kāi)始總是存儲在ROM/Flash里面的,其RO部分既可以在ROM/Flash里面執行,也可以轉移到速度更快的RAM中執行;而RW和ZI這兩部分是必須轉移到可寫(xiě)的RAM里去,其實(shí)RW包括ZI區域,ZI區域放的是未賦值的全局變量,RW 區域放的是已賦值(賦0除外)的全局變量。所謂應用程序執行環(huán)境的初始化,就是完成必要的從ROM到RAM的數據傳輸和內容清零。
先介紹幾個(gè)必要的符號,編譯器使用下列符號來(lái)記錄各段的起始和結束地址:
|Image$$RO$$Base| :RO段起始地址
|Image$$RO$$Limit| :RO段結束地址加1?。ㄔ诩虞d域中,是RW的起始地址)
|Image$$RW$$Base| :RW段起始地址?。ㄔ谶\行域中即運行的時(shí)候,是RW的起始地址)
|Image$$RW$$Limit| :ZI段結束地址加1
|Image$$ZI$$Base| :ZI段起始地址
|Image$$ZI$$Limit| :ZI段結束地址加1
這些符號的值是根據鏈接器中設置的中ro-base和rw-base的設置來(lái)計算的。 由于rw和zi相連,|Image$$ZI$$Base|就等于|Image$$RW$$Limit| .其它的值都是編譯器自動(dòng)計算出來(lái)的。我們還可以通過(guò)scatter文件更詳細得指定各個(gè)輸出段的工作地址。
初始化用戶(hù)執行環(huán)境主要是把ro、rw、zi三段拷貝到指定的位置。
下面的程序是rw、zi段在運行域中的搬運過(guò)程:
;Copy and paste RW da
ldr r0, =|Image$$RO$$Limit| /*取RO區末地址后面的地址,即RW數據源的起始地址*/
ldr r1, =|Image$$RW$$Base|/*取RW區在RAM里的執行區起始地址,即編譯器選項RW_Base指定的地址*/
ldr r3, =|Image$$ZI$$Base|/*取ZI區在RAM里面的起始地址*/
;Zero init base => top of initialised da
cmp r0, r1 /* 比較ROM區中數據段首地址和RAM區中RW段目標首地址*/
beq %F2 /*相等代表當前已經(jīng)是在RAM中運行*/(F表示after,B表示before,r0與r1相等則轉跳)
/*B %F2表向前跳到標號為2的Lable處*/
1
cmp r1, r3 /*不相等則和RAM區中ZI段的目標地址比較*/
ldrcc r2, [r0], #4/*如果r1
ldr r1, =|Image$$ZI$$Limit| /* 取ZI段的結束地址 */
mov r2, #0 /*將r2賦值為0*/
3
cmp r3, r1 ; Zero init
strcc r2, [r3], #4 /*如果r3
評論