博主是個還沒入門的弱菜,老師讓查資料所以我把自己找的資料整理一下擱在這里方便以后查閱用的,自己並沒有試過。
如有錯誤,歡迎指正。
參考資料:
《ARM體系結構與編程》
keil .sct分散加載文件及其應用
keil分散加載文件*.sct
Keil下分散加載文件
分散加載描述文件
首先介紹幾個概念:
1.ARM映像文件
ARM映像文件是一個層次性結構的文件,其中包含了域(region)、輸出段(output section)和輸入段(input section)。各部分關系如下:
- 一個映像文件由一個或多個域組成
- 每個域包含一個或多個輸出段
- 每個輸出段包含一個或多個輸入段
- 各輸入段包含了目標文件中的代碼和數據
輸入段中包含了4類內容:代碼、已經初始化的數據、未經初始化的存儲區域、內容初始化成0的存儲區域。每個輸入段有相應的屬性,可以為只讀的(RO)、可讀寫的(RW)以及初始化成0的(ZI)。ARM連接器根據各輸入段的屬性將這些輸入段分組,再組成不同的輸出段以及域。
一個輸出段中包含了一系列的具有相同的RO、RW和ZI屬性的輸入段。輸出段的屬性與其中包含的輸入段的屬性相同。在一個輸出段內部,各輸入段是按照一定的規則排序的,這個后面再補充。
一個域中包含了1~3個輸出段,其中各輸出段的屬性各不相同。各輸出段的排列順序是由其屬性決定的。其中,RO屬性的輸出段排在最前面,其次是RW屬性的輸出段,最后是ZI屬性的輸出段。一個域通常映射到一個物理存儲器上,如ROM和RAM等。
2.ARM映像文件各組成部分的地址映射
分散加載機制允許為鏈接器指定映像的存儲器映射信息,可實現對映像組件分組和布局的全面控制。分散加載通常僅用於具有復雜存儲器映射的映像(盡管也可用於簡單映像),也就是適合加載和執行時內存映射中的多個區是分散的情況。
要構建映像的存儲器映射,鏈接器必須有:描述節如何分組成區的分組信息、描述映像區在存儲器映射中的放置地址的放置信息。
分散加載區域分兩類:
- 加載區:該映像文件開始運行前存放的區域,即當系統啟動或加載時應用程序存放的區域。
- 執行區:映像文件運行時的區域,即系統啟動后,應用程序進行執行和數據訪問的存儲器區域,系統在實時運行時可以有一個或多個執行塊。
3.分散加載文件(即scatter file,后綴為.scf)
分散加載文件是一個文本文件,通過編寫一個分散加載文件來指定ARM連接器在生成映像文件時如何分配RO,RW,ZI等數據的存放地址。如果不用SCATTER文件指定,那么ARM連接器會按照默認的方式來生成映像文件,一般情況下我們是不需要使用分散加載文件的。
但在某些場合,我們希望把某些數據放在指定的地址處,那么這時候SCATTER文件就發揮了非常大的作用。而且SCATTER文件用起來非常簡單好用。
舉個例子:比如像LPC2378芯片具有多個不連續的SRAM,通用的RAM是32KB,可是32KB不夠用,我想把某個.C中的RW數據放在USB的SRAM中,那么就可以通過SCATTER文件來完成這個功能。
分散加載文件的語法:
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 // 恢復默認設置
樣例:
簡單存儲器映射實例
LOAD_ROM 0x0000 0x8000 //Name of load region, Start address for load region, Maximum size of load region { EXEC_ROM 0x0000 0x8000 //Name of first exec region, Start address for exec region, Maximum size of this region { *(+RO) //Place all code and RO data into this exec region } RAM 0x10000 0x60000 //Start of second exec region { *(+RW, +ZI) //Place all RW and ZI data into this exec region } }
復雜存儲器映射實例:
LOAD_ROM_1 0x0000 //Start address for first load region { EXEC_ROM_1 0x0000 //Start address for first exec region { program1.o (+RO) //Place all code and RO data from program1.o into this exec region } DRAM 0x18000 0x8000 //Start address for this exec region Maximum size of this exec region { program1.o (+RW, +ZI) //Place all RW and ZI data from program1.o into this exec region } } LOAD_ROM_2 0x4000 //Start address for second load region { EXEC_ROM_2 0x4000 { program2.o (+RO) //Place all code and RO data from program2.o into this exec region } SRAM 0x8000 0x8000 { program2.o (+RW, +ZI) //Place all RW and ZI data from program2.o into this exec region } }
具體格式描述請參考資料: 分散加載描述文件
一個具體的例子:
; ************************************************************* ; * Scatter-Loading Description File generated by uVision * ; ************************************************************* LR_IROM1 0x00000000 0x00080000 { ; 第一個加載域,名字是LR_IROM1,起始地址0x00000000 大小是0x00080000 ER_IROM1 0x00000000 0x00080000 { ; 第一個運行時域,名字是ER_IROM1 起始地址0x00000000 大小事0x00080000 *.o (RESET, +First) ; IAP第一階段在FLASH中運行 *(InRoot$$Sections) ; All library sections that must be in a root region .ANY (+RO) ; .ANY與*功能相似,用.ANY可以把已經被指定的具有RW,ZI屬性的數據排除 } RW_IRAM1 0x10000000 0x00010000 { ; RW data .ANY(+RW +ZI) } RW_SDRAM1 0xA0000000 0x00800000 { ; RW data STARTUP_LPC177X_8X.o (HEAP) ;HEAP用來定位堆棧的底 *.LIB(+RW +ZI) } }