博主是個還沒入門的弱菜,老師讓查資料因此我把本身找的資料整理一下擱在這裏方便之後查閱用的,本身並無試過。編程
若有錯誤,歡迎指正。佈局
首先介紹幾個概念:this
ARM映像文件是一個層次性結構的文件,其中包含了域(region)、輸出段(output section)和輸入段(input section)。各部分關係以下:url
輸入段中包含了4類內容:代碼、已經初始化的數據、未經初始化的存儲區域、內容初始化成0的存儲區域。每一個輸入段有相應的屬性,能夠爲只讀的(RO)、可讀寫的(RW)以及初始化成0的(ZI)。ARM鏈接器根據各輸入段的屬性將這些輸入段分組,再組成不一樣的輸出段以及域。spa
一個輸出段中包含了一系列的具備相同的RO、RW和ZI屬性的輸入段。輸出段的屬性與其中包含的輸入段的屬性相同。在一個輸出段內部,各輸入段是按照必定的規則排序的,這個後面再補充。.net
一個域中包含了1~3個輸出段,其中各輸出段的屬性各不相同。各輸出段的排列順序是由其屬性決定的。其中,RO屬性的輸出段排在最前面,其次是RW屬性的輸出段,最後是ZI屬性的輸出段。一個域一般映射到一個物理存儲器上,如ROM和RAM等。code
分散加載機制容許爲連接器指定映像的存儲器映射信息,可實現對映像組件分組和佈局的全面控制。分散加載一般僅用於具備複雜存儲器映射的映像(儘管也可用於簡單映像),也就是適合加載和執行時內存映射中的多個區是分散的狀況。blog
要構建映像的存儲器映射,連接器必須有:描述節如何分組成區的分組信息、描述映像區在存儲器映射中的放置地址的放置信息。排序
分散加載區域分兩類:ip
分散加載文件是一個文本文件,經過編寫一個分散加載文件來指定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)) * ")"] } }
PI 與地址無關方式存放;
RELOC 從新部署,保留定位信息,以便從新定位該段到新的執行區;
OVERLAY 覆蓋,容許多個可執行區域在同一個地址,ADS不支持;
ABSOLUTE 絕對地址(默認);
PI 與地址無關,該區域的代碼可任意移動後執行;
OVERLAY 覆蓋;
ABSOLUTE 絕對地址(默認);
FIXED 固定地址;
UNINIT 不用初始化該區域的ZI段;
*.o匹配全部目標,* (或「.ANY」)匹配全部目標文件和庫。
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,同上;
彙編中指定段:
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) } }