Arm Ads Scatter File

9
ARM ADS Scatter File 何文智 Stanley.Ho 何謂 Scatter File Scatter File(分散式載入描述文年)用於 armlink 的輸入參數,它用來指定映像檔內部各個區域的 載入位置以及執行時的位置。armlink 將會根據 scatter file 產生一些區域相關的符號,讓使用者 建立執行時期的環境使用。 使用 scatter file 的時機 1. 系統存在複雜的位址映射:如程式和資料需要分開放在多個區域。 2. 系統存在多種儲存設備:如包含了 NOR/NAND FlashROMSDRAMSRAM 等。我 們會根據程式與資料的特性分別存放於不同的儲存設備之中,比如將中斷處理程式放於 SRAM 來提升程式執行的效率,而把相較之下比較不常用的程式放於速度較慢的 Flash 之中。 3. 函數的位址固定定位:可以利用 scatter file 實做出把某個函式放在固定位址上,而不用 管應用程式是否已經改變或重編譯。 4. 指定 dataheap stack 位址:可以利用 scatter file 指定 dataheap stack 的位置。 Scatter File 範例 簡單的記憶體配置 LOAD_ROM 0x0000 0x8000 { EXEC_ROM 0x0000 0x8000 { *(+RO) } RAM 0x10000 0x6000 { *(+RW, +ZI) } } 說明: LOAD_ROM(下載區域名稱) 0x0000(下載區域起始地址) 0x8000(下載區域大小) { EXEC_ROM(第一執行區域名稱) 0x0000(第一執行區域起始地址) 0x8000(第一執行區域結 束位址) { *(+RO(程式碼為唯讀數據)) 1/9

description

 

Transcript of Arm Ads Scatter File

Page 1: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

何謂 Scatter FileScatter File(分散式載入描述文年)用於 armlink 的輸入參數,它用來指定映像檔內部各個區域的

載入位置以及執行時的位置。armlink 將會根據 scatter file 產生一些區域相關的符號,讓使用者

建立執行時期的環境使用。

使用 scatter file 的時機

1. 系統存在複雜的位址映射:如程式和資料需要分開放在多個區域。

2. 系統存在多種儲存設備:如包含了 NOR/NAND Flash,ROM,SDRAM,SRAM 等。我

們會根據程式與資料的特性分別存放於不同的儲存設備之中,比如將中斷處理程式放於

SRAM 來提升程式執行的效率,而把相較之下比較不常用的程式放於速度較慢的 Flash之中。

3. 函數的位址固定定位:可以利用 scatter file 實做出把某個函式放在固定位址上,而不用

管應用程式是否已經改變或重編譯。

4. 指定 data,heap 及 stack 位址:可以利用 scatter file 指定 data,heap 及 stack 的位置。

Scatter File 範例

簡單的記憶體配置

LOAD_ROM 0x0000 0x8000

{

  EXEC_ROM 0x0000 0x8000

  {

    *(+RO)

  }

  RAM 0x10000 0x6000

  {

   *(+RW, +ZI)

  }

}

說明:

LOAD_ROM(下載區域名稱) 0x0000(下載區域起始地址) 0x8000(下載區域大小)

{

  EXEC_ROM(第一執行區域名稱) 0x0000(第一執行區域起始地址) 0x8000(第一執行區域結

束位址)

  {

    *(+RO(程式碼為唯讀數據))

1/9

Page 2: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

  }

  RAM(第二執行區域名稱) 0x10000(第二執行區域起始地址) 0x6000(第二執行區域大小)

  {

   *(+RW(讀寫變量), +ZI(未初始化變數))

  }

}

複雜的記憶體配置

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(下載區域一起始地址)

{

  EXEC_ROM_1 0x0000(第一執行區域開始地址)

  {

   program1.o(+RO) (program1.o内的Code與 RO data 放在第一執行區域)

  }

  DRAM 0x18000(第二執行區域開始地址) 0x8000(第二執行區域大小)

  {

    program1.o (+RW, +ZI) (program1.o内的RW data與 ZI data 放在第二執行區域)

2/9

Page 3: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

  }

}

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

{

  EXEC_ROM_2 0x4000

  {

   program2.o(+RO) (program2.o内的Code與 RO data 放在第一執行區域)

  }

  SRAM 0x8000 0x8000

  {

   program2.o (+RW, +ZI) (program2.o内的RW data與 ZI data 放在第二執行區域)

  }

}

armlink 命令參數說明

armlink [-help] [-vsn] [-partial] [-output file] [-elf] [-reloc][-ro-base address] [-ropi]

[-rw-base address] [-rwpi] [-split]

[-scatter file][-debug|-nodebug][-remove?RO/RW/ZI/DBG]|-noremove] [-entry location ]

[-keep section-id] [-first section-id] [-last section-id] [-libpath pathlist] [-scanlib|-noscanlib] [-locals|-nolocals] [-callgraph] [-info topics] [-map] [-symbols] [-symdefs file] [-edit file] [-xref] [-xreffrom object(section)] [-xrefto object(section)] [-errors file] [-list file] [-verbose]

[-unmangled |-mangled] [-match crossmangled][-via file] [-strict]

[-unresolved symbol][-MI|-LI|-BI] [input-file-list]

上面各選項的含義分彆為:

-help

這個選項會列出在命令行中常用的一些選項操作。

-vsn

這個選項顯示出所用的 armlink 的版本信息。

-partial

用這個選項創建的是部分鏈接的目標文件而不是可執行映像文件。

-output file

這個選項指定了輸出文件名,該文件可能是部分鏈接的目標文件,也可能是可執行映像文件。如果輸出文件名沒

有特號指定的話,armlink 將使用下面的預設:

如果輸出是一個可執行映像文件,則生成的輸出文件名為__image.axf;

如果輸出是一個部分鏈接的目標文件,在生成的文件名為__object.o;

如果没有指定輸出文件的路徑信息,則輸出文件就在當前目録下生成。如果指定了路徑信息,則所指定的路徑成

為輸出文件的當前路徑。

3/9

Page 4: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

-elf

這個選項生成 ELF 格式的映像文件,這也是 armlink 所支持的唯一的一種輸出格式,這是預設選項。

-reloc

這個選項生成可重定址的映像。

一個可重定址的映像具有動態的段,這個段中包含可重定址信息,利用這些信息可以在鏈接後,進行映像文件的

重新定址;

-reloc,-rw-base 一起使用,但是如果没有-split 選項,鏈接時會産生錯誤。

-ro-base address

這個選項將包含有 RO(Read-Only 屬性)輸出段的加載地址和運行地址設置為 address,該地址必須是字對齊的,如

果没有指定這個選項,則預設的 RO 基地址值為 0x8000。

-ropi

這個選項使得包含有 RO 輸出段的加載域和運行域是位置無關的。如果該選項没有使用,則相應的域被標記為絶

對的。通常每一個只讀屬性的輸入段必須是只讀位置無關的。如果使用了這個選項,armlink 將會進行以下操作:

檢查各段之間的重定址是否有效;

確保任何由 armlink 自身生成的代碼是只讀位置無關的。

這裏希望注意的是,ARM 工具直到 armlink 完成了對輸入段的處理後,才能够决定最終的生成映像是否為只讀位

置無關的。這就意味着 ,即使為編譯器和匯編器指定了 ROPI 選項,armlink 也可能會産生 ROPI 錯誤信息。

-rw-base address

這個選項設置包含 RW(Read/Write 屬性)輸出段的域的運行時地址,該地址必須是字對齊的。

如果這個選項和-split 選項一起使用,將設置包含 RW 輸出段的域的加載和運行時地址都設置在 address 處。

-rwpi

這個選項使得包含有 RW 和 ZI(Zero Initialization,初始化為 0)屬性的輸出段的加載和運行時域為位置無關的。如

果該選項没有使用,相應域標記為絶對的。這個選項要求-rw- base 選項後有值,如果-rw-base 没有指定的話,預

設值為 0,即相當于-rw-base 0。通常每一個可寫的輸入段必須是可讀/ 可寫的位置無關的。

如果使用了該選項,armlink 會進行以下的操作:

檢查可讀/可寫屬性的運行域的輸入段是否設置了位置無關屬性;

檢查在各段之間的重定址是否有效;

生成基於静態寄存器 sb 的條目,這些在 RO 和 RW 域被拷貝和初始化的時候會用到。

編譯器並不會强制可寫的數據一定要為位置無關的,這就是説,即使在為編譯器和匯編器指定了 RWPI 選項,

armlink 也可能生成數據不是 RWPI 的信息。

-split

這個選項將包含 RO 和 RW 屬性的輸出段的加載區,分割成 2 個加載區。一個是包含 RO 輸出 段的加載區,預設

的加載地址為 0x8000,但是可以用-ro-base 選項設置其他的地址值,另一個加載域包含 RO 屬性的輸出段,由-rw-base 選 項指定加載地址,如果没有使用-rw-base 選項的話,預設使用的是-rw-base 0。

-scatter file

這個選項使用在 file 中包含的分組和定位訊息來創建映像記憶體配置。

4/9

Page 5: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

一個實際參考範例

1.main.c//************************************************************************************************************//【 版 權 】Copyright (c) 2007-2008 gliethttp////【 文 件 版 本 】v1.x////【 文 件 名 稱 】main.c////【 創 建 日 期 】2007-04-12////【 功 能 描 述 】//************************************************************************************************************#include <stdio.h>//---------------------------------------------------------------------------------------------------------------------static char rs_code = 0x88;extern int add1(int x);#define uint8 unsigned char#define uint32 unsigned long//---------------------------------------------------------------------------------------------------------------------//【 版 本 】v1.0//【 函 數 名 稱 】int main(void)//【 創建人及創建時間 】gliethttp 2007-04-12//【 修改人及修改時間 】

//【 修 改 原 因 】

//【 功 能 描 述 】//---------------------------------------------------------------------------------------------------------------------int main(void){extern uint32 Load$$r1_exec_rom1$$Base; extern uint32 Image$$r1_exec_rom1$$Base; extern uint32 Image$$r1_exec_rom1$$Length; extern uint32 Image$$r1_exec_rom1$$Limit;

extern uint32 Load$$r1_exec_ram1$$Base; extern uint32 Image$$r1_exec_ram1$$Base; extern uint32 Image$$r1_exec_ram1$$Length; extern uint32 Image$$r1_exec_ram1$$Limit;

extern uint32 Load$$r2_exec_ram1$$Base; extern uint32 Image$$r2_exec_ram1$$Base; extern uint32 Image$$r2_exec_ram1$$Length; extern uint32 Image$$r2_exec_ram1$$Limit;

extern uint32 Load$$r2_exec_ram2$$Base; extern uint32 Image$$r2_exec_ram2$$Base; extern uint32 Image$$r2_exec_ram2$$Length; extern uint32 Image$$r2_exec_ram2$$Limit; char tmp[100];

sprintf(tmp,"Hello%c",rs_code);

sprintf(tmp,"0x%lX",(uint32)&Load$$r1_exec_rom1$$Base); sprintf(tmp,"0x%lX",(uint32)&Image$$r1_exec_rom1$$Base); sprintf(tmp,"0x%lX",(uint32)&Image$$r1_exec_rom1$$Length); sprintf(tmp,"0x%lX",(uint32)&Image$$r1_exec_rom1$$Limit);

5/9

Page 6: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

sprintf(tmp,"0x%lX",(uint32)&Load$$r1_exec_ram1$$Base); sprintf(tmp,"0x%lX",(uint32)&Image$$r1_exec_ram1$$Base); sprintf(tmp,"0x%lX",(uint32)&Image$$r1_exec_ram1$$Length); sprintf(tmp,"0x%lX",(uint32)&Image$$r1_exec_ram1$$Limit);

sprintf(tmp,"0x%lX",(uint32)&Load$$r2_exec_ram1$$Base); sprintf(tmp,"0x%lX",(uint32)&Image$$r2_exec_ram1$$Base); sprintf(tmp,"0x%lX",(uint32)&Image$$r2_exec_ram1$$Length); sprintf(tmp,"0x%lX",(uint32)&Image$$r2_exec_ram1$$Limit);

sprintf(tmp,"0x%lX",(uint32)&Load$$r2_exec_ram2$$Base); sprintf(tmp,"0x%lX",(uint32)&Image$$r2_exec_ram2$$Base); sprintf(tmp,"0x%lX",(uint32)&Image$$r2_exec_ram2$$Length); sprintf(tmp,"0x%lX",(uint32)&Image$$r2_exec_ram2$$Limit);

add1(2);}//---------------------------------------------------------------------------------------------------------------------//【 版 本 】v1.0//【 函 數 名 稱 】void gliethttp(void)//【 創建人及創建時間 】gliethttp 2007-04-12//【 修改人及修改時間 】

//【 修 改 原 因 】

//【 功 能 描 述 】入口函數測試//---------------------------------------------------------------------------------------------------------------------#pragma arm section code = "gliethttp_startup"void gliethttp(void){ main(); for(;;);}#pragma arm section code

2.pragma_arm_section_example.c//*********************************************************************************************************************//【 版 權 】Copyright (c) 2007-2008 gliethttp////【 文 件 版 本 】v1.x////【 文 件 名 稱 】pragma_arm_section_example.c////【 創 建 日 期 】2007-04-12////【 功 能 描 述 】//*********************************************************************************************************************#include <stdio.h>//---------------------------------------------------------------------------------------------------------------------void xxxprintf(char *fmt);/*ads幫助文件 3-1The full syntax for the pragma is :#pragma arm section [sort_type[[=]"name"]] [,sort_type="name"]*Where name is the name to use for the section and sort_type is one of:coderwdatarodatazidata.

6/9

Page 7: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

If sort_type is specified but name is not, the section name for sort_type is reset to the default value. Enter #pragma arm section on its own to restore the names of all object sections to their defaults. See Example 3-1.Example 3-1 Section naming 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 codeUse a scatter-loading description file with the linker to control placing a named section at a particular address in memory*/int x1 = 5; // in .data (default)char y1[100]; // in .bss (default)int const z1[3] = {1,2,3}; // in .constdata (default)char *s1 = "abc"; // s1 in .data (default), "abc" in .constdata (default)//---------------------------------------------------------------------------------------------------------------------//【 版 本 】v1.0//【 函 數 名 稱 】int add1(int x)//【 創建人及創建時間 】gliethttp 2007-04-12//【 修改人及修改時間 】

//【 修 改 原 因 】

//【 功 能 描 述 】//---------------------------------------------------------------------------------------------------------------------#pragma arm section rwdata = "foo", rodata = "bar"//接下來定義的所有 rw,ro 數據都會放到相應的 foo 和 bar 段中,直到遇到釋放占

用權語句

//1.#pragma arm section code 釋放 code占用權 ,回.code (default) //2.#pragma arm section rwdata 釋放 rwdata占用權,回.data (default) //3.#pragma arm section rodata 釋放 rodata占用權,回.constdata (default) //4.#pragma arm section zidata 釋放 zidata占用權,回.data (default)

int x2 = 5; // in foo (data part of region)char y2[100]; // in .bssint const z2[3] = {1,2,3}; // in barchar *s2 = "abc"; // s2 in foo, "abc" in bar

#pragma arm section rodata //釋放 rodata 的占用權,還給 default,所以下邊的所有 rodata全都會放到.constdata (default)中

int x3 = 5; // in foochar y3[100]; // in .bssint const z3[3] = {1,2,3}; // in .constdatachar *s3 = "abc"; // s3 in foo, "abc" in .constdata

#pragma arm section code = "foo"//獲取 code 的占用權

7/9

Page 8: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

int add1(int x) // in foo (code part of region){char tmp[100]; sprintf(tmp,"out%d",x1); sprintf(tmp,"out%d",x2); sprintf(tmp,"out%d",x3); printf(y1,"ab%s","y1"); printf(y2,"ab%s","y1"); printf(y3,"ab%s","y1"); sprintf(tmp,"z[0]=%d,z[1]=%d,z[2]=%d",z1[0],z1[1],z1[2]); sprintf(tmp,"z[0]=%d,z[1]=%d,z[2]=%d",z2[0],z2[1],z2[2]); sprintf(tmp,"z[0]=%d,z[1]=%d,z[2]=%d",z3[0],z3[1],z3[2]); printf(s1); printf(s2); printf(s3);

xxxprintf("hello world!\r\n"); return x+1;} #pragma arm section code //表示釋放前面的 code 設置 回到預設,也就是說 該#pragma arm section code 下的所有 code 段將都

會放到預設 code 段中//---------------------------------------------------------------------------------------------------------------------//【 版 本 】v1.0//【 函 數 名 稱 】int main(void)//【 創建人及創建時間 】gliethttp 2007-04-12//【 修改人及修改時間 】

//【 修 改 原 因 】

//【 功 能 描 述 】//---------------------------------------------------------------------------------------------------------------------void xxxprintf(char *fmt){ printf(fmt);}

3.pragma_arm_section_example.map(scatter file);//***********************************************************************************************************;//【 版 權 】Copyright (c) 2007-2008 gliethttp;//;//【 文 件 版 本 】v1.x;//;//【 文 件 名 稱 】main.c;//;//【 創 建 日 期 】2007-04-12;//;//【 功 能 描 述 】;//***********************************************************************************************************

;//---------------------------------------------------------------------------------------------------------------------;//【 版 本 】v1.0;//【 函 數 名 稱 】load_region1 0x30000000 0x4000000;//【 創建人及創建時間 】gliethttp 2007-04-12;//【 修改人及修改時間 】

;//【 修 改 原 因 】

;//【 功 能 描 述 】加載地址域 1,用于存放運行時的程序

;// 引用方式 load_region1$$r1_exec_rom1$$Base,load_region1$$r1_exec_rom1$$Limit;// 引用方式 load_region1$$r1_exec_ram1$$Base,load_region1$$r1_exec_ram1$$Limit;//---------------------------------------------------------------------------------------------------------------------

load_region1 0x30000000 0x4000000 ;load 加載域 入口起始地址 0x30000000 長度 0x4000000 64M{

8/9

Page 9: Arm Ads Scatter File

ARM ADS Scatter File 何文智 Stanley.Ho

r1_exec_rom1 +0x00 ;exec 執行域 起址 0x30000000+0x00 { main.o(gliethttp_startup,+First) ;input 輸入域 main.o 中的 gliethttp_startup 段作為起始加載地址

* (+RO-CODE,+RO-DATA) ;所有目標文件都存放到 main.o 的後邊 * (+RO-CODE,+RO-DATA)等效于* (+RO) RO-CODE 對應 CODE;RO-DATA 對應 CONST;RO 對應 TEXT;RW 對應 DATA;ZI 對應 BSS }

r1_exec_ram1 +0x00;0x50000000 ;+0x00表示接續前一個執行域 r1_exec_rom1 的結束地址為開始,加上偏移量 0x00,對r1_exec_ram1 域中的?容編址

{ ;0x50000000表示 exec_ram1 執行域的起始地址為 0x50000000,不過最好不要這樣寫,不是很清楚,比較混亂

* (+RW);* (+RW,+ZI) ;所有目標文件和庫文件的 RW 和 ZI 段存放在該區域

}};//---------------------------------------------------------------------------------------------------------------------;//【 版 本 】v1.0;//【 函 數 名 稱 】Image +0;//【 創建人及創建時間 】gliethttp 2007-04-12;//【 修改人及修改時間 】

;//【 修 改 原 因 】

;//【 功 能 描 述 】防止報錯

;// 引用方式 Image$$ZI$$Base,Image$$ZI$$Limit;//---------------------------------------------------------------------------------------------------------------------Image +0 ;+0 接著 load_region1 域的結束地址存放該 Image 加載域中的內容

{ ;只能這樣否則提示:Undefined symbol Image$$ZI$$Limit(referred from sys_statckheap.o). ZI +0 { * (+ZI) }};//---------------------------------------------------------------------------------------------------------------------;//【 版 本 】v1.0;//【 函 數 名 稱 】load_region2 0x20000 0x4000;//【 創建人及創建時間 】gliethttp 2007-04-12;//【 修改人及修改時間 】

;//【 修 改 原 因 】

;//【 功 能 描 述 】分部 sram;// 引用方式 load_region2$$r2_exec_ram1$$Base,load_region2$$r2_exec_ram1$$Limit;// 引用方式 load_region2$$r2_exec_ram2$$Base,load_region2$$r2_exec_ram2$$Limit;//---------------------------------------------------------------------------------------------------------------------load_region2 0x2000000 0x40000{ r2_exec_ram1 0x20000 0x4000 ;分部

{ pragma_arm_section_example.o(foo) } r2_exec_ram2 0x2300000 ;分部

{ pragma_arm_section_example.o(bar) }}

9/9