快速產生linker script 的Andes SAG 機制

Facebook
Twitter
LinkedIn

    在嵌入式系統設計中,通常使用不同的記憶體,如 Flash、SRAM、SDRAM, 並位於不同的物理位址空間,怎樣更好地利用這些不同的記憶體並讓系統高效率地執行呢?通常這需要複雜的 linker script 來管理實作,而 Andes 提供了 SAG 語法(Scattering-And-Gathering),SAG 能夠將載入和執行時記憶體中的代碼和資料描述在一個SAG 格式的文字描述檔中,並通過linker script generator tool 將SAG 檔轉化為標準 GNU 的 linker script 檔,以供 link 程式時使用。採用 Andes SAG 機制,不僅可以幫助工程師清晰的描述記憶體的使用情況,更可以避免使用複雜的標準 linker script 語言 。本文詳細介紹了 SAG 語法格式,並以實際專案為例, 闡述 SAG 的使用方法和益處。

1. Andes ELF 檔案的結構
    Andes 使用標準的 GNU link script 格式,Andes 的可執行檔案也遵行標準的ELF(Executable and Linking Format)格式。
    ELF 檔案主要由 .text 段 .data 段 .bss 段,還有一些其它的段如:.debug .comment 段組成。

    下面以一個簡單的 linker script 的例子作為說明:

    SECTIONS 是 linker script 語法中的關鍵 command,它用來描述輸出檔的記憶體佈局。例如上例中就含.text, .data, .bss 三個部分。
  .=0x10000;  其中的”.”是定位點(location counter -LC)。表示.text 段虛擬位址(VMA)從 0x10000 開始的。
     AT 用來說明載入位址,AT(0)表示.text 段的載入地址是 0。{ *(.text) },這個表示輸出檔的.text 段內容由所有輸入檔()的.text 段組成。後面的一個. = 0x40000。如果沒有這個設定值,那麼 LC 應該等於 0x10000+sizeof(.text),這裡強制指定 LC=0x40000。表示後面的.data 段的虛擬位址(VMA)從 0x40000 開始。
    LOADADDR 用來得到載入地址,此處.data 段的載入地址是 AT(LOADADDR (.text) + SIZEOF (.text)),它緊接著.text 段,.data 為所有輸入目的檔案的.data段構成。同理,.bss 段的虛擬位址是緊接著.data 段虛擬位址之後,而載入位址是緊接著.data 段載入位址之後的。.bss 段由所有輸入目的檔案的.bss 段組成。
    通常在實際使用中的 linker script 會更加的複雜,SAG 機制能夠很好的簡化linker script 的設計,那接下來將對 SAG 機制做介紹。

2. Andes SAG 語法
    SAG 語法的 BNF 符號表示法如下表:

SAG 格式總覽
   
SAG 語法格式由:load regions、execution regions 和 input sections 等組成, 如下圖所示:

2.1 關 於 LMA 和 VMA
    一般在嵌入式系統中,程式載入和執行在不同的位址空間,LMA 表示的是程式載入位址,VMA 表示的是程式執行位址,當 LMA 不等於 VMA 時,程式在載入後不能直接執行,而程式執行前,要把程式的內容複製到對應的記憶體位址處, 才能正確地執行。

2.2 header 格式      當要使用者自訂的 section 時,必需在 USER_SECTIONS 中定義。

2.3 Load Region(載入區)
  Load Region 格式為:
    load_region_name 表示某個程式載入區的名稱。
    address 表示的是 LMA。
    offset 表示的是偏移量,當此時是第一個 load region 時表示的是與 0 位址的偏移量,當表示的不是第一個 load region 時,表示的是與前一個 load region 結尾處的偏移量。
    load_attr 表示屬性,現在可以設置為 ALIGN alignment, 如 ALIGN 0x4。
    max_size 表示該載入區域的最大值。
    例子:
    LOAD_ROM_1 0x0000 ALIGN 0x4 0x10000
    在這個例子中 load_region_name 是:LOAD_ROM_1,LMA 是 0x0000,以4-byte 對齊,max_size 是 64K byte

2.4 Execution Region(執行區)
    Execution Region 格式為:     exe_region_name 用於表示某個程式執行區的名稱
    address 表示的是 VMA。
    offset 當表示的是第一個 execution region,表示的是與該載入區的偏移量, 當表示的不是第一個 execution region 時,offset 表示的是前一個 execution region 結尾處的偏移量。
    exe_attr 表示屬性,如可以設置為 ALIGN alignment,如 ALIGN 0x4。
    max_size 表示該 execution region 的最大值。
    例子:
    EXEC_ROM_1 0x0000 ALIGN 0x4 0x8000
    在這個例子中exe_region_name 是 EXEC_ROM_1,它的 VMA 是 0x0000, 以4-byte 對齊,max_size 是 32K byte。

2.5 Input Section(輸入段)
     Input Section 的描述格式為:     此處:
    module_select_pattern 可以是目的檔案名。
    input_attr 可以加上”KEEP”,其屬性可以保證該 section 在連結時不會被                remove 掉,或者是 SORT,用於排序。
    例如:
    program1.o   KEEP (+RO)
    此時該 input section 將包含目的檔案 program1.o 中所有的 read-only section,由於加了 KEEP,所以 prgram1.o 的 read-only section,在連結的時候不會被 gc-section 刪除掉。
    input_section_selector 中最常用的是 input section_attr。
    input section_attr 有以下幾種:
    input_section_selector 中另外一種用的是 input_section_pattern, 它的表示方法是 input_section_pattern ::= (.text | .data|…)。

    ADDR variable   取得該處的 VMA 並存放在 variable 內。LOADADDR variable 取得該處的 LMA 並存放在 variable 內。STACK “=” num       為$sp 設定一個初始值 num。
    VAR  用於設定並初始化一個變數。如 VAR _ILM_BASE = 0x00600000。

2.6 Execution Overlay Region(overlay 的執行區)
     當使用 overlay 功能時,需要設定 Execution Overlay Region,設定格式為:  

    它在後面加了個:OVERLAY 的關鍵字。
    pagesize 後面表示 Overlay 的大小,當是 0 時,表示 software Overlay,其它的設置和前面的 execution region 相同。

2.7 Overlay Input Section(overlay 的輸入段)
     當使用 overlay 功能時,要設置 Overlay Input Section,它和前面的 Input Section 類似。

3. 例子
     如下例子所示的效果是:
     在一個系統中,從 0x0000 開始,大小為 0x2000 的是 ROM1, 從 0x4000 開始,大小為 0x8000 的是 ROM2,此時我們需要將目的檔案 program1.o 的 RO 和 RW,ZI data。 存放在 ROM1 中,將其它目的檔案的 .text,RO,RW, ZI 存放在 ROM2 中。此時的 LMA 效果對應於下圖的左側。
    同時需要將目的檔案program1.o 中的RW, ZI 的執行位址設置在從0x10000 開始的大小為 0x8000 的 DRAM 上,將其它目的檔案的 RW,ZI 的執行位址設置在從 0x18000 開始,大小為 0x8000 的SRAM 上。此時的 VMA 效果對應於下圖的右側。

    該例子中 program1.o 中的 RO 和其它目的檔案中的.text, RO 的 LMA 和 VMA 是相等的,此時所有的 RW,ZI 的載入區域是分別在 ROM1 和 ROM2 上,但是執行位址是分別在 DRAM 和 SRAM 上,所以 RW,ZI 的 LMA 不等於 VMA, 所以在程式使用到 RW, ZI 所代表的.data,.bss 段之前需要將它們從載入區複製到執行區,以達到所圖中右側所示的效果。

    對應的 SAG 可以這樣設計:

    利用 SAG 機制,除了快速設計上列所示的系統中儲存空間的分配,還可以快速的進行 overlay 程式的設計,overlay 程式主要是用於分時重複利用快速但儲存空間有限的記憶體。

4.將 SAG 檔轉換成 linker script
     在 AndeSight™ 或者 BSP package 中提供了叫做 nds_ldsag 的工具,該工具可以將 SAG 檔轉換成標準的 GNU linker script 檔。在 cygwin 下,執行方法如下,filename.ld 就是我們希望獲得的linker script 檔。
./nds_ldsag.exe filename.sag -o filename.ld

5.結語
     Andes 提供的簡單、易用的 SAG 描述語言,讓工程師根據系統中的存放裝置的特點,對程式的載入與執行區域進行很方便的設計和描述,甚至可以快速的進行更為複雜的 overlay 程式的設計,然後通過自動化工具 nds_ldsag 將 SAG 描述檔轉成標準 linker script 供 linker 使用,從而大大提高在 Andes core 平臺上的軟體發展效率。

參考文件:
     1: Andes BSP v3.2.1 Programming Guide 第 14 章 ”Linker Script Generation”
     2: The GNU Linker Manual