新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 引用 ADS1.2下ARM映像文件

引用 ADS1.2下ARM映像文件

作者: 時(shí)間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
ARM中的各種源文件(包括匯編文件,C語言程序及C++程序等)經(jīng)過ARM編譯器編譯后生成ELF(Executable and linking format)格式的目標(biāo)文件。這些目標(biāo)文件和相應(yīng)的C/C++運(yùn)行 時(shí)用到的庫經(jīng)過ARM連接器處理后,生成ELF格式的映像文件(image),這種ELF格式的映像文件是一種可執(zhí)行文件,可被寫入嵌入式設(shè)備的ROM 中。

bin文件是真正的可執(zhí)行文件,axf文件是ARM的調(diào)試文件,除了包含bin的內(nèi)容之外,還附加了其他的調(diào)試信息,這些調(diào)試信息加在可執(zhí)行的二進(jìn)制數(shù)據(jù)的前面,所以把a(bǔ)xf文件寫到ARM的指令執(zhí)行地址(一般是0x0)將不能運(yùn)行,因?yàn)樵诖说刂非皫资畟€(gè)字節(jié)的數(shù)據(jù)不是可執(zhí)行的二進(jìn)制數(shù)據(jù),而是頭部的調(diào)試信息;而bin文件正是去掉了調(diào)試信息的可以執(zhí)行的“精華”部分。

本文引用地址:http://butianyuan.cn/article/201611/317261.htm

ARM映像文件的組成:ARM映像文件是一個(gè)層次性結(jié)構(gòu)的文件,包括了域(region),輸出段(output section)和輸入段(input section)。一個(gè)映像文件由一個(gè)或者多個(gè)域組成;每個(gè)域最多由三個(gè)輸出段組成組成;每個(gè)輸出段又包含一個(gè)或者多個(gè)輸入段;各輸入端包含了目標(biāo)文件中的代碼和數(shù)據(jù)。

相關(guān)術(shù)語:

1。域 (region):一個(gè)映象文件由一個(gè)或多個(gè)域組成。反過來說域是組成映象文件的最大的結(jié)構(gòu)。所謂域,指的就是整個(gè)bin映像文件所處在的區(qū)域,它又分為加載域和運(yùn)行域。加載域就是映像文件被靜態(tài)存放的工作區(qū)域,一般來說flash里的整個(gè)bin文件所在的地址空間就是加載域,當(dāng)然程序一般都不會放在flash里執(zhí)行,一般都會搬到sdram里運(yùn)行工作,它們在被搬到sdram里工作所處的地址空間就是運(yùn)行域。一個(gè)域通常映射到一個(gè)物理存儲器上,如ROM和RAM等。

2。段(Section):一個(gè)域包含一個(gè)或多個(gè)輸出段,一個(gè)輸出段包含一個(gè)或多個(gè)輸入段。我們輸入的代碼,一般有代碼部分和數(shù)據(jù)部分,這就是所謂的輸入段,每個(gè)輸入段都有相應(yīng)的屬性,可以為只讀(ro),可讀寫的(rw)以及初始化成0的(zi)。

3。RO,RW,ZI:輸入段中包含4類內(nèi)容:代碼、已經(jīng)初始化的數(shù)據(jù)、未經(jīng)初始化的存儲區(qū)域、內(nèi)容初始化為0的存儲區(qū)域。每個(gè)輸入段有相應(yīng)的屬性,可以為只讀(RO)、可讀寫(RW)以及初始化為0的(ZI)。ARM連接器根據(jù)各輸入段的屬性將這些輸入段分組,再組成對應(yīng)屬性的輸出段。對于加載域中的輸出段,一般來說ro段后面緊跟著rw段,rw段后面緊跟著zi段。在運(yùn)行域中這些輸出段并不連續(xù),但rw和zi一定是連著的。zi段和rw段中的數(shù)據(jù)其實(shí)可以是rw屬性。

注:(1); C中的指令以及常量被編譯后是RO類型數(shù)據(jù)。

(2); C中的未被初始化或初始化為0的變量編譯后是ZI類型數(shù)據(jù)。

(3); C中的已被初始化成非0值的變量編譯后市RW類型數(shù)據(jù)。

4。加載時(shí)地址:是映象文件位于存儲器(還沒有運(yùn)行,一般在ROM中)時(shí)的地址

5。運(yùn)行時(shí)地址:是映象文件運(yùn)行時(shí)的地址。

通常一個(gè)映像文件中包含若干個(gè)域,各個(gè)域又包含若干的輸出段。ARM連接器就需要知道如下信息以決定生成相應(yīng)的映像文件。燒錄到ROM中的image文件與實(shí)際運(yùn)行時(shí)的ARM程序之間并不是完全一樣的。因此就有必要了解ARM程序是如何從ROM中的image到達(dá)實(shí)際運(yùn)行狀態(tài)的。

*分組信息 :決定如何各將輸入段組織成相應(yīng)的輸出段和域。
*定位信息 :決定各個(gè)域在存儲器空間中的起始地址。

根據(jù)映像文件中地址映射的復(fù)雜程度有兩種方法告訴ARM連接器這些相關(guān)的信息。

(1)當(dāng)映像文件中最多包含兩個(gè)域,每個(gè)域最多有三個(gè)輸出段時(shí),可以使用連接器選項(xiàng)告訴連接器相關(guān)的地址映射關(guān)系。選項(xiàng)有-ropi,-rwpi,-ro_base,-rw_base,-split等。

(2)當(dāng)映像文件地址映射關(guān)系更復(fù)雜時(shí),可以使用一個(gè)配置文件(分散加載文件)告訴連接器相關(guān)的地址映射關(guān)系。ARM映像文件

數(shù)據(jù)移動:

上面已經(jīng)提到了RW段加載地址一般在ROM中,運(yùn)行時(shí)需要被搬運(yùn)到RAM中。加載時(shí)狀態(tài)的映象文件中的RO、RW和ZI的地址都是臨時(shí)的,他們在運(yùn)行時(shí)要被BootLoader程序搬運(yùn)到真正的運(yùn)行時(shí)地址。這個(gè)地址是連接時(shí)設(shè)置的地址。這個(gè)問題很重要,如果在編譯前沒有正確的設(shè)置運(yùn)行時(shí)地址,那么程序就不能被搬運(yùn)到正確的RAM地址中運(yùn)行。

了解了以上內(nèi)容,那么就可以打開ADS1.2來看一下具體的設(shè)置。

打開ADS的一個(gè)工程后,點(diǎn)擊如下圖所示的Debug Settings按鈕打開對話框。打開Target Settings對話框后,在左邊列表中選擇Linker選項(xiàng)。點(diǎn)擊它下面的的ARM Linker。然后在右面的選項(xiàng)卡選擇Output選項(xiàng)卡。如下圖所示。

看看ADS 開發(fā)文檔ARMDeveloper suite 1.2 的ADS_CodeWarriorIDEGuide.pdf 怎么說的

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í)地址和運(yùn)行時(shí)地址。如果沒有設(shè)置值,默認(rèn)時(shí)0x8000。這個(gè)值將會對應(yīng)ADS的預(yù)定義變量Image$$RO$$Base,指定了RO的base。這個(gè)變量可以被初始化程序IMPORT進(jìn)去。這個(gè)參數(shù)有兩個(gè)意思:1,如果生成可執(zhí)行bin文件燒寫到flash中去,那么這個(gè)地址就是要燒到flash中的地址(一般是0x0)。這里又出現(xiàn)一個(gè)問題,如果使用的ARM芯片是支持memory remap的(如三星的4510芯片),那么可以在bootloader程序中將RO段搬運(yùn)到RAM中,再把RAM remap 到0x0,這樣系統(tǒng)讀取RO段的時(shí)候就可以在RAM中讀了。如果ARM芯片不支持remap(如三星的44b0x),那么RO段不能搬運(yùn)到RAM中,而在FLASH中讀取。2,如果生成afx調(diào)試文件,那么這個(gè)地址是調(diào)試時(shí)加載到RAM中的地址。

根據(jù)上面的1,2可知,如果要燒寫FLASH 那么RO Base 應(yīng)該設(shè)置成ARM片選的FLASH 的首地址;如果要調(diào)試那么RO Base要設(shè)置成RAM地址。

RW Base 這個(gè)文本框設(shè)定包含RW和ZI輸出段的運(yùn)行時(shí)域地址。如果你在這里輸入一個(gè)值,連接器創(chuàng)建一個(gè)包含兩個(gè)運(yùn)行時(shí)域的映象,這兩個(gè)域是:

包含RO輸出段的運(yùn)行時(shí)域

包含RW和ZI輸出段的運(yùn)行時(shí)域

如果你輸入了RW Base值并且選擇了Split image選項(xiàng),連接器創(chuàng)建的映象文件分別包含RW輸出段和ZI輸出段的裝載時(shí)地址和運(yùn)行時(shí)地址,并都由你輸入的RW Base值指定。

對于簡單連接方式,當(dāng)沒有輸入RW Base值時(shí),映象文件包含一個(gè)加載時(shí)域和一個(gè)運(yùn)行時(shí)域。這時(shí),RO輸出段、RW輸出段、ZI輸出段都包含在一個(gè)域中。當(dāng)輸入RW Base值時(shí),映象文件包含兩個(gè)運(yùn)行時(shí)域,一個(gè)包含RO輸出段,一個(gè)包含RW輸出段和ZI輸出段。當(dāng)指定了-split選項(xiàng)時(shí),映象文件又多包含兩個(gè)加載時(shí)域,一個(gè)包含RO輸出段,一個(gè)包含RW輸出段和ZI輸出段。

簡單的初始化用戶程序的執(zhí)行環(huán)境

ARM映像文件一開始總是存儲在ROM/Flash里面的,其RO部分既可以在ROM/Flash里面執(zhí)行,也可以轉(zhuǎn)移到速度更快的RAM中執(zhí)行;而RW和ZI這兩部分是必須轉(zhuǎn)移到可寫的RAM里去,其實(shí)RW包括ZI區(qū)域,ZI區(qū)域放的是未賦值的全局變量,RW 區(qū)域放的是已賦值(賦0除外)的全局變量。所謂應(yīng)用程序執(zhí)行環(huán)境的初始化,就是完成必要的從ROM到RAM的數(shù)據(jù)傳輸和內(nèi)容清零。

先介紹幾個(gè)必要的符號,編譯器使用下列符號來記錄各段的起始和結(jié)束地址:
|Image$$RO$$Base| :RO段起始地址
|Image$$RO$$Limit| :RO段結(jié)束地址加1?。ㄔ诩虞d域中,是RW的起始地址)
|Image$$RW$$Base| :RW段起始地址?。ㄔ谶\(yùn)行域中即運(yùn)行的時(shí)候,是RW的起始地址)
|Image$$RW$$Limit| :ZI段結(jié)束地址加1
|Image$$ZI$$Base| :ZI段起始地址
|Image$$ZI$$Limit| :ZI段結(jié)束地址加1
這些符號的值是根據(jù)鏈接器中設(shè)置的中ro-base和rw-base的設(shè)置來計(jì)算的。 由于rw和zi相連,|Image$$ZI$$Base|就等于|Image$$RW$$Limit| .其它的值都是編譯器自動計(jì)算出來的。我們還可以通過scatter文件更詳細(xì)得指定各個(gè)輸出段的工作地址。
初始化用戶執(zhí)行環(huán)境主要是把ro、rw、zi三段拷貝到指定的位置。

下面的程序是rw、zi段在運(yùn)行域中的搬運(yùn)過程:

;Copy and paste RW data/zero initialized data
ldr r0, =|Image$$RO$$Limit| /*取RO區(qū)末地址后面的地址,即RW數(shù)據(jù)源的起始地址*/
ldr r1, =|Image$$RW$$Base|/*取RW區(qū)在RAM里的執(zhí)行區(qū)起始地址,即編譯器選項(xiàng)RW_Base指定的地址*/
ldr r3, =|Image$$ZI$$Base|/*取ZI區(qū)在RAM里面的起始地址*/


;Zero init base => top of initialised data
cmp r0, r1 /* 比較ROM區(qū)中數(shù)據(jù)段首地址和RAM區(qū)中RW段目標(biāo)首地址*/
beq %F2 /*相等代表當(dāng)前已經(jīng)是在RAM中運(yùn)行*/(F表示after,B表示before,r0與r1相等則轉(zhuǎn)跳)
/*B %F2表向前跳到標(biāo)號為2的Lable處*/
1
cmp r1, r3 /*不相等則和RAM區(qū)中ZI段的目標(biāo)地址比較*/
ldrcc r2, [r0], #4/*如果r1 strcc r2, [r1], #4/*如果r1 bcc %B1 /*如果r12
ldr r1, =|Image$$ZI$$Limit| /* 取ZI段的結(jié)束地址 */
mov r2, #0 /*將r2賦值為0*/
3
cmp r3, r1 ; Zero init
strcc r2, [r3], #4 /*如果r3 bcc %B3 /*如果r3



關(guān)鍵詞: ADS1.2ARM映像文

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉