一.ADS分散加載
分散加載能夠將加載和運行時存儲器中的代碼和數據描述在被稱爲分散加載描述文件的一個文本描述文件中,以供連接時使用。
(1)分散加載區
分散加載區域分爲兩類:
• 加載區,包含應用程序復位和加載時的代碼和數據。
• 執行區,包含應用程序執行時的代碼和數據。應用程序啓動過程中,從每個加載區可創建一個或多個執行區。
映象中所有的代碼和數據準確地分爲一個加載區和一個執行區。
(2)分散加載文件示例
ROM_LOAD 0x0000 0x4000
{
ROM_EXEC 0x0000 0x4000; Root region
{
* (+RO); All code and constant data
}
RAM 0x10000 0x8000
{
* (+RW, +ZI); All non-constant data
}
}
(3)分散加載文件語法
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: 加載區,用來保存永久性數據(程序和只讀變量)的區域;
execution_region: 執行區,程序執行時,從加載區域將數據複製到相應執行區後才能被正確執行;
load_region_name: 加載區域名,用於“Linker”區別不同的加載區域,最多31個字符;
start_address: 起始地址,指示區域的首地址;
+offset: 前一個加載區域尾地址+offset 做爲當前的起始地址,且“offset”應爲“0”或“4”的倍數;
attributes: 區域屬性,可設置如下屬性:
PI 與地址無關方式存放;
RELOC 重新部署,保留定位信息,以便重新定位該段到新的執行區;
OVERLAY 覆蓋,允許多個可執行區域在同一個地址,ADS不支持;
ABSOLUTE 絕對地址(默認);
max_size: 該區域的大小;
execution_region_name:執行區域名;
start_address: 該執行區的首地址,必須字對齊;
+offset: 同上;
attributes: 同上;
PI 與地址無關,該區域的代碼可任意移動後執行;
OVERLAY 覆蓋;
ABSOLUTE 絕對地址(默認);
FIXED 固定地址;
UNINIT 不用初始化該區域的ZI段;
module_select_pattern: 目標文件濾波器,支持通配符“*”和“?”;
*.o匹配所有目標,* (或“.ANY”)匹配所有目標文件和庫。
input_section_attr: 每個input_section_attr必須跟隨在“+”後;且大小寫不敏感;
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,用於指定存放在一個執行區域的第一個或最後一個區域;
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”指定了但沒有指定“name”,那麼之前的修改的段名將被恢復成默認值。
#pragma arm section // 恢復所有段名爲默認設置。
應用:
#pragma arm section rwdata = "SRAM",zidata = "SRAM"
static OS_STK SecondTaskStk[256]; // “rwdata”“zidata”將定位在“sram”段中。
#pragma arm section // 恢復默認設置
(4)程序中對區域地址引用的方法
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: 加載區,即存放地址;
Image: 執行區,即運行地址;
Base: 區首地址;
Limit: 區尾地址;
Length: 區長度;
region_name: RO、RW、ZI、load_region_name、execution_region_name;
例如:
“RAM1”區域的首地址: 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++;
}
}
二.分散加載應用
前面提到過,從NAND Flash啓動,對於S3C2410而言,由於片內具有4K的稱作"SteppingStone"的SRAM,NAND FLASH的最低4K代碼可以自動複製到"SteppingStone",因此可以將初始化等代碼放在NAND FLASH的低4K區域內,其他的代碼放置在4K以外,在初始化代碼內將這些代碼複製到外部SDRAM,從而這些代碼可以在外部SDRAM內運行。
1.應用實例描述
先完成初始化操作,並且在初始化代碼中將NAND FLASH的4K範圍以外的代碼(簡單起見,這部分代碼可以操作LED燈)複製到外部SDRAM中。主要目的是使用分散加載文件以及將NAND FLASH中的數據代碼複製到SDRAM中。
2.分散加載文件
NAND_FLASH_LOAD 0x0 0x1000
{
RAM_EXEC +0 0x1000
{
;參見前面的加載文件語法
}
}
NAND_FLASH_LOAD2 0x1000
{
SDRAM_EXEC 0x30000000
{
;參見前面的加載文件語法
}
}
(1)將一些初始化代碼放在第一個加載區(根區:加載地址和執行地址相同的區域,每一個分散加載描述文件必須至少要有一個根區。),地址範圍
爲:0x0000~0x0fff的4K,其執行區的地址範圍也是0x0000~0x0fff的4K,這正好是NAND
FLASH啓動時自動複製的地址範圍。
(2)其他代碼放在第2個加載區,從地址0x1000開始,由於這一部分不能自動複製,因此在初始化代碼中應該將這一部分複製到外部SDRAM中,其執行區的起始地址爲外部SRDAM的地址。
3. 二進制文件燒錄
由於有2個加載區,因此生成的二進制文件有2個,文件名對應於相應的執行區名,分別是RAM_EXEC和SDRAM_EXEC,需要注意的是,應該 將存放初始化代碼的加載區對應的二進制文件RAM_EXEC燒錄NAND FLASH的低4K區域,第二個加載區對應的二進制文件SDRAM_EXEC燒錄到4K以後的區域。這個可以通過修改Samsuang的sjf燒錄程序實 現,原來的燒錄程序是按BLOCK(16K)燒錄,可以修改爲按4K的Section燒錄,即將1個Block分爲4個Section(4K)。主要修改 k9s1208.c中的K9S1208_Program函數,需要注意的是,由於NAND FLASH寫入前應該擦除,擦除是按Block擦除,由於現在是按Section寫,因此應該注意只有在第1次寫某一塊中的Section前進行擦除,以 後再寫着一塊的其它Section前不能再進行擦除。
這樣RAM_EXEC燒錄到0 SECTION,SDRAM_EXEC燒錄到1 SECTION開始的以後的區域中,完成後復位即可。
參考資料:
1. ads下分散加載文件,http://hxdlj.spaces.live.com/blog/cns!1083C4D05B5E5E09!152.entry
2. S3C2410數據手冊
3. ARM DUI 0203BSC,RealView 編譯工具 2.0 版 開發者指南,http://infocenter.arm.com/help/index.jsp
4. FS2410光盤