新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Andes SAG應(yīng)用實(shí)例

Andes SAG應(yīng)用實(shí)例

作者: 時(shí)間:2014-12-04 來源:電子產(chǎn)品世界 收藏

  在開發(fā)中,系統(tǒng)軟件設(shè)計(jì)特別是各種的規(guī)劃是必不可少的一個(gè)環(huán)節(jié),它也直接體現(xiàn)在鏈接腳本的撰寫上。 因鏈接腳本的語法相對復(fù)雜和篇幅較大,前期撰寫和后期維護(hù)對工程師來講難度都很大, 但對使用AndesCore做開發(fā)的工程師來講,Andes SAG是一大福音,它提供簡單直觀的描述語言替代了復(fù)雜的鏈接腳本。我們收到的反饋也證明,越來越多的工程師開始采用Andes SAG替代linker,之前我們有一篇技術(shù)文章對SAG的語法格式做了介紹并說明如何使用,本文將展示四個(gè)實(shí)際工程開發(fā)的例子,以幫助廣大開發(fā)者更好的熟悉和理解Andes SAG,同時(shí)可以作為開發(fā)時(shí)的參考。

本文引用地址:http://butianyuan.cn/article/266369.htm

  1.將函數(shù)和變量指定到特定地址

  第一個(gè)例子是如何將函數(shù)和變量的地址指定到一個(gè)特定的地址,例子中的地址指運(yùn)行地址——VMA。有這樣要求的原因有很多,諸如SOC的運(yùn)行地址空間不連續(xù),或者需要高效使用某一塊效率很高的等情況。解法分為兩步:一,在SAG文件中添加自定義的section,將此section的VMA設(shè)定到指定地址;二,在C語言中,將需要改變的函數(shù)和變量用特定的語法放在自定義的section。

  圖表1是在SAG中自定義section 的例子。第1行關(guān)鍵詞USER_SECTIONS表示后面接的這幾個(gè)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í)行時(shí)期會從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.實(shí)現(xiàn)IVB在運(yùn)行時(shí)切換

  有一個(gè)客戶需要系統(tǒng)在開機(jī)與正常運(yùn)行時(shí)能有不同的ISR,即是同一個(gè)中斷的服務(wù)函數(shù)在開機(jī)和正常運(yùn)行時(shí)會不一樣。對于這個(gè)問題的解法有很多,我們今天介紹是其中一種解決方法:設(shè)置一個(gè)新的Vector Table,新的Vector Table會跳到新的ISR;通過SAG將新的Vector Table指定到一個(gè)特定地址上;當(dāng)程序開機(jī)完成,需要正常運(yùn)行時(shí),只需要去修改IVBASE (ir3)這個(gè)寄存器。

  所以完成這個(gè)例子的重點(diǎn)是如何在匯編代碼中建一個(gè)新的vector table 并指定到自定義的section中。表5是實(shí)例的寫法:

    

 

    

 

  圖表5 指定Vector table到自定義section

  圖表5重點(diǎn)是是第一行,.section 是用來定義非標(biāo)準(zhǔn)的section,.nds32_aa 即為非標(biāo)準(zhǔn)section的名稱,”a”表示allocable, “x”表示executable. 因?yàn)锳ndes的標(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è)定到這個(gè)地址,那么當(dāng)有中斷進(jìn)來,就會跳到新的Vector Table中。

  3.指定一個(gè)或幾個(gè)C檔的所有section到指定地址

  上兩個(gè)例子有共同點(diǎn)是通過編程將某一段程序放到自定義section,區(qū)別在于一個(gè)是指定C語言函數(shù)和變量到自定義section,一個(gè)指定匯編函數(shù)到指定的section,都需要改動源代碼。然而對于一些應(yīng)用場景,比如不提供源代碼只有編譯好的.o或者.a 文件,如果想將.o檔里的section指定到特定地址運(yùn)行,這個(gè)時(shí)候該如何做呢?請參考圖表7A的寫法,這表示我們要將hello.o的只讀區(qū),包含程序代碼(.text section)及只讀數(shù)據(jù)段(.rodata section)放在LMA及VMA在0x10000的地址上。

    

 

  圖表7A 指定自定義section到特定地址

  在整個(gè)project 中如果將每個(gè).o檔都列出來,那么整個(gè)SAG文檔將變得難以閱讀,而且在給后期維護(hù)帶來麻煩,這種解法不好。如果使用者只需要排除幾個(gè).o檔,對于熟悉GNU linker的讀者會想到“EXCLUDE_FILE”這一語法,讓使用者可以很方便地在Linker中實(shí)現(xiàn)這一需求。Andes SAG也與時(shí)俱進(jìn)地引入這一語法。圖表7B正是這樣一個(gè)例子,它將uart.o中所有的section 都放到一個(gè)特定地址去運(yùn)行,而其它的保持不變。

    

 

  圖表7B 支持“EXCULDE_FILE”

  4、如何避免LMA或VMA的偏差

  在前三個(gè)例子中,都是舉例去說明如何實(shí)現(xiàn)將程序的某一部分的LMA或者VMA固定在某一個(gè)特定地址上,這是對鏈接這一動作的基本要求。軟件工程師需要知道,當(dāng)某一section的LMA與VMA不相等時(shí),那么在程序初始化時(shí)需要將這一section從LMA的地址拷貝到VMA的地址。初始化做拷貝時(shí),這些section的LMA和VMA都是在鏈接腳本中賦值的,代碼中只是去做引用。

  Andes SAG同樣可以給變量賦值LMA和VMA,但如何賦值呢,是不是一個(gè)一個(gè)緊湊地排列下來?答案很顯然是不。很多工程師都知道,數(shù)據(jù)存放有Alignment的要求,比如4 Byte 的Word其存放的首地址需要是4 Byte Align;程序呢,因?yàn)閮?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”,有一個(gè)關(guān)鍵字“NEXT”。它的作用就是讓SAG知道,這個(gè)變量的取值是下一個(gè)Section的開始,而不是上一個(gè)Section的結(jié)束。為了讓讀者更明白所表示的含義,我們首先來看依照圖表7的SAG編譯出的elf(adx)檔header信息,如圖表8:

    

 

  圖表8 adx header

  可以看到.text_*uart.o 的LMA應(yīng)該是0x1c60, 上一個(gè)section(.bss)的LMA結(jié)束地址應(yīng)為:0x1c48+0x10=0x1c58,所以為了清晰地讓SAG知道__uart_lmastart代表.text_*uart.o的LMA開始而不是.bss的LMA結(jié)束,我們應(yīng)該用NEXT去修飾它。

  然后,我們再來看圖表9的例子,這個(gè)例子中,使用“LMA_FORCE_ALIGN”的原因是因?yàn)榭赡苣骋粋€(gè)section的size 只有2 Byte(不是4 Byte的整數(shù)倍),但下一個(gè)section的VMA 起始地址需要4 Byte Align,這時(shí)就會出現(xiàn)沖突,為解決沖突,Andes SAG引入這一關(guān)鍵字“LMA_FORCE_ALIGN”,強(qiáng)制讓LMA與VMA用同一個(gè)值去做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ā)效率。本文從實(shí)際例子出發(fā),介紹了Andes SAG 工具如何快速解決工程實(shí)際問題,說明了Andes SAG強(qiáng)大而且容易上手。然而工具的功能越強(qiáng)大,也就需要工程師多加深入了解功能設(shè)計(jì)的緣由,這也正是最后一個(gè)例子展現(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)文章:存儲器原理




評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉