Keil sct分散加載文件

博主是個還沒入門的弱菜,老師讓查資料因此我把本身找的資料整理一下擱在這裏方便之後查閱用的,本身並無試過。編程

若有錯誤,歡迎指正。佈局

參考資料:

《ARM體系結構與編程》

keil .sct分散加載文件及其應用

keil分散加載文件*.sct

Keil下分散加載文件

分散加載描述文件

 

首先介紹幾個概念:this

1.ARM映像文件

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

2.ARM映像文件各組成部分的地址映射

分散加載機制容許爲連接器指定映像的存儲器映射信息,可實現對映像組件分組和佈局的全面控制。分散加載一般僅用於具備複雜存儲器映射的映像(儘管也可用於簡單映像),也就是適合加載和執行時內存映射中的多個區是分散的狀況。blog

要構建映像的存儲器映射,連接器必須有:描述節如何分組成區的分組信息、描述映像區在存儲器映射中的放置地址的放置信息。排序

分散加載區域分兩類:ip

  • 加載區:該映像文件開始運行前存放的區域,即當系統啓動或加載時應用程序存放的區域。
  • 執行區:映像文件運行時的區域,即系統啓動後,應用程序進行執行和數據訪問的存儲器區域,系統在實時運行時能夠有一個或多個執行塊。

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)
    }
}
相關文章
相關標籤/搜索