轉自:http://blog.chinaunix.net/uid-23510468-id-139313.htmlhtml
晚上作嵌入式實驗的時候發現,當我把c文件和彙編語言s文件放到一個項目中時,debug的起點不知道跑到哪裏去了,因此我開始思考怎麼控制程序的入口地址。
後來日後翻實驗指導書,發現後面就有解釋,因而我知道了還有分散加載描述文件這麼個高大上的東西。
看了看語法,發現有些複雜,因此僅僅將指導書中提供的sct文件看明白了,就罷手,在這裏找到一篇不錯的講sct的文章,在這裏和你們分享以及記錄。c++
這幾天正好在研究NAND Flash,手頭有一塊FS2410開發板。從NAND Flash啓動,對於S3C2410而言,因爲片內具備4K的稱做"SteppingStone"的SRAM,NAND FLASH的最低4K代碼能夠自動複製到"SteppingStone",所以能夠將初始化等代碼放在NAND FLASH的低4K區域內,其餘的代碼放置在4K之外,在初始化代碼內將這些代碼複製到外部SDRAM,從而這些代碼能夠在外部SDRAM內運行。ADS的分散加載功能正好能夠實現這一目的。下面結合實例來講明分散加載文件。
一.ADS分散加載
分散加載可以將加載和運行時存儲器中的代碼和數據描述在被稱爲分散加載描述文件的一個文本描述文件中,以供鏈接時使用。
(1)分散加載區
分散加載區域分爲兩類:
• 加載區,包含應用程序復位和加載時的代碼和數據。
• 執行區,包含應用程序執行時的代碼和數據。應用程序啓動過程當中,從每一個加載區可建立一個或多個執行區。
映象中全部的代碼和數據準確地分爲一個加載區和一個執行區。
(2)分散加載文件示例函數
cROM_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)分散加載文件語法 ```c 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: 段名;
彙編中指定段:ui
cAREA 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|
CMP R1, R2
LDRCC R3, [R0], #4
STRCC R3, [R1], #4
BCC %b0
C 引用:this
cextern 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.分散加載文件.net
cNAND_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開始的之後的區域中,完成後復位便可。debug
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/denlee/archive/2008/05/28/2491332.aspxunix