當燒錄ELF file到對應的硬體時,需要參考 linker script 以決定該如何安排各個區域所在的位置。
// 1. 指定多個輸入檔案,輸入的檔案必須已經包裝成函數庫,而且他們會被重複搜尋直到沒有新的定義值出現
GROUP(libcr_c.a libcr_semihost.a libcr_eabihelpers.a)
// 2. 根據所使用的硬體,進行記憶體配置
MEMORY
{
/* Define each memory region */
MFlash32 (rx) : ORIGIN = 0x0, LENGTH = 0x8000 /* 32k */
RamLoc8 (rwx) : ORIGIN = 0x10000100, LENGTH = 0x1F00 /* 8k-256bytes */
}
// 定義記憶體的邊界值
__top_MFlash32 = 0x0 + 0x8000;
__top_RamLoc8 = 0x10000100 + 0x1F00;
// 3. 設定入口函數名稱為 ResetISR, 這是CPU執行的第一個程式, 若不指定,
// 預設會採用 .text section 的第一個Byte的位置
ENTRY(ResetISR)
// 4. 描述如何將輸入檔案的各個section,組合成輸出檔案中所對應的section。
SECTIONS
{
.text :
{
FILL(0xFF); // filled unused code space
KEEP(*(.isr_vector)) // 把程式中定義的 isr_vector 放到此處,此資料結構即 interrupt vector table
*(.text.Reset_Handler .text.SystemInit) //將 Reset_Handler 與 SystemInit 兩個函數放置此處
. = 0x000002FC; // 改變當前的位址,將位址設定為 0x000002FC
KEEP(*(.crp))
*(.text*) // 將所有連結的檔案(*.o)內的 .text section 通通放到此處
*(.rodata*) // 將所有連結的檔案(*.o)內的 .rodata section 通通放到此處
} > MFlash32 // 把以上 .text 中的內容寫到 MFlash32 中
/* for exception handling/unwind - some Newlib functions (in common with C++ and STDC++) use this. */
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > MFlash32
__exidx_start = .; // 記住當前位址
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > MFlash32
__exidx_end = .;
_etext = .; // text 區域的結束位址
.data : AT (__exidx_end)
{
_data = .; // 記住 .data 區域的起始位址, 之後程式可以利用此變數找到 .data 區域
*(vtable)
*(.data*)
_edata = .; // 記住 .data 區域的結束位址
} > RamLoc8
/* zero initialized data */
.bss :
{
_bss = .; // 記住 .bss 區域的起始位址
*(.bss*)
*(COMMON)
_ebss = .; // 記住 .bss 區域的結束位址
} > RamLoc8
/* Where we put the heap with cr_clib */
.cr_heap :
{
end = .;
_pvHeapStart = .;
} > RamLoc8
_vRamTop = __top_RamLoc8 ;
_vStackTop = _vRamTop;
}
參考資料
1. http://wenku.baidu.com/view/03a3d481e53a580216fcfeba.html
2. http://www.math.utah.edu/docs/info/ld_3.html