Andes SAG應(yīng)用實例
在嵌入式開發(fā)中,系統(tǒng)軟件設(shè)計特別是各種存儲器的規(guī)劃是必不可少的一個環(huán)節(jié),它也直接體現(xiàn)在鏈接腳本的撰寫上。 因鏈接腳本的語法相對復(fù)雜和篇幅較大,前期撰寫和后期維護(hù)對工程師來講難度都很大, 但對使用AndesCore做開發(fā)的工程師來講,Andes SAG是一大福音,它提供簡單直觀的描述語言替代了復(fù)雜的鏈接腳本。我們收到的反饋也證明,越來越多的工程師開始采用Andes SAG替代linker,之前我們有一篇技術(shù)文章對SAG的語法格式做了介紹并說明如何使用,本文將展示四個實際工程開發(fā)的例子,以幫助廣大開發(fā)者更好的熟悉和理解Andes SAG,同時可以作為開發(fā)時的參考。
本文引用地址:http://www.ex-cimer.com/article/266369.htm1.將函數(shù)和變量指定到特定地址
第一個例子是如何將函數(shù)和變量的地址指定到一個特定的地址,例子中的地址指運(yùn)行地址——VMA。有這樣要求的原因有很多,諸如SOC的運(yùn)行地址空間不連續(xù),或者需要高效使用某一塊效率很高的存儲器等情況。解法分為兩步:一,在SAG文件中添加自定義的section,將此section的VMA設(shè)定到指定地址;二,在C語言中,將需要改變的函數(shù)和變量用特定的語法放在自定義的section。
圖表1是在SAG中自定義section 的例子。第1行關(guān)鍵詞USER_SECTIONS表示后面接的這幾個sections都是由使用者自定義的sections。
圖表1. Samp1.sag文件
圖表1中,第4行至8行表示從0x0開始的區(qū)域是只讀區(qū),包含程序代碼(.text section)及只讀數(shù)據(jù)段(.rodata section)。第9行,MYRAM0部分表示.mysection0的VMA從0x00014000開始。以此類推,MYRAM1和MYRAM2部分各自表示mysection1和.mysection2的VMA起始位置。第21行的RAM1里放的是.data及.bss sections,執(zhí)行時期會從0x00010000開始,源代碼中須做到將data 的LMA地址copy至 VMA位置,可以使用 __data_lmastart 與 __data_start 來尋址。
指定函數(shù)放在自定義section里,在源代碼的對應(yīng)處要使用__attribute__((section(".mysection0")))語法,完整寫法請參考圖表2a。圖表2b是另外一種寫法。
圖表2a. 指定函數(shù)放在自定義section
圖表2b. 指定函數(shù)放在自定義section的另一種寫法
指定全局變量gdata1放在自定義section .mysection1里,在源代碼的對應(yīng)處要使用__attribute__((section(".mysection1")))語法,完整語法請參考圖表3。
圖表3. 指定變量放在自定義section
將函數(shù)和變量這樣指定后,編譯后的adx(elf)文檔可以清晰看到對應(yīng)Section的LMA與VMA如圖表4.
圖表4. ELF Header
2.實現(xiàn)IVB在運(yùn)行時切換
有一個客戶需要系統(tǒng)在開機(jī)與正常運(yùn)行時能有不同的ISR,即是同一個中斷的服務(wù)函數(shù)在開機(jī)和正常運(yùn)行時會不一樣。對于這個問題的解法有很多,我們今天介紹是其中一種解決方法:設(shè)置一個新的Vector Table,新的Vector Table會跳到新的ISR;通過SAG將新的Vector Table指定到一個特定地址上;當(dāng)程序開機(jī)完成,需要正常運(yùn)行時,只需要去修改IVBASE (ir3)這個寄存器。
所以完成這個例子的重點(diǎn)是如何在匯編代碼中建一個新的vector table 并指定到自定義的section中。表5是實例的寫法:
圖表5 指定Vector table到自定義section
圖表5重點(diǎn)是是第一行,.section 是用來定義非標(biāo)準(zhǔn)的section,.nds32_aa 即為非標(biāo)準(zhǔn)section的名稱,”a”表示allocable, “x”表示executable. 因為Andes的標(biāo)準(zhǔn)vector table一般會放在.nds32_init section,所以新的vector table 放.nds32_aa里,名稱不一樣能區(qū)別就好。接下來是讓新的自定義section .nds32_aa 運(yùn)行在特定地址上,如圖表6所示。
圖表6 指定自定義section到特定地址
這樣新的vector table的首地址會被固定到0x10000的位置,當(dāng)程序開機(jī)完成,只需要將IVBASE設(shè)定到這個地址,那么當(dāng)有中斷進(jìn)來,就會跳到新的Vector Table中。
3.指定一個或幾個C檔的所有section到指定地址
上兩個例子有共同點(diǎn)是通過編程將某一段程序放到自定義section,區(qū)別在于一個是指定C語言函數(shù)和變量到自定義section,一個指定匯編函數(shù)到指定的section,都需要改動源代碼。然而對于一些應(yīng)用場景,比如不提供源代碼只有編譯好的.o或者.a 文件,如果想將.o檔里的section指定到特定地址運(yùn)行,這個時候該如何做呢?請參考圖表7A的寫法,這表示我們要將hello.o的只讀區(qū),包含程序代碼(.text section)及只讀數(shù)據(jù)段(.rodata section)放在LMA及VMA在0x10000的地址上。
圖表7A 指定自定義section到特定地址
在整個project 中如果將每個.o檔都列出來,那么整個SAG文檔將變得難以閱讀,而且在給后期維護(hù)帶來麻煩,這種解法不好。如果使用者只需要排除幾個.o檔,對于熟悉GNU linker的讀者會想到“EXCLUDE_FILE”這一語法,讓使用者可以很方便地在Linker中實現(xiàn)這一需求。Andes SAG也與時俱進(jìn)地引入這一語法。圖表7B正是這樣一個例子,它將uart.o中所有的section 都放到一個特定地址去運(yùn)行,而其它的保持不變。
圖表7B 支持“EXCULDE_FILE”
4、如何避免LMA或VMA的偏差
在前三個例子中,都是舉例去說明如何實現(xiàn)將程序的某一部分的LMA或者VMA固定在某一個特定地址上,這是對鏈接這一動作的基本要求。嵌入式軟件工程師需要知道,當(dāng)某一section的LMA與VMA不相等時,那么在程序初始化時需要將這一section從LMA的地址拷貝到VMA的地址。初始化做拷貝時,這些section的LMA和VMA都是在鏈接腳本中賦值的,代碼中只是去做引用。
Andes SAG同樣可以給變量賦值LMA和VMA,但如何賦值呢,是不是一個一個緊湊地排列下來?答案很顯然是不。很多工程師都知道,數(shù)據(jù)存放有Alignment的要求,比如4 Byte 的Word其存放的首地址需要是4 Byte Align;程序呢,因為優(yōu)化的需要,比如在Andes 編譯器在-Os等級下,函數(shù)的首地址同樣強(qiáng)制4 Byte Align。既然有對齊的要求,就必然有g(shù)ap存在,當(dāng)然這里舉出的對齊因素只是讓讀者了解到鏈接器對某一section的LMA或VMA的數(shù)值確定不只是單純累加,Andes SAG能自動處理好大部分對齊狀況。但在一些較復(fù)雜的例子中,需要給Andes SAG更多指示,讓它工作正確。
首先,我們來看圖表7所舉出的例子,這一行“LOADADDR NEXT __uart_lmastart”,有一個關(guān)鍵字“NEXT”。它的作用就是讓SAG知道,這個變量的取值是下一個Section的開始,而不是上一個Section的結(jié)束。為了讓讀者更明白所表示的含義,我們首先來看依照圖表7的SAG編譯出的elf(adx)檔header信息,如圖表8:
圖表8 adx header
可以看到.text_*uart.o 的LMA應(yīng)該是0x1c60, 上一個section(.bss)的LMA結(jié)束地址應(yīng)為:0x1c48+0x10=0x1c58,所以為了清晰地讓SAG知道__uart_lmastart代表.text_*uart.o的LMA開始而不是.bss的LMA結(jié)束,我們應(yīng)該用NEXT去修飾它。
然后,我們再來看圖表9的例子,這個例子中,使用“LMA_FORCE_ALIGN”的原因是因為可能某一個section的size 只有2 Byte(不是4 Byte的整數(shù)倍),但下一個section的VMA 起始地址需要4 Byte Align,這時就會出現(xiàn)沖突,為解決沖突,Andes SAG引入這一關(guān)鍵字“LMA_FORCE_ALIGN”,強(qiáng)制讓LMA與VMA用同一個值去做Align。
圖表9 “LMA_FORCE_ALIGN”example
我們用圖表9的SAG 例子去編譯對應(yīng)的project,可以看到圖表10中section .sbss_b的LMA已經(jīng)被從0x1d42調(diào)整到0x1d44。
圖表10 “LMA_FORCE_ALIGN”的效果
5、結(jié)語
Andes提供通俗易用的SAG工具幫助工程師替代了復(fù)雜的鏈接腳本,可以大大提高在Andes core平臺上的軟件開發(fā)效率。本文從實際例子出發(fā),介紹了Andes SAG 工具如何快速解決工程實際問題,說明了Andes SAG強(qiáng)大而且容易上手。然而工具的功能越強(qiáng)大,也就需要工程師多加深入了解功能設(shè)計的緣由,這也正是最后一個例子展現(xiàn)出來的道理,即是透徹了解就可以熟能生巧。希望廣大讀者能熟練掌握Andes SAG這樣一把利器,在軟件開發(fā)中發(fā)揮四兩撥千斤的作用。
參考文檔:
1: BSP321 programming guide link generator
2: The GNU Linker Manual
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)可控硅相關(guān)文章:可控硅工作原理
c語言相關(guān)文章:c語言教程
比較器相關(guān)文章:比較器工作原理
存儲器相關(guān)文章:存儲器原理
評論