精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Keil分散加載文件淺析

靈動MM32MCU ? 來源:靈動MM32MCU ? 作者:靈動MM32MCU ? 2023-11-17 10:00 ? 次閱讀

1?

ARM映像文件組成

ARM 映像文件其實就是源文件經編譯器生成的目標文件,一般是bin文件或者hex文件,可以直接燒錄到ROM中執行(一般是內部FLASH),這個文件稱為可執行映像文件(image file)。

映像文件一般由域組成,域最多由三個輸出段組成(RO,RW,ZI)組成,輸出段又由輸入段組成。所謂域,指的就是整個映像文件所處在的區域,它又分為加載域和運行域。我們輸入的代碼,一般有代碼部分和數據部分,這就是所謂的輸入段,經過編譯后就變成了映像文件中的RO段和RW段,還有所謂的ZI段,這就是輸出段。

加載域:映像文件被靜態存放的工作區域。

運行域:程序運行起來的存儲區域。

程序在存儲狀態時,RO段及RW段都被保存在ROM區。

當程序開始運行時,內核直接從 ROM 中讀取代碼,并且在執行主體代碼前,會先執行一段加載代碼,它把 RW 段數據從 ROM 復制到 RAM,并且在 RAM加入 ZI 段,ZI 段的數據都被初始化為 0。加載完后 RAM 區準備完畢,正式開始執行主體程序。

2?

分散加載機制

分散加載機制允許開發者為代碼或數據變量在加載和執行時指定不同的存儲空間,通知鏈接器把程序的某一部分鏈接在存儲器的某個地址空間。

2.1 何時使用分散加載

實現嵌入式系統通常需要分散加載,這些系統使用ROM、RAM和內存映射的外設。通常需要分散加載的情況如下:

1)復雜內存映射:

必須放置在許多不同內存區域的代碼和數據需要詳細的指令來說明在內存空間中放置這些部分的位置。

2)不同類型的內存:

許多系統包含各種物理存儲設備,如FLASH、ROM、SDRAM和快速SRAM。分散加載描述可以將代碼和數據與最合適的內存類型相匹配。例如,中斷代碼可以放在快速的SRAM中以改善中斷響應時間,但不常用的配置信息可以放在較慢的閃存中。

3)內存映射的外設:

分散加載描述可以將數據段放置在內存映射中的精確地址上,以便可以訪問內存映射的外設。

4)函數在固定位置:

即使周圍的應用程序已被修改和重新編譯,也可以將函數放置在內存中的相同位置。這對于跳轉表的實現很有用。

5)使用符號來標識堆和堆棧:

在鏈接應用程序時,可以為堆和堆棧位置定義符號。

2.2 怎么使用分散加載

1)對于具有簡單內存映射(僅有SRAM和ROM)的image文件,可以僅使用鏈接器命令行選項或scatter文件來指定內存映射。下圖顯示了一個簡單的內存映射:

d0f6fe42-8478-11ee-939d-92fbcf53809c.png

2)對于具有復雜內存映射(具有DRAM、SRAM、ROM2、ROM1等)的image文件,不能僅使用鏈接器命令行選項指定內存映射,需要使用scatter文件。下圖顯示了一個復雜的內存映射:

d1036fe2-8478-11ee-939d-92fbcf53809c.png

3?

分散加載文件說明

分散加載文件(scatter file)是一個文本文件,它的作用是可以用于描述 ARM 鏈接器生成映像文件所需要的信息。如果不使用分散加載文件來指定,那么 ARM 鏈接器會按照默認的方式來生成映像文件。Keil的分散加載主要是通過 .sct 文件實現的,鏈接器根據 .sct 文件的配置分配各個段區地址,生成分散加載代碼。

編寫分散加載文件中可以指定下列信息:

1)各個加載域的加載起始地址、最大尺寸和屬性。

2)各個加載域中包含的輸出段。

3)各個運行域的運行起始地址、最大尺寸、存儲訪問特性和屬性。

4)各個運行域中包含的輸入段。

一個Scatter文件包含若干個加載域,一個加載域包含若干個輸出段,一個輸出段由若干個具有相同屬性的輸入段組成。

4?

分散加載文件語法

Scatter文件是一個文本文件,使用BNF語法來描述ARM鏈接器生成映像文件時所需要的信息。

BNF符號與語法:

" :由雙引號標識的符號保持其字面原意,如A”+”B表示A+B。

A ::= B :定義A為B。

[A] :用來表示可選部分,如A[B]C表示ABC或AC

A+ :用來表示A可以重復任意次,如A+表示A,AA,AAA,......

A* :同A+。

A | B :用來表示選擇其一,不能全選。如A|B表示A或者B。

(AB) :表示一個整體,通常其他符號一起使用,如(AB)+(C|D)表示ABC,ABD,ABABC,ABABD,......

一個Scatter文件包含一個或多個加載區域,每個加載區域可以包含一個或多個執行區域。下圖顯示了典型的Scatter文件的組成結構:

d10edf58-8478-11ee-939d-92fbcf53809c.png

4.1 加載域描述

加載域可以包含一個或多個執行域。

加載域描述的語法如下:

load_region_description::=
load_region_name(base_address|("+"offset))[attribute_list][max_size]
"{"
execution_region_description+
"}"

1)load_region_name:命名加載區域。你可以使用帶引號的名字。只有在使用任何與區域相關的鏈接器定義的符號時,該名稱才區分大小寫。

2)base_address:指定區域內對象的鏈接地址。base_address必須滿足加載區域的對齊約束。

3)+offset:描述基址,該基址在前面的加載區域的末尾以外偏移字段。偏移量的值必須是0取4的模。如果這是第一個加載區域,那么+offset表示基址從零開始偏移字段。如果使用+offset,則加載區域可能會從前一個加載區域繼承某些屬性。

4)attribute_list:指定加載區域內容的屬性。

5)max_size:指定加載區域的最大大小。這是在進行任何解壓縮或零初始化之前加載區域的大小。如果指定了可選的max_size值,那么如果分配給該區域的字段超過max_size, armlink將生成一個錯誤。

6)execution_region_description:指定執行區域的名稱、地址和內容。

4.2 執行域描述

執行域指定在運行時將輸入段放置在目標內存中的位置。

執行域描述的語法如下:

execution_region_description::=
exec_region_name(base_address|"+"offset)[attribute_list][max_size|length]
"{"
input_section_description*
"}"

1)exec_region_name:命名執行區域。你可以使用帶引號的名字。只有在使用任何與區域相關的鏈接器定義的符號時,該名稱才區分大小寫。

2)base_address:指定區域內對象的鏈接地址。Base_address必須與字對齊。

注意:在執行區域上使用ALIGN會導致加載地址和執行地址對齊。

+offset:描述一個基址,該基址在前面執行區域的末尾以外偏移字段。偏移量的值必須是0取4的模。如果這是加載區的第一個執行區,則+offset表示基址在包含加載區的基址之后開始偏移字段。如果使用+offset,則執行區域可能會從父加載區域繼承某些屬性,或者從同一加載區域內的前一個執行區域繼承某些屬性。

4)attribute_list:指定執行區域內容的屬性。

5)max_size:對于標記為EMPTY或FILL的執行區域,max_size值被解釋為該區域的長度。否則,max_size值將被解釋為執行區域的最大大小。

6)-length:只能與EMPTY一起使用,表示在內存中增長的堆棧。如果長度為負值,則base_address被視為該區域的結束地址。

7)input_section_description:指定輸入段的內容。

4.3 輸入段描述

輸入段描述指定將哪些輸入段加載到執行區域。

輸入段描述的語法是:

input_section_description::=
module_select_pattern["("input_section_selector(","input_section_selector)*")"]
input_section_selector::="+"input_section_attr
|input_section_pattern
|input_section_type
|input_symbol_pattern
|section_properties

1)module_select_pattern:

一種由文本構成的模式。當module_select_pattern匹配以下選項之一時,輸入段匹配模塊選擇器模式:

包含該段的目標文件的名稱。

庫成員的名稱(不帶前導路徑名)。

提取部分的庫的全名(包括路徑名)。如果名稱包含空格,請使用通配符以簡化搜索。

例如,使用*libname來匹配C:lib dirlibname.lib。

通配符 * 匹配零個或多個字符,? 匹配任意單個字符。匹配不區分大小寫,即使在文件命名區分大小寫的主機上也是如此。使用 *.o 匹配所有對象,使用 * 來匹配所有的目標文件和庫。可以使用帶引號的文件名,例如”file one.o”。

在一個Scatter文件中不能有兩個 * 選擇器。但是可以使用兩個修改過的選擇器,例如*A和*B,并且可以將. any選擇器與*模塊選擇器一起使用。*模塊選擇器的優先級高于.any。如果文件中包含*選擇器的部分被刪除,則. any選擇器將變為活動的。

2)input_section_attr:

與輸入部分屬性匹配的屬性選擇器。每個input_section_attr后面跟著一個+。選擇器不區分大小寫,可以識別以下選擇器:

RO-CODE

RO-DATA

RO,同時選擇RO-CODE和RO-DATA

RW-DATA

RW-CODE

RW,同時選擇RW-CODE和RW-DATA

XO

ZI

ENTRY,包含入口點的部分。

可以識別以下同義詞:

CODE代表RO-CODE

CONST代表RO-DATA

TEXT代表RO

DATA代表RW

BSS代表ZI

可以識別以下偽屬性:

FIRST

LAST

如果放置順序很重要,則使用FIRST和LAST標記執行區域中的第一部分和最后一部分。例如,如果特定的輸入部分必須在區域中位于第一個,并且包含校驗和的輸入部分必須位于最后。

FIRST和LAST必須不違反基本屬性排序順序。例如,FIRST RW放在任何只讀代碼或只讀數據之后。

一個執行區域只能有一個FIRST或一個LAST屬性,并且它必須遵循一個input_section_selector。例如:

*(section, +FIRST) 這種模式是正確的。

*(+FIRST, section) 此模式不正確,并產生錯誤消息。

3)input_section_pattern:

一種模式,不區分大小寫,與輸入段名匹配。它是由文字構成的。通配符 * 匹配0個或多個字符,而 ? 匹配任何單個字符。可以使用帶引號的輸入段名。

如果使用多個input_section_pattern,請確保在不同的執行區域中沒有重復的模式,以避免歧義錯誤。

4)input_section_type:

與輸入段類型進行比較的數字。支持十進制或十六進制。

5)input_symbol_pattern:

可以通過該段定義的全局符號名選擇輸入段。全局名稱能夠使你從部分鏈接的對象中選擇具有相同名稱的單個段。

6)section_properties:

section屬性可以是+FIRST、+LAST和OVERALIGN值。OVERALIGN的值必須是2的正冪,且必須大于或等于4。

5?

如何打開.sct文件

在Options for Targets->Linker界面,Keil默認選擇了“Use Memory Layout from Target Dialog”,勾掉復選框里面的對號,就可以使用自己定義的分散加載文件。

d11d61ae-8478-11ee-939d-92fbcf53809c.png

6?

練習

根據前面介紹的語法編輯 .sct文件,將函數和數據放到指定地址:

1)在LR_ROM加載域中定義2個執行域RW_RAM1、RW_RAM2:

RW_RAM1基地址為0x20001000,域大小為0x400,將TEST_FUNCTION_ADDR段最先加載到本域的起始地址。

RW_RAM2基地址為0x20001400,域大小為0x400,將TEST_DATA_ADDR段最先加載到本域的起始地址。

LR_ROM__RO_BASE__RO_SIZE{;loadregionsize_region
ER_ROM__RO_BASE__RO_SIZE{;loadaddress=executionaddress
*.o(RESET,+First)
*(InRoot$$Sections)
;*(Veneer$$CMSE);uncommentforsecureapplications
.ANY(+RO)
.ANY(+XO)
}

RW_RAM__RW_BASE__RW_SIZE{;RWdata
.ANY(+RW+ZI)
}

RW_RAM10x200010000x400{;RWdata
*.o(TEST_FUNCTION_ADDR,+First)
}

RW_RAM20x200014000x400{;RWdata
*.o(TEST_DATA_ADDR,+First)
}

#if__HEAP_SIZE>0
ARM_LIB_HEAP__HEAP_BASEEMPTY__HEAP_SIZE{;Reserveemptyregionforheap
}
#endif

ARM_LIB_STACK__STACK_TOPEMPTY-__STACK_SIZE{;Reserveemptyregionforstack
}
}

2)使用__attribute__((section("section_name"))) 定義函數和數據如下:

(表示將函數或數據放入指定名為"section_name"的段)

uint32_ttest_data__attribute__((section("TEST_DATA_ADDR")));
voidtest_function(void)__attribute__((section("TEST_FUNCTION_ADDR")));

3)調用上述函數和數據:

intmain(void)
{
test_function();

while(1)
{
test_data++;
if(test_data>=1000)
{
test_data=0;
}
}
}

編譯后查看map文件中內存映射部分:

d13a11f0-8478-11ee-939d-92fbcf53809c.png

TEST_FUNCTION_ADDR段對應的執行域基地址為0x20001000,TEST_DATA_ADDR段對應的執行域基地址為0x20001400,和在Scatter文件定義一致,即將函數和數據放到了指定地址。

7?

小結

分散加載文件(scatter file)是一個文本文件,用于描述 ARM 鏈接器生成映像文件所需要的信息,在一些應用場景中嵌入式系統可能會使用分散加載。本章節簡要介紹了分散加載文件的基本概念和語法,旨在對分散加載文件有初步認識,具體內容可以參考官方文檔或查閱資料進行詳細了解。


審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • ARM
    ARM
    +關注

    關注

    134

    文章

    8967

    瀏覽量

    365018
  • SDRAM
    +關注

    關注

    7

    文章

    420

    瀏覽量

    55047
  • 存儲器
    +關注

    關注

    38

    文章

    7366

    瀏覽量

    163091
  • ROM
    ROM
    +關注

    關注

    4

    文章

    539

    瀏覽量

    85431
  • keil
    +關注

    關注

    68

    文章

    1207

    瀏覽量

    166171
  • 內存映射
    +關注

    關注

    0

    文章

    14

    瀏覽量

    7388
  • 靈動微
    +關注

    關注

    3

    文章

    174

    瀏覽量

    22617
  • MM32
    +關注

    關注

    1

    文章

    106

    瀏覽量

    659

原文標題:靈動微課堂 (第278講)|Keil分散加載文件淺析

文章出處:【微信號:MindMotion-MMCU,微信公眾號:靈動MM32MCU】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    如何把文件系統燒到EMMC并從EMMC加載

    如何下載并從SD卡加載文件系統,提到過可以從EMMC引導系統,本篇將為您介紹如何把文件系統燒到EMMC,并從EMMC加載
    的頭像 發表于 10-30 16:06 ?2428次閱讀
    如何把<b class='flag-5'>文件</b>系統燒到EMMC并從EMMC<b class='flag-5'>加載</b>

    ARM分散加載及應用

    從ARM ELF目標文件主要構成出發,詳細介紹了分散加載的基本原理、分散加載文件的語法、分散
    發表于 05-04 16:09

    單片機中的分散加載文件主要包括哪幾類呢

    單片機中的分散加載文件主要包括哪幾類呢?
    發表于 01-27 08:00

    什么是分散加載文件

    分散加載的作用是什么?什么是分散加載文件
    發表于 02-16 06:48

    請問怎樣去修改STM32F2中ROM分區的分散加載文件

    的sector。應用程序跑在后面。但是這樣的作法弊端就是需要兩份程序。 另一個方法是我在想,通過修改鏈接文件,例如MDK下修改分散加載文件讓其中保存參數的sector不放任何東西。修改例如下面這樣
    發表于 07-22 10:10

    求助,關于mdk5分散加載文件的問題

    有沒有人能解釋一下,分散加載文件應該怎么寫
    發表于 11-02 07:23

    如何使用BitTorrent下載文件

    如何使用BitTorrent下載文件 若要使用BitTorrent下載文件,您需要安裝BitTorrent客戶端軟件。您也可能需要調整防火墻和網絡路由器的設置(如果使用)
    發表于 08-03 09:26 ?8603次閱讀

    周立功單片機:分散加載文件淺釋

    Scatter-Loading Description File 分散加載文件
    發表于 03-13 14:19 ?97次下載

    使用KEIL載文件到單片機外置存儲器的方法

    使用KEIL載文件到單片機外置存儲器給單片機下載程序的原理實用性要解決的難點怎樣編寫bootloader使用KEIL載文件給單片機下載程序的原理給單片機下載程序一般有兩種方法:1,
    發表于 11-17 11:21 ?11次下載
    使用<b class='flag-5'>KEIL</b>下<b class='flag-5'>載文件</b>到單片機外置存儲器的方法

    單片機中分散加載文件介紹

    單片機中分散加載文件介紹
    發表于 12-03 10:51 ?2次下載
    單片機中<b class='flag-5'>分散</b><b class='flag-5'>加載文件</b>介紹

    ARM分散加載文件

    分散加載作用:可以將代碼放入不同的存儲空間。1.基本概念了解分散加載文件之前,首先需要了解Code、RO-Data、RW-Data、ZI-Data。Code:程序代碼RO-Data:程
    發表于 12-20 19:10 ?7次下載
    ARM<b class='flag-5'>分散</b><b class='flag-5'>加載文件</b>

    什么是分散加載文件?何時進行分散加載

    分散加載文件(scatter file)是一個文本文件,它的作用是可以用于描述 ARM 鏈接器生成映像文件所需要的信息。
    的頭像 發表于 09-14 10:38 ?2596次閱讀

    什么是分散加載文件

    分散加載文件(scatter file)是一個文本文件,它的作用是可以用于描述 ARM 鏈接器生成映像文件所需要的信息。 如果不使用 scatter file
    的頭像 發表于 01-30 14:12 ?2307次閱讀
    什么是<b class='flag-5'>分散</b><b class='flag-5'>加載文件</b>?

    AN024 GD32F4xx_Keil分散加載說明

    AN024 GD32F4xx_Keil分散加載說明
    發表于 02-27 18:25 ?1次下載
    AN024 GD32F4xx_<b class='flag-5'>Keil</b><b class='flag-5'>分散</b><b class='flag-5'>加載</b>說明

    深入分析一下MDK的分散加載文件

    ARM C 庫提供了函數 __user_setup_stackheap() 的多個實現,并且可以根據分散文件中提供的信息自動選擇正確的一種。
    發表于 04-28 14:21 ?611次閱讀
    深入分析一下MDK的<b class='flag-5'>分散</b><b class='flag-5'>加載文件</b>