目錄
1.鏈接文件有什么用?
2.文件結(jié)構(gòu)和語法解析
2.1 文件結(jié)構(gòu)
2.2 語法解析
3.小結(jié)
玩慣了ld文件,突然讓搞lsl文件,被其中花里胡哨的語法搞暈了,例如:
memory cpu0_dlmu { mau = 8; size = 64k; type = ram; map cached (dest=bus:sri, dest_offset=0x90000000, size=64k); map not_cached (dest=bus:sri, dest_offset=0xb0000000, size=64k,priority=8); }雖然這個字面意思寫的很清楚,但是在鏈接器實際運行時有什么不一樣嗎,mau、priority具體表示什么?因此有必要搞一搞其底層原理。 編譯原理這里就不多談了,咱們直接從鏈接器開始走起。
1.鏈接文件有什么用?
Tasking 鏈接器將Linker和Locator集合到一起, Linker階段主要把 .o文件、lib文件組合成一個可重定位的對象文件,例如.out;Locator主要用于給上述.out文件重新分配絕對地址,并生成目標(biāo)處理器的文件,例如elf、hex、s19等,總體流程如下圖:
在連接過程中,lsl(Linker Script Language)文件起到了非常關(guān)鍵的作用:
確定當(dāng)前目標(biāo)處理的內(nèi)核硬件架構(gòu),例如邏輯地址和物理地址的偏移等;
確定當(dāng)前系統(tǒng)的memory位置,例如RAM、ROM首地址和長度等;
確定代碼數(shù)據(jù)放到memory的什么位置,這也是我們主要關(guān)心的點,控制數(shù)據(jù)代碼到指定位置;
有了上述基本了解,我們來看看lsl的一些關(guān)鍵語法。
2.文件結(jié)構(gòu)和語法解析
2.1 文件結(jié)構(gòu)
lsl鏈接文件主要包含如下幾個部分:
內(nèi)核架構(gòu)的定義:幫助linker將目標(biāo)內(nèi)核的邏輯地址轉(zhuǎn)換為物理地址,可能還包括中斷向量表、棧的定義等,一般來說編譯器會把這個定義好,例如tc1v1_6_2.lsl;
派生的定義:主要是用于描述內(nèi)部總線定義、memeory定義等;
處理器的定義:用于定義單核還是多核,以及對應(yīng)內(nèi)核實例
段的定義:控制自定義段的具體位置
框架如下如下:
2.2 語法解析
首先來看幾個最常見到但是沒有關(guān)心過的關(guān)鍵字,以開頭代碼為例:
mau:Minimal Addressable Units,最小可尋址單元,對Tricore來說就是1 byte,對應(yīng)數(shù)字 8;
type:指定memory類型,常見的如rom,ram,nvram(任意時刻都可以修改),blockram
map:該關(guān)鍵字將源地址轉(zhuǎn)為目的地址,具體映射關(guān)系如下:
space => space
space => bus
bus => bus
memory => bus
上述幾個關(guān)鍵字接下來我們就來分析幾個常用的語法。 定義memory的基本格式如下:
memory mem_name { type = xx; mau = xx; size = 64k; map map_name ( map_description ); }以定義TC3xx CPU0 DSPR的空間為例,代碼如下:
memory dsram0 // Data Scratch Pad Ram { mau = 8; size=240k; type=ram; map(dest=busfpi_bus,dest_offset=0xd0000000,size=240k,priority=8); map(dest=bus:sri,dest_offset=0x70000000,size=240k); }mau = 8,表示最小尋址單位為1 byte;整塊memory為240k,屬于ram類型;比較好玩的是下面兩塊map,我們來看第一個:
map (dest=busfpi_bus, dest_offset=0xd0000000, size=240k, priority=8)目的地是Tricore 0 的FPI 總線,偏移為0xd0000000,size為240k,優(yōu)先級為8;我們回過頭看TC3xx的手冊,會發(fā)現(xiàn)CH、DH這個Segment是保留的,這就奇怪了,鏈接文件為什么要定義這個東西?直覺告訴我這個可能和Tricore尋址方式有關(guān)系。 fpi_bus用于將CPU等連接至中低帶寬外設(shè),對應(yīng)具體實例為SPB(系統(tǒng)外設(shè)額總線)、BBB(ADAS domain相關(guān)),位寬32bit;如下圖:
其次,針對CHDH的用途在map中也給出體現(xiàn),如下
我們繼續(xù)翻看5.3.6.1.1章節(jié),詳細(xì)描述了本地和全局尋址方式。 核內(nèi)DSPR位置始終為0xD0000000,PSPR為0xC000000,可以理解這是本地地址;而在多核系統(tǒng)中,根據(jù)Core ID,PSPR和DSPR分別對應(yīng)1-7H,這就是所謂的全局地址,如下:
但是,還有但是,CPU始終是用全局進行總線傳輸,意味著即使CPU0從本地DSPR拿數(shù)據(jù),仍然使用是的7000000的地址。 所以緊接著定義了關(guān)于多核globle的map,如下:
map (dest=bus:sri, dest_offset=0x70000000, size=240k);那么在鏈接的時候,linker如何知道用0x7開頭還是0xd開頭的呢?根據(jù)后面的priority優(yōu)先級來定。 在測試優(yōu)先級的時候,上面關(guān)于DSPR的例子舉的不好,因為不管我怎么調(diào)優(yōu)先級都還是用的global地址,除了在調(diào)試時將某些指定到本地地址,如下: 所以換個DLMU來搞,cpu0_dlmu memory定義如下:
memory cpu0_dlmu { mau = 8; size = 64k; type = ram; map cached (dest=bus:sri, dest_offset=0x90000000, size=64k); map not_cached (dest=bus:sri, dest_offset=0xb0000000, size=64k); }我們將變量放到cpu0dlmu0,在不設(shè)置優(yōu)先級的情況下,編譯結(jié)果如下: 將not_cached地址優(yōu)先級提高,結(jié)果如下: 這里我們基本可以得出結(jié)論:數(shù)值越高,優(yōu)先級越高。 我們將cached ot_cached的代碼互換位置,優(yōu)先級不變,結(jié)果如下: 這就很神奇了,好像不是優(yōu)先級相同,先到先得,而是默認(rèn)為cached,這是為什么呢? 我們就從這個變量放置的段來找答案,對于section的定義,有兩種關(guān)鍵詞: section_setup:定義堆棧、copy、table、啟動地址等等
section_setup ::my_space { reserved address range stack definition heap definition copy table definition start address space reference restrictions input section modifications section reference restrictions MPU data table }
section_layout:定義一個或者多個section,并賦予section一個地址空間,可以指定運行地址、加載地址,section空間大小等等;可以這樣理解,我們寫的代碼、數(shù)據(jù)存放位置是在linker里lsl里的section指定,在車規(guī)中常常會會將標(biāo)定數(shù)據(jù)、信息安全數(shù)據(jù)等放置到特定位置,因此掌握這部分內(nèi)容是比較重要的。 實例如下:
仔細(xì)看,在示例中section_layout里還定義group了,它包含了一個或者多個input section,因此需要使用語法select 選擇section。 在上一個試驗中,我們把g_DataTest放到了section lmubss_cpu0,如下圖:
該section在lsl鏈接文件中定義如下:
注意看,此時run_addr為cpu0_dlmu,對應(yīng)memory:
編譯出來是cached地址,那有沒有辦法讓它在non-cached的地址? 根據(jù)lsl說明,使用語法:
group (run_addr = mem:A/map_name)修改如下:
編譯得到結(jié)果如下:
3.小結(jié)
上面兩節(jié)將lsl的基本框架和常用語法進行了梳理,其中比較重要的就是memory定義和section定義,這里最后再總結(jié)下如何將數(shù)據(jù)或者代碼放到指定位置:
首先定義一塊memory,使用語法memory name{ },指定map地址,mau,size;
在section_layout里用group定義運行地址,如有必要定義加載地址;
代碼里在待處理的數(shù)據(jù)或者代碼前后添加限定符#pragma,或者_(dá)_attribute__ ((section".name"))
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7145瀏覽量
89587 -
代碼
+關(guān)注
關(guān)注
30文章
4828瀏覽量
69059 -
TriCore
+關(guān)注
關(guān)注
0文章
15瀏覽量
11768
原文標(biāo)題:基于Tricore的Tasking鏈接文件解讀
文章出處:【微信號:eng2mot,微信公眾號:汽車ECU開發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論