Arm Ads Scatter File
description
Transcript of 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
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
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
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
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
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
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
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
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