久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

RO,RW,ZI 和scatter file詳解

 kyosho 2010-07-21

要了解RO,,RW和ZI需要首先了解以下知識(shí):
      (1)    

   ARM程序的組成
            此處所說(shuō)的“ARM程序”是指在 ARM系統(tǒng)中正在執(zhí)行的程序,而非保存在ROM中的bin映像(image)文件,,這一點(diǎn)清注意區(qū)別。
            一個(gè)ARM程序包含3部分:RO,,RW和ZI
            RO是程序中的指令和常量
            RW是程序中的已初始化變量
            ZI是程序中的未初始化的變量
            由以上3點(diǎn)說(shuō)明可以理解為:
            RO就是readonly,,
            RW就是read/write,
            ZI就是zero

(2)
        ARM映像文件的組成
            所謂ARM映 像文件就是指燒錄到ROM中的bin文件,,也成為image文件,。以下用Image文件來(lái)稱呼它。
            Image文件包含了RO和RW數(shù)據(jù),。
            之所以Image文件不包含ZI數(shù)據(jù),,是因?yàn)閆I數(shù)據(jù)都是0,沒(méi)必要包含,,只要程序運(yùn)行之前將ZI數(shù)據(jù)所在的區(qū)域一律清零即可,。包含進(jìn)去反而浪費(fèi)存儲(chǔ)空 間。
            Q:為什么Image中必須包含RO和RW,?
            A:因?yàn)镽O中的指令和常量以及RW中初始化過(guò)的變量是不能像ZI那樣“無(wú)中生有”的,。
   (3)

    ARM程序的執(zhí)行過(guò)程
            從以上兩點(diǎn)可以知道,燒錄到ROM中的image文件與實(shí)際運(yùn)行時(shí)的ARM程序之間并不是完全一樣的,。因此就有必要了解ARM程序是如何從ROM中的image到達(dá)實(shí)際運(yùn)行狀態(tài)的,。
            實(shí)際上,ROM中的指令至少應(yīng)該有這樣的功能:
            1. 將RW從ROM中搬到RAM中,,因?yàn)镽W是變量,,變量不能存在ROM中。
            2. 將ZI所在的RAM區(qū)域全部清零,因?yàn)閆I區(qū)域并不在Image中,,所以需要程序根據(jù)編譯器給出的ZI地址及大小來(lái)將相應(yīng)得RAM區(qū)域清零,。ZI中也是變 量,同理:變量不能存在ROM中
            在程序運(yùn)行的最初階段,,RO中的指令完成了這兩項(xiàng)工作后C程序才能正常訪問(wèn)變量,。否則只能運(yùn)行不含變量的代碼。


    下面我將給出幾個(gè)例子,,最直觀的來(lái)說(shuō)明RO,,RW,ZI在C中是什么意思,。
            1; RO
            看下面兩段程序,,他們之間差了一條語(yǔ)句,這條語(yǔ)句就是聲明一個(gè)字符常量,。因此按照我們之前 說(shuō)的,,他們之間應(yīng)該只會(huì)在RO數(shù)據(jù)中相差一個(gè)字節(jié)(字符常量為1字節(jié))。
            Prog1:
            #include <stdio.h>
            void main(void)
            {
            ;
            }
            Prog2:
            #include <stdio.h>
            const char a = 5,;
            void main(void)
            {
            ;
            }
            Prog1編譯出來(lái)后的信息如下:
            ================================================================================
            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編譯出來(lái)后的信息如下:
            ================================================================================
            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)
            ================================================================================
            以上兩個(gè)程序編譯出來(lái)后的信息可以看出:
            Prog1和Prog2的RO包含了Code和RO Data 兩類數(shù)據(jù),。他們的唯一區(qū)別就是Prog2的RO Data比Prog1多了1個(gè)字節(jié),。這正和之前的推測(cè)一致。
            如果增加的是一條指令而不是一個(gè)常量,則結(jié)果應(yīng)該是Code數(shù)據(jù)大小有差別,。
            2; RW
            同樣再看兩個(gè)程序,,他們之間只相差一個(gè)“已初始化的變量”,,按照之前所講的,,已初始化的變 量應(yīng)該是算在RW中的,所以兩個(gè)程序之間應(yīng)該是RW大小有區(qū)別,。
            Prog3:
            #include <stdio.h>
            void main(void)
            {
            ;
            }
            Prog4:
            #include <stdio.h>
            char a = 5,;
            void main(void)
            {
            ;
            }
            Prog3編譯出來(lái)后的信息如下:
            ================================================================================
            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編譯出來(lái)后的信息如下:
            ================================================================================
            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之間確實(shí)只有RW Data之間相差了1個(gè)字節(jié),這個(gè)字節(jié)正是被初始化過(guò)的一個(gè)字符型變量“a”所引起的,。
            3; ZI
            再看兩個(gè)程序,,他們之間的差別是一個(gè)未初始化的變量“a”,從之前的了解中,,應(yīng)該可以推測(cè),,這兩個(gè)程序之間應(yīng)該只有ZI大小有差別。
            Prog3:
            #include <stdio.h>
            void main(void)
            {
            ;
            }
            Prog4:
            #include <stdio.h>
            char a,;
            void main(void)
            {
            ;
            }
            Prog3編譯出來(lái)后的信息如下:
            ================================================================================
            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編譯出來(lái)后的信息如下:
            ================================================================================
            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)
            ================================================================================
            編譯的結(jié)果完全符合推測(cè),,只有ZI數(shù)據(jù)相差了1個(gè)字節(jié)。這個(gè)字節(jié)正是未初始化的一個(gè)字符型變量“a”所引起的,。
            注意:如果一個(gè)變量被初始化為0,,則該變量的處理方法與未初始化華變量一樣放在ZI區(qū)域。
            即:ARM C程序中,所有的未初始化變量都會(huì)被自動(dòng)初始化為0,。
            總結(jié):
            1; C中的指令以及常量被編譯后是RO類型數(shù)據(jù),。
            2; C中的未被初始化或初始化為0的變量編譯后是ZI類型數(shù)據(jù)。
            3; C中的已被初始化成非0值的變量編譯后市RW類型數(shù)據(jù),。


        (4)
            ROM主要指:NAND Flash,,Nor Flash
            RAM主要指:PSRAM,SDRAM,,SRAM,,DDRAM

(5)

    Image$$??$$Limit 的含義

對(duì)于剛學(xué)習(xí)ARM的人來(lái)說(shuō),如果分析它的啟動(dòng)代碼,,往往不明白下面幾個(gè)變量的含 義:|Image$$RO$$Limit|,、|Image$$RW$$Base|、|Image$$ZI$$Base|,。

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

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ù)是根據(jù)用戶不同的程序而來(lái)的,下面就以上面的數(shù)據(jù)為例來(lái)介紹那幾個(gè)變量的計(jì)算,。

     在ADS的Debug Settings中有一欄是Linker/ARM Linker,,在output選項(xiàng)中有一個(gè)RO base選項(xiàng),

  假如 

 RO base設(shè)置為0x0c100000,,后面的RW base 設(shè)置為0x0c200000,,然后在Options選項(xiàng)中有Image entry point ,是一個(gè)初始程序的入口地址,,設(shè)置為0x0c100000 ,。

有了上面這些信息我們就可以完全知道這幾個(gè)變量是怎么來(lái)的了:

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

|Image$$RO$$Limit|=程序代碼起始地址+代碼長(zhǎng)度+1=0x0c100000+Tatal RO size+1

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

= 0x0c12d0fc

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

|Image$$RW$$Limit| =|Image$$RW$$Base|+ RW Data 53 = 0x0c200000+0x37(4的倍數(shù),0到55,共56個(gè)單元)

=0x0c200037

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

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

                            =0x0c200038 + 0x4284

                            =0x0c2042bc

也可以由此計(jì)算:

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

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

                            =0x0c2042bc


Part1  簡(jiǎn)介

一 概述

Scatter file (分散加載描述文件)用于armlink的輸入?yún)?shù),他指定映像文件內(nèi)部各區(qū)域的download與運(yùn)行時(shí)位置,。Armlink將會(huì)根據(jù)scatter file生成一些區(qū)域相關(guān)的符號(hào),,他們是全局的供用戶建立運(yùn)行時(shí)環(huán)境時(shí)使用。(注意:當(dāng)使用了scatter file 時(shí)將不會(huì)生成以下符號(hào) Image$$RW$$Base, Image$$RW$$Limit, Image$$RO$$Base, Image$$RO$$Limit, Image$$ZI$$Base, and Image$$ZI$$Limit)

二 什么時(shí)候使用scatter file

       當(dāng)然首要的條件是你在利用ADS進(jìn)行項(xiàng)目開(kāi)發(fā),,下面我們看看更具體的一些情況,。

1 存在復(fù)雜的地址映射:例如代碼和數(shù)據(jù)需要分開(kāi)放在在多個(gè)區(qū)域。

2 存在多種存儲(chǔ)器類型:例如包含 Flash,ROM,SDRAM,快速SRAM,。我們根據(jù)代碼與數(shù)據(jù)的特性把他們放在不同的存儲(chǔ)器中,,比如中斷處理部分放在快速SRAM內(nèi)部來(lái)提高響應(yīng)速 度,而把不常用到的代碼放到速度比較慢的Flash內(nèi),。

3 函數(shù)的地址固定定位:可以利用Scatter file實(shí)現(xiàn)把某個(gè)函數(shù)放在固定地址,,而不管其應(yīng)用程序是否已經(jīng)改變或重新編譯。

4 利用符號(hào)確定堆與堆棧:

5 內(nèi)存映射的IO:采用scatter file可以實(shí)現(xiàn)把某個(gè)數(shù)據(jù)段放在精確的地指處,。

因此對(duì)于嵌入式系統(tǒng)來(lái)說(shuō)scatter file是必不可少的,,因?yàn)榍度胧较到y(tǒng)采用了ROM,RAM,,和內(nèi)存映射的IO,。

三 scatter file 實(shí)例

1 簡(jiǎn)單的內(nèi)存映射

LOAD_ROM 0x0000 0x8000

{

       EXEC_ROM 0x0000 0x8000

       {

       *( RO)

       }

      RAM 0x10000 0x6000

      {

       *( RW, ZI)

      }

}

 

LOAD_ROM(下載區(qū)域名稱) 0x0000(下載區(qū)域起始地址) 0x8000(下載區(qū)域最大字節(jié)數(shù))

{

        EXEC_ROM(第一執(zhí)行區(qū)域名稱) 0x0000(第一執(zhí)行區(qū)域起始地址) 0x8000(第一執(zhí)行區(qū)域最大字節(jié)數(shù))

       {

       *( RO(代碼與只讀數(shù)據(jù)))

       }

      RAM(第二執(zhí)行區(qū)域名稱) 0x10000(第二執(zhí)行區(qū)域起始地址) 0x6000(第二執(zhí)行區(qū)域最大字節(jié)數(shù))

      {

       *( RW(讀寫(xiě)變量), ZI(未初始化變量))

      }

}

2 復(fù)雜內(nèi)存映射

LOAD_ROM_1 0x0000

{

       EXEC_ROM_1 0x0000

       {

        program1.o( RO)

       }

      DRAM 0x18000 0x8000

      {

       program1.o ( RW, ZI)

      }

}

 

LOAD_ROM_2 0x4000

{

       EXEC_ROM_2 0x4000

       {

       program2.o( RO)

       }

       SRAM 0x8000 0x8000

      {

       program2.o ( RW, ZI)

      }

}

 

LOAD_ROM_1 0x0000(下載區(qū)域一起始地址)

{

       EXEC_ROM_1 0x0000(第一執(zhí)行區(qū)域開(kāi)始地址)

       {

        program1.o( RO) (program1.o內(nèi)的Code與RO data 放在第一執(zhí)行區(qū)域)

       }

       DRAM 0x18000(第二執(zhí)行區(qū)域開(kāi)始地址) 0x8000(第二執(zhí)行區(qū)域最大字節(jié)數(shù))

      {

       program1.o ( RW, ZI) (program1.o內(nèi)的RW data與 ZI data 放在第二執(zhí)行區(qū)域)

      }

}

LOAD_ROM_2 0x4000(下載區(qū)域二起始地址)

{

       EXEC_ROM_2 0x4000

       {

       program2.o( RO) (program2.o內(nèi)的Code與RO data 放在第一執(zhí)行區(qū)域)

      }

      SRAM 0x8000 0x8000

      {

       program2.o ( RW, ZI) (program2.o內(nèi)的RW data與 ZI data 放在第二執(zhí)行區(qū)域)

      }

}

Part2 基本語(yǔ)法

2.1   BNF 符號(hào)與語(yǔ)法

" :由引號(hào)賴標(biāo)示的符號(hào)保持其字面原意,如A” ”B標(biāo)示A B,。

A ::= B :定義A為B,。

[A] :標(biāo)示可選部分,如A[B]C用來(lái)標(biāo)示ABC或AC,。

A :用來(lái)標(biāo)示A可以重復(fù)任意次,,如A 可標(biāo)示A,AA,AAA, …

A* :同A 。

A | B :用來(lái)標(biāo)示選擇其一,,不能全選,。如A|B用來(lái)標(biāo)示A或者B。

(A B) :標(biāo)示一個(gè)整體,,當(dāng)和|符號(hào)或復(fù)雜符號(hào)的多次重復(fù)一起使用時(shí)尤其強(qiáng)大,,如(AB) (C|D)標(biāo)示ABC,ABD,ABABC,ABABD, …

2.2     分散加載文件各部分描述                       

                            (2.1)

如圖2.1所示為一個(gè)完整的分散加載腳本描述結(jié)構(gòu)圖。下面我們對(duì)圖示中各個(gè)部分進(jìn)行講述,。

2.2.1 加載區(qū)描述

每個(gè)加載區(qū)有:

ó名稱:供連接器確定不同下載區(qū)域

ó基地址:相對(duì)或絕對(duì)地址

ó屬性:可選

ó最大字節(jié)數(shù):可選

ó執(zhí)行區(qū)域列:確定執(zhí)行時(shí)各執(zhí)行區(qū)域的類型與位置

load_region_name (base_address | (" " offset)) [attribute_list] [ max_size ]

"{"

execution_region_description

"}"

 

load_region_name:下載區(qū)域名稱,,最大有效字符數(shù)31。(并不像執(zhí)行區(qū)域段名用于Load$$region_name,,而是僅僅用 于標(biāo)示下載區(qū)域),。

base_address:本區(qū)域內(nèi)部目標(biāo)被連接到的地址(按字對(duì)齊)。

offset:相對(duì)前一個(gè)下載區(qū)域的偏移量(4的整數(shù)倍,,如果為第一個(gè)區(qū)域),。

 

2.2.2 執(zhí)行區(qū)描述

每個(gè)執(zhí)行區(qū)有:

ó名稱:供連接器確定不同下載區(qū)域

ó基地址:相對(duì)或絕對(duì)地址

ó屬性:確定執(zhí)行區(qū)域的屬性

ó最大字節(jié)數(shù):可選

ó輸入段:確定放在該執(zhí)行區(qū)域的模塊

exec_region_name (base_address | " " offset) [attribute_list] [max_size]

"{"

input_section_description

"}"

exec_region_name:執(zhí)行區(qū)域名稱,,最大有效字符數(shù)31。

base_address:本執(zhí)行區(qū)域目標(biāo)要被聯(lián)接到的位置,,按字對(duì)齊,。

offset:相對(duì)于前一個(gè)執(zhí)行區(qū)域結(jié)束地址的偏移量,4的整數(shù)倍,;如果沒(méi)有前繼之能夠行區(qū)域(本執(zhí)行區(qū)域?yàn)樵撓螺d區(qū)域的第一個(gè)執(zhí)行區(qū)域),,則該偏 移量是相對(duì)于該下載區(qū)域的基址偏移量。

attribute_list:PI,,OVERLAY,,ABSOLUTE,F(xiàn)IXED,,UNINIT,。

PI: 位置獨(dú)立。

OVERLAY: 覆蓋,。

ABSOLUTE: 絕對(duì)地址,。

FIXED: 固定地址,下載地址與執(zhí)行地址具有該地址指示確定,。

UNINIT: 未初始化數(shù)據(jù),。

RELOC:無(wú)法明確指定執(zhí)行區(qū)域具有該屬性,而只能通過(guò)繼承前一個(gè)執(zhí)行區(qū)或父區(qū)域獲得,。

對(duì)于PI,,OVERLAY,ABSOLUTE,,F(xiàn)IXED,,我們只能選擇一個(gè),缺省屬性為ABSOLUTE,。一個(gè)執(zhí)行區(qū)域要么直接繼承其前面的執(zhí)行 區(qū)域的屬性或者具有屬性為ABSOLUTE,。

具有PI,OVERLAY,,RELOC屬性的執(zhí)行區(qū)域允許其地址空間重疊,,對(duì)于BSOLUTE,,F(xiàn)IXED 屬性執(zhí)行區(qū)域地址空間重疊Armlink會(huì)報(bào)錯(cuò),。

max_size:可選,他用于指使Armlink在實(shí)際分配空間大于指定值時(shí)報(bào)錯(cuò),。

input_section_description:指示輸入段的內(nèi)容,。

 

2.2.3 輸入段描述

輸入段:

ó模塊名:目標(biāo)文件名,庫(kù)成員名,,庫(kù)文件名,。名稱可以使用通配符,。

ó輸入段名,或輸入段屬性(READ-ONLY,CODE),。

module_select_pattern

["("

(" " input_section_attr | input_section_pattern)

([","] " " input_section_attr | "," input_section_pattern))*

")"]

2.2.3.1

module_select_pattern:選擇的模塊名稱(目標(biāo)文件,,庫(kù)文件成員,庫(kù)文件),,模塊名可以使用通配符(*匹配任意多個(gè)字符,,?匹 配任意一個(gè)字符),,名稱不區(qū)分字母大小寫(xiě),,它是供選擇的樣本。

例1:*libtx.a ( RO)

libtx.a為threadX庫(kù)文件,。

例2:tx_ill.o (INIT)

       tx_ill.o為threadX中斷向量目標(biāo)文件,。

2.2.3.2

input_section_attr:輸入段屬性選擇子,每個(gè)選擇子以” ”開(kāi)頭,,選擇子不區(qū)分大小寫(xiě)字符,。

選擇子可選RO-CODE,RO-DATA,,RO( selects both RO-CODE and RO-DATA),,RW-DATA,RW-CODE,,RW( selects both RW-CODE and RW-DATA),,ZI,ENTRY( that is a section containing an ENTRY point),。

以下同義詞可以選擇:CODE (for RO-CODE),,CONST( for RO-DATA),TEXT (for RO),,DATA (for RW),,BSS (for ZI)。

還有兩個(gè)偽屬性:FIRST,,LAST,。如果各段的先后順序比較重要時(shí),可以使用FIRST,,LAST標(biāo)示一個(gè)執(zhí)行區(qū)域的第一個(gè)和最后一個(gè)段,。

例1:os_main_init.o (INIT , FIRST)

FIRST表示放于本執(zhí)行區(qū)域的開(kāi)始處。

例2:*libtx.a ( RO)

       RO 表示*libtx.a的只讀部分,。

2.2.3.3

input_section_pattern:輸入段名,。

例1:os_main_init.o (INIT , FIRST)

INIT 為os_main_init.o的一個(gè)段。

例2:os_stackheap.o (heap)

       heap 為os_stackheap.o的一個(gè)段,。

例3:os_stackheap.o (stack)

       stack為os_stackheap.o的一個(gè)段,。

 

 

 

 

//--------------------------------------------------------------------------------------------------------------------------

分散加載文件事例

 

ADS下的分散加載文件應(yīng)用實(shí)例

load_region_name  start_address | " "offset  [attributes] [max_size]

{

    execution_region_name  start_address | " "offset  [attributes][max_size]

    {

        module_select_pattern  ["("

                                    (" " input_section_attr | input_section_pattern)

                                    ([","] " " input_section_attr | "," input_section_pattern)) *

                               ")"]

    }

}

load_region:       加載區(qū),,用來(lái)保存永久性數(shù)據(jù)(程序和只讀變量)的區(qū)域;

execution_region:  執(zhí)行區(qū),,程序執(zhí)行時(shí),,從加載區(qū)域?qū)?shù)據(jù)復(fù)制到相應(yīng)執(zhí)行區(qū)后才能被正確執(zhí)行;

load_region_name:  加載區(qū)域名,,用于“Linker”區(qū)別不同的加載區(qū)域,,最多31個(gè)字符;

start_address:     起始地址,,指示區(qū)域的首地址,;

offset:           前一個(gè)加載區(qū)域尾地址+offset 做為當(dāng)前的起始地址,且“offset”應(yīng)為“0”或“4”的倍數(shù),;

attributes:        區(qū)域?qū)傩?,可設(shè)置如下屬性:

                    PI       與地址無(wú)關(guān)方式存放;

                    RELOC    重新部署,,保留定位信息,,以便重新定位該段到新的執(zhí)行區(qū);

                    OVERLAY  覆蓋,,允許多個(gè)可執(zhí)行區(qū)域在同一個(gè)地址,,ADS不支持;

                    ABSOLUTE 絕對(duì)地址(默認(rèn)),;

max_size:          該區(qū)域的大?。?/p>

execution_region_name:執(zhí)行區(qū)域名,;

start_address:     該執(zhí)行區(qū)的首地址,,必須字對(duì)齊;

offset:           同上,;

attributes:        同上,;

                    PI          與地址無(wú)關(guān),該區(qū)域的代碼可任意移動(dòng)后執(zhí)行,;

                    OVERLAY     覆蓋,;

                    ABSOLUTE    絕對(duì)地址(默認(rèn));

                    FIXED       固定地址,;

                    UNINIT      不用初始化該區(qū)域的ZI段,;

module_select_pattern: 目標(biāo)文件濾波器,支持通配符“*”和“?”,;

                        *.o匹配所有目標(biāo),,* (或“.ANY”)匹配所有目標(biāo)文件和庫(kù),。

input_section_attr:    每個(gè)input_section_attr必須跟隨在“+”后,;且大小寫(xiě)不敏感,;

                        RO-CODE 或 CODE

                        RO-DATA 或 CONST

                        RO或TEXT, selects both RO-CODE and RO-DATA

                        RW-DATA

                        RW-CODE

                        RW 或 DATA, selects both RW-CODE and RW-DATA

                        ZI 或 BSS

                        ENTRY, that is a section containing an ENTRY point.

                        FIRST,用于指定存放在一個(gè)執(zhí)行區(qū)域的第一個(gè)或最后一個(gè)區(qū)域,;

                        LAST,,同上;

input_section_pattern: 段名,;

匯編中指定段:

     AREA    vectors, CODE, READONLY

C中指定段:

#pragma arm section [sort_type[[=]"name"]] [,sort_type="name"]*

sort_type:      code,、rwdata、rodata,、zidata

                如果“sort_type”指定了但沒(méi)有指定“name”,,那么之前的修改的段名將被恢復(fù)成默認(rèn)值。

#pragma arm section     // 恢復(fù)所有段名為默認(rèn)設(shè)置,。

應(yīng)用:

    #pragma arm section rwdata = "SRAM",zidata = "SRAM"

        static OS_STK  SecondTaskStk[256];              // “rwdata”“zidata”將定位在“sram”段中,。

    #pragma arm section                                 // 恢復(fù)默認(rèn)設(shè)置

分散加載文件中定義如下:

    Exec_Sram  0x80000000  0x40000

    {

        * (sram)

    }

“PI” 屬性使用示例:

LR_1 0x010000 PI                ; The first load region is at 0x010000.

{

    ER_RO 0                    ; The PI attribute is inherited from parent.

                                ; The default execution address is 0x010000, but the code can be moved.

    {

        *( RO)                  ; All the RO sections go here.

    }

    ER_RW 0 ABSOLUTE           ; PI attribute is overridden by ABSOLUTE.

    {

        *( RW)                  ; The RW sections are placed next. They cannot be moved.

    }

    ER_ZI 0                    ; ER_ZI region placed after ER_RW region.

    {

        *( ZI)                  ; All the ZI sections are placed consecutively here.

    }

}

LR_1 0x010000                   ; The first load region is at 0x010000.

{

    ER_RO 0                    ; Default ABSOLUTE attribute is inherited from parent. The execution address

                                ; is 0x010000. The code and ro data cannot be moved.

    {

        *( RO)                  ; All the RO sections go here.

    }

    ER_RW 0x018000 PI           ; PI attribute overrides ABSOLUTE

    {

        *( RW)                  ; The RW sections are placed at 0x018000 and they can be moved.

    }

    ER_ZI 0                    ; ER_ZI region placed after ER_RW region.

    {

        *( ZI)                  ; All the ZI sections are placed consecutively here.

    }

}

程序中對(duì)某區(qū)域地址等的引用方法:

Load$$region_name$$Base             Load address of the region.

Image$$region_name$$Base            Execution address of the region.

Image$$region_name$$Length          Execution region length in bytes (multiple of 4).

Image$$region_name$$Limit           Address of the byte beyond the end of the execution region.

Image$$region_name$$ZI$$Base        Execution address of the ZI output section in this region.

Image$$region_name$$ZI$$Length      Length of the ZI output section in bytes (multiple of 4).

Image$$region_name$$ZI$$Limit       Address of the byte beyond the end of the ZI output sectionin the execution region.

SectionName$$Base                   Input Address of the start of the consolidated section called SectionName.

SectionName$$Limit                  Input Address of the byte beyond the end of the consolidated section called SectionName.

Load:          加載區(qū),即存放地址,;

Image:         執(zhí)行區(qū),,即運(yùn)行地址;

Base:          區(qū)首地址,;

Limit:         區(qū)尾地址,;

Length:        區(qū)長(zhǎng)度;

region_name:   RO,、RW,、ZI、load_region_name,、execution_region_name,;

例如:

    “RAM1”區(qū)域的首地址:      Image$$RAM1$$Base

    上例中“sram”段首地址:    sram$$Base

匯編引用示例:

  IMPORT |Load$$Exec_RAM1$$Base|              // Exec_RAM1 為“RW”段

  IMPORT |Image$$Exec_RAM1$$Base|

  IMPORT |Image$$Exec_RAM1$$Length|

  IMPORT |Image$$Exec_RAM1$$Limit|

  LDR  R0, =|Load$$Exec_RAM1$$Base|

  LDR  R1, =|Image$$Exec_RAM1$$Base|

  LDR  R2, =|Image$$Exec_RAM1$$Limit|

0

  CMP  R1,   R2

  LDRCC R3,   [R0], #4

  STRCC R3,   [R1], #4

  BCC  %b0

C 引用:

extern unsigned char Load$$Exec_RAM1$$Base;

extern unsigned char Image$$Exec_RAM1$$Base;

extern unsigned char Image$$Exec_RAM1$$Length;

void MoveRO(void)

{

unsigned char * psrc, *pdst;

unsigned int  count;

count = (unsigned int)   &Image$$Exec_RAM1$$Length;

psrc  = (unsigned char *)&Load$$Exec_RAM1$$Base;

pdst  = (unsigned char *)&Image$$Exec_RAM1$$Base;

while (count--) {

  *pdst = *psrc ;

}

}

加載文件示例一:

        起始地址      大小

ROM:    0x00000000    256K      ;0x1fc 保留為加密字,,程序在ROM中運(yùn)行,;

RAM     0x40000000     16K      ;用于全局變量及任務(wù)堆棧,;

SRAM    0x80000000    512K      ,;SRAM速度慢,主要用于存放大的數(shù)據(jù)表,;

LOAD_ROM1 0x00000000  0x1f8                 ; 指定該加載區(qū)域首地址,、大小

{

    EXEC_ROM1  0  0x1f8                    ; 沒(méi)有前一加載區(qū)域,所以該執(zhí)行區(qū)域首地址為加載去首地址

                                            ; 并指定該區(qū)域長(zhǎng)度

    {

        Startup.o (vectors, FIRST)         ; 目標(biāo)文件的“vectors”段放在該執(zhí)行區(qū)域的第一段

        irq.o ( RO)                         ; 目標(biāo)文件的所有“RO”段放在該執(zhí)行區(qū)域

    }

}

LOAD_ROM2 0x00000200                        ; 第二個(gè)加載區(qū)域

{

    EXEC_ROM2  0  0x3e600

    {

        * ( RO)                             ; 所有目標(biāo)文件和庫(kù)文件中的“RO”段存放在該區(qū)域

    }

    RAM1   0x40000000   0x4000

    {

        * ( RW, ZI)                        ; 所有目標(biāo)文件和庫(kù)文件的“RW”和“ZI”段存放在該區(qū)域

    }

    SRAM2  0x80000000  0x80000

    {

        * (sram)                            ; 所有目標(biāo)文件中的“sram”段存放在該區(qū)域

    }

}

示例二:

    “iap.o”定義在“Exec_RAM1”中運(yùn)行,,所以設(shè)置“PI”屬性,;

    在調(diào)用“iap.c”中函數(shù)之前應(yīng)該將其從“Load$$Exec_IAP$$Base”復(fù)制到指定的“Exec_RAM1”區(qū)域;

Load_region1  0x00000000  0x1fc

{

    EXEC_ROM1  0

    {

        Startup.o (vectors, FIRST)

        irq.o ( RO)

    }

}

Load_region2  0x00000200  0x3e600

{

    EXEC_ROM2  0

    {

        * ( RO)

    }

    Exec_IAP   0  PI               // 可能引起鏈接器未使用該屬性警告,,忽略

    {

        iap.o ( RO)

    }

    Exec_RAM1  0x40000000  0x4000

    {

        * ( RW, ZI)

    }

    Exec_Sram  0x80000000  0x40000

    {

        * (SRAM)

    }

}

// 移動(dòng)“IAP.o”中的所有函數(shù)到“ImageExecIAPBase”加載區(qū),,并調(diào)用其中的函數(shù)

extern unsigned char Load$$Exec_IAP$$Base;

extern unsigned char Image$$Exec_IAP$$Length;

#define  ImageExecIAPBase  (0x40000000 0x1000)   // 加載區(qū)首址

void MoveIAPRO(void)

{

unsigned char * psrc, *pdst;

unsigned int  count;

count = (unsigned int)   &Image$$Exec_IAP$$Length;

psrc  = (unsigned char *)&Load$$Exec_IAP$$Base;

pdst  = (unsigned char *)ImageExecIAPBase;

while (count--) {

  *pdst = *psrc ;

}

}

// 調(diào)用“IAP.O”中的某函數(shù)

{

  void (* pfnIAPWrite)(unsigned long, int);

  pfnIAPWrite = (void (*)(unsigned long, int))

   (ImageExecIAPBase

   (unsigned int)IAPWrite -                        // 被調(diào)用函數(shù)名

   (unsigned int)&Load$$Exec_IAP$$Base);

  pfnIAPWrite((int)((CUPDATA *)CODESTARTADDR)->data,

     ((CUPDATA *)CODESTARTADDR)->length);

    }

 

 

 

 

//————————————————————————————————————————————————————————————
ARM 編譯程序參考
介紹ARM編譯程序的ARM特有方面,,包括:
Pragmas                                     編譯指示
Function keywords                    函數(shù)關(guān)鍵字
Variable declaration keywords 變量聲明關(guān)鍵字

Pragmas
ARM編譯程序可識(shí)別一下格式的編譯指示:
#pragma [no_] feature-name
編譯指示 優(yōu)于相關(guān)的命令行選項(xiàng)。
能識(shí)別的編譯選項(xiàng)如下:


Pragma name
       
Default
       
Reference
arm section
       
Off
       
Pragmas controlling code generation
check_printf_formats
       
Off
       
Pragmas controlling printf and scanf argument checking
check_scanf_formats
       
Off
       
Pragmas controlling printf and scanf argument checking
check_stack
       
On
       
Pragmas controlling code generation
debug
       
On
       
Pragmas controlling debugging
import
       

       
code generation
Ospace
       

       
optimization
Otime
       

       
optimization
Onum
       

       
optimization
softfp_linkage
       
Off
       
code generation

 

    * check_printf_formats

該編譯指示標(biāo)記類似于printf的函數(shù),,如果存在文字格式串,,則對(duì)照進(jìn)行類型檢查。
#pragma check_printf_formats
extern void myprintf(const char *format, …);
#pragma no_check_printf_formats

    * check_scanf_formats

該編譯指示對(duì)聲明為類似于scanf的函數(shù)做標(biāo)記,,以便對(duì)照文字格式串檢查自變量的格式,。
#pragma check_scanf_formats
extern void myformat(const char *format, …);
#pragma no_check_scanf_formats

    * debug 該編譯指示可打開(kāi)或關(guān)閉調(diào)試表生成, 如果指定#pragma no_debug,則不會(huì)為隨后的聲明和函數(shù)生成調(diào)試信息表?xiàng)l目,,直到下一個(gè)#pragma debug出現(xiàn),。
    * Pragmas controlling optimization

Ospace
Otime
Onum

    * Pragmas controlling code generation
          o check_stack 如果已經(jīng)使用了#pragma no_check_stack和-apcs/swst命令行選項(xiàng)禁止棧檢查,則該編譯指示可使的檢查是否違反了棧限制的函數(shù)入口代碼的重新生成,。
          o once             同#ifndef …#endif效果相類似,,用于頭文件。但一般推薦使用#ifndef…#define,。
          o softfp_linkage   該編譯指示指定了至下一個(gè)#pragma no_softfp_linkage之間的所有函數(shù)聲明描述了使用軟件浮點(diǎn)鏈接的函數(shù),。__softfp關(guān)鍵字與該編譯指示的效果相同
          o import(symbol_name) 該編譯指示生成對(duì)symbol_name的導(dǎo)入引用。同如下匯編語(yǔ)言相同:IMPORT symbol_name,。符號(hào)名作為外部符號(hào)放在映像的符號(hào)表中,。
          o arm section section_sort_list This pragma specifies the code or data section name that used for subsequent function or objects.This include definitions of anonymous objects the compiler creates for initializations.該編譯指示可指定代碼或數(shù)據(jù)段的名稱用于隨后的函數(shù)或?qū)ο蟆0ň幾g程序?yàn)槌跏蓟鴦?chuàng)建的匿名對(duì)象的定義,。該選項(xiàng)對(duì)一下 情況沒(méi)有影響:

內(nèi)聯(lián)函數(shù)(及其局部靜態(tài)變量)
模板實(shí)例(及其局部靜態(tài)變量)
消除未使用的變量和函數(shù)
將定義寫(xiě)入目標(biāo)文件中的順序
                        該編譯指示完整語(yǔ)法為:
                                #pragma arm section [sort_type[[=]“name”]][,sort_type= 
“name”]
                        此處name用于段名稱,,sort_type可為如下之一code, rwdata, rodata
                        和zidata。若指定sort_type,,沒(méi)有指定name,,則sort_type的段名被
                        重新設(shè)置為默認(rèn)值。單獨(dú)輸入#pragma arm section,,則所以對(duì)象段的
                         恢復(fù)為其默認(rèn)值
int x1 = 5;                     // in .data (default)
    int y1[100];                    // in .bss (default)
    int const z1[3] = {1,2,3};      // in .constdata (default)
#pragma arm section rwdata = "foo", rodata = "bar"

int x2 = 5;                     // in foo (data part of region)
int y2[100];                    // in .bss
     int const z2[3] ={1,2,3};      // in bar
  char *s2 = "abc";               // s2 in foo, "abc" in bar
  #pragma arm section rodata
  int x3 = 5;                     // in foo
  int y3[100];                    // in .bss
      int const z3[3] ={1,2,3};      // in .constdata
  char *s3 = "abc";               // s3 in foo, "abc" in .constdata
  #pragma arm section code = "foo"
   int add1(int x)                   // in foo (code part of region)
      {
        return x 1;
      }
    #pragma arm section code


使用分散加載描述文件和鏈接程序,,以控制將命名段放置在存儲(chǔ)器中
                         的特定地址。
·          Function keywords
一些關(guān)鍵字指示編譯程序?qū)ζ淠硞€(gè)函數(shù)進(jìn)行特殊處理,。包括函數(shù)內(nèi)的聲明,,函數(shù)限定符及函數(shù)存儲(chǔ)類限定符。即 Declarations inside function, Function qualifiers and Function storage.
      __asm{assembler-code} 指示編譯程序該語(yǔ)句是用匯編語(yǔ)言編寫(xiě)的,。
      __irq      This enables a C or C function to be used as an interrupt routine called by the IRQ, or FIQ vectors. All corrupted registers except floating-point registers are preserved, not only those that are normally preserved under the ATPCS. The default ATPCS mode must be used. The function exits by setting the pc to lr-4 and the CPSR to the value in SPSR. It is not available in tcc or tcpp. No arguments or return values can be used with __irq functions.
      __pure      指明函數(shù)聲明為純的,。純函數(shù)沒(méi)有了公共子表達(dá)式。默認(rèn)情況下,,函數(shù)假定是不純的(產(chǎn)生副作用),。純函數(shù)需要滿足:其結(jié)果僅取決于其自變量的值;沒(méi)有副作 用,其不能調(diào)用非純函數(shù),。不能使用全局變量或廢棄指針,,同一參數(shù)兩次調(diào)用純函數(shù),返回應(yīng)該相同
一般而言,,一個(gè)程序包括只讀的代碼段和可讀寫(xiě)的數(shù)據(jù) 段,。在ARM的集成開(kāi)發(fā)環(huán)境中,,只讀的代碼段和常量被稱作RO段(ReadOnly),;可讀寫(xiě)的全局變量和靜態(tài)變量被稱作RW段 (ReadWrite);RW段中要被初始化為零的變量被稱為ZI段(ZeroInit),。對(duì)于嵌入式系統(tǒng)而言,,程序映象都是存儲(chǔ)在Flash存儲(chǔ)器等一 些非易失性器件中的,而在運(yùn)行時(shí),,程序中的RW段必須重新裝載到可讀寫(xiě)的RAM中,。這就涉及到程序的加載時(shí)域和運(yùn)行時(shí)域。簡(jiǎn)單來(lái)說(shuō),,程序的加載時(shí)域就是指 程序燒入Flash中的狀態(tài),,運(yùn)行時(shí)域是指程序執(zhí)行時(shí)的狀態(tài)。對(duì)于比較簡(jiǎn)單的情況,,可以在ADS集成開(kāi)發(fā)環(huán)境的ARM LINKER選項(xiàng)中指定RO BASE和RW BASE,,告知連接器RO和RW的連接基地址。對(duì)于復(fù)雜情況,,如RO段被分成幾部分并映射到存儲(chǔ)空間的多個(gè)地方時(shí),,需要?jiǎng)?chuàng)建一個(gè)稱為“分布裝載描述文件” 的文本文件,通知連接器把程序的某一部分連接在存儲(chǔ)器的某個(gè)地址空間,。需要指出的是,,分布裝載描述文件中的定義要按照系統(tǒng)重定向后的存儲(chǔ)器分布情況進(jìn)行。 在引導(dǎo)程序完成初始化的任務(wù)后,,應(yīng)該把主程序轉(zhuǎn)移到RAM中去運(yùn)行,,以加快系統(tǒng)的運(yùn)行速度。
            什么是arm的映像文件,,arm映像文件其實(shí)就是可執(zhí)行文件,,包括bin或hex兩種格式,可以直接燒到rom里執(zhí)行,。在axd調(diào)試過(guò)程中,,我們調(diào)試的是 axf文件,其實(shí)這也是一種映像文件,,它只是在bin文件中加了一個(gè)文件頭和一些調(diào)試信息,。映像文件一般由域組成,域最多由三個(gè)輸出段組成 (RO,RW,ZI)組成,輸出段又由輸入段組成,。所謂域,,指的就是整個(gè)bin映像文件所處在的區(qū)域,它又分為加載域和運(yùn)行域,。加載域就是映像文件被靜態(tài) 存放的工作區(qū)域,,一般來(lái)說(shuō)flash里的 整個(gè)bin文件所在的地址空間就是加載域,當(dāng)然在程序一般都不會(huì)放在 flash里執(zhí)行,,一般都會(huì)搬到sdram里運(yùn)行工作,,它們?cè)诒话岬絪dram里工作所處的地址空間就是運(yùn)行域。我們輸入的代碼,,一般有代碼部分和數(shù)據(jù)部 分,,這就是所謂的輸入段,經(jīng)過(guò)編譯后就變成了bin文件中ro段和rw段,,還有所謂的zi段,,這就是輸出段。對(duì)于加載域中的輸出段,,一般來(lái)說(shuō)ro段后面緊 跟著rw段,,rw段后面緊跟著zi段。在運(yùn)行域中這些輸出段并不連續(xù),,但rw和zi一定是連著的,。zi段和rw段中的數(shù)據(jù)其實(shí)可以是rw屬性。
                | Image$$RO$$Base| |Image$$RO$$Limit| |Image$$RW$$Base| |Image$$ZI$$Base| |Image$$ZI$$Limit|這幾個(gè)變量是編譯器通知的,,我們?cè)? makefile文件中可以看到它們的值,。它們指示了在運(yùn)行域中各個(gè)輸出段所處的地址空間| Image$$RO$$Base| 就是ro段在運(yùn)行域中的起始地址,|Image$$RO$$Limit| 是ro段在運(yùn)行域中的截止地址,。其它依次類推,。我們可以在linker的output中指定,在 simple模式中,,ro base對(duì)應(yīng)的就是| Image$$RO$$Base|,,rw base 對(duì)應(yīng)的是|Image$$RW$$Base|,由于rw和zi相連,,|Image$$ZI$$Base| 就等于|Image$$ZI$$limit| .其它的值都是編譯器自動(dòng)計(jì)算出來(lái)的,。
                 下面是2410啟動(dòng)代碼的搬運(yùn)部分,我給出注釋
            BaseOfROM DCD |Image$$RO$$Base|
            TopOfROM DCD |Image$$RO$$Limit|
            BaseOfBSS DCD |Image$$RW$$Base|
            BaseOfZero DCD |Image$$ZI$$Base|
            EndOfBSS DCD |Image$$ZI$$Limit|
            adr r0, ResetEntry;    ResetEntry是復(fù)位運(yùn)行時(shí)域的起始地址,,在boot
            nand中一般是0
            ldr r2, BaseOfROM;
            cmp r0, r2
            ldreq r0, TopOfROM;TopOfROM=0x30001de0,,代碼段地址的結(jié)束
            beq InitRam
            ldr r3, TopOfROM
            ;part 1,,通過(guò)比較,,將ro搬到sdram里,,搬到的目的地址從 | Image$$RO$$Base| 開(kāi)始,到|Image$$RO$$Limit|結(jié)束
           
            0
            ldmia r0!, {r4-r7}
            stmia r2!, {r4-r7}
            cmp r2, r3
            bcc %B0;
           
            ,;part 2,,搬rw段到sdram,目的地址從|Image$$RW$$Base| 開(kāi)始,,到|Image$$ZI$$Base|結(jié)束
            sub r2, r2, r3;r2=0
            sub r0, r0, r2   
            InitRam ;carry rw to baseofBSS
            ldr r2, BaseOfBSS ;TopOfROM=0x30001de0,baseofrw
            ldr r3, BaseOfZero ;BaseOfZero=0x30001de0
            0
            cmp r2, r3
            ldrcc r1, [r0], #4
            strcc r1, [r2], #4
            bcc %B0
            ,;part 3,將sdram zi初始化為0,,地址從|Image$$ZI$$Base|到|Image$$ZI$$Limit|
            mov r0, #0;init 0
            ldr r3, EndOfBSS;EndOfBSS=30001e40
            1
            cmp r2, r3
            strcc r0, [r2], #4
            bcc %B1

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多