目錄
1.Tricore尋址模式
2.lsl鏈接文件Section分析
3.限定符對于代碼的影響
4.小結
1.Tricore尋址模式
今天聊個好玩的事情。 之前ARM培訓的時候,他們對于函數形參的先后順序、數據類型、對齊方式等等做了介紹,詳細分析了上述操作不同寫法對于CPU的通用寄存器使用效率上的影響,這給我留下了一點印象,但不多。 而最近我在用ADS驗英飛凌LMU、DSPR、PSRP等等訪問效率時,發現了這樣一行代碼:
#pragma section farbss lmubss#pragma ,section,咱們都非常熟悉了,這個farbss是什么意思呢?以前做BSW還真沒多大關注這個。 查看Tasking的手冊,得到了一些答案,如下:
可以看到,上述farbss這類屬于lsl里的section類型,而對于其memory 限定符則為__far,它表示遠程數據;再看其他的限定符,分別出現了__a0,__a1等等,很明顯講的是Tricore內核的尋址模式,那么順著這個思路來捋捋線索,為代碼能力和系統優化打基礎。 Tricore 1.6.2的編程模型長這樣:
總共32個通用寄存器,其中16個作為數據寄存器D[0]-D[15],16個作為地址寄存器A[0]-A[15],特別的,A[0]、A[1]、A[8]、A[9]還可以作為系統Global寄存器進行使用,我們再回過頭來看看Tasking文件里給的memory限定符,似乎有某種聯系,因此接下來我們了解Tricore的尋址模式。 Tricore是32位機,很明顯可以訪問4GBytes(2^32)的memory空間,這4GB空間分成了16個Segment[0H-FH],用地址高四位來索引,每個Segment為256MBytes,其用法如下:
所謂尋址模式,就是LoadStore這類指令訪問數據元素的機制,這些數據元素長度可以為8163264bits。Tricore提供了7種尋址模式,如下圖:
絕對尋址:主要用于I/O 外設寄存器和全局數據的訪問,值得一提的是,這種方式只能訪問每個segment的前16K,原因如下:
利用高四位定位segment,利用低14位定位目標,而2^14剛好為16KB,這與Tasking memory限定符__near關聯。 基地址+偏移:主要用于局部變量、靜態數據等訪問,根據偏移的不同尋址方式可以分為short offset尋址(10 bits)和long offset尋址(16bits)。long offset尋址剛好就對應__a0a1a8a9訪問。 故對于尋址方式與限定符關聯關系如下:
那這個__far到底指的是什么呢?根據手冊描述,指的是能夠訪問所有memory區域的數據,難不成這些個限定符還會對匯編代碼有所影響嗎?這些限定符與鏈接文件有沒有關聯呢?
2.lsl鏈接文件Section分析
在ADS給的lsl模板中,可以看到關于上述限定符以及對應section type的描述,例如:
/*Near Abbsolute Addressable Data Sections*/ section_layout abs18 { group { } } /*Relative A0/A1/A8/A9 Addressable Sections*/ section_layout linear { group { } }
其中,abs18表示18bit絕對尋址空間,linear表示線性地址空間,如下圖所示:
.bss:未初始化數據
.bss_a0a1a8a9:未初始化數據,用寄存器A0A1A8A9尋址
.data:已初始化數據
.data_a0a1a8a9:已初始化的數據,用寄存器A0A1A8A9尋址
.sbss:未初始化的數據,a0尋址
.sdata:已初始化的數據,a0尋址
.zbss:未初始化數據,abs18尋址
.zdata:已初始化數據,abs18尋址
我們在Cpu0_main.c里定義兩個變量,不添加任何限定符,如下:
編譯生成出來的map,可以看到這兩個變量是放在.bss中: ?對應lsl定義的Far Data Section:
如果加上限定符__near,如下:
uint32 __near example_x ; uint32 __near example_y;
編譯出來發現已經放到了zbss段
如果加上限定符__a0,我們會發現這時候編譯出了問題,如下:
ltc E121: relocation error in "task1": relocation value 0x50000000, type R_TRICORE_16SM, offset 0x34, section ".text.Cpu0_Main.core0_main" at address 0x800023bc is not within a 16-bit signed range from the value of A0 as defined by the symbol _SMALL_DATA_
這就意味著,如果要使用寄存器+偏移尋址的方式,那么就必須是A0A1...寄存器中內容上下偏移±32KB,例如,當A0寄存器里內容為0xD0018000時,那么通過A0寄存器尋址的所有變量就應該在0xD0010000 - 0xD001FFFF。這個場景后面構建了我們再討論,但至少我們確定了利用寄存器+偏移的方式多用于局部變量訪問。
3.限定符對于代碼的影響
第二節我們發現了利用不同限定符將變量發到不同的section里,但是變量的地址始終沒有變化,那這到底有什么用呢? 編譯出來的C代碼最終會以匯編形式展示給機器,因此我們來看看不同限定符下對于代碼的影響。 1)添加__near限定符,編譯得到的結構,代碼如下:
uint32 __near example_x ; uint32 __near example_y; void main(void) { example_x = 3; example_y=example_x+2; }得到匯編代碼如下
解釋如下:
將立即數3賦給寄存器D15
D15的值直接賦給變量(x)
立即數3賦給寄存器D15
D15和2相加
將D15的值直接賦給變量(y)
統計攏共5條指令完成x=3,y=x+2這個操作; 2)添加__far限定符,得到如下
uint32 __far example_x ; uint32 __far example_y; void main(void) { example_x = 3; example_y=example_x+2; }匯編代碼如下:
解釋如下:
x的賦值:
將0x7000給到地址寄存器A15高16bit,低位補0,這時候A15 = 0x70000000
加載有效地址到A15,因為x地址為0x70000004,故A15 = 0x70000004
將數據3移至D15;
將D15賦給A15指向的地址
y的賦值
將0x7000給到地址寄存器A15高16bit,低位補0,這時候A15 = 0x70000000
加載有效地址到A15,因為y地址為0x70000008,故A15 = 0x70000008
將數據3移至D15,并加2;
將D15賦給A15指向的地址
總計9條指令,咋一看僅僅節省了4條指令,但從統計角度來看,效率提升了44.44%,Flash消耗更少了。 同樣兩行C代碼,僅僅因為尋址方式的不同,匯編指令差異如此之大 ,從而影響系統運行效率。
4.小結
現在MCU的性能越來越強大,導致我在使用上越來越隨意,對于這種特別底層的知識非常匱乏,直到遇到了系統優化問題,才會去從這些角度來考慮。總結下來,在系統性能優化時要注意:
構建memory限定符使用場景以優化代碼執行效率;
多使用靠近CPU的memory,例如ARM TCM、Tricore DSPR、PSPR;
通過調試匯編代碼,也更進一步了解了Tricore內核的運行原理;接下來,思考如何將這些理論引入到工程代碼中。
-
寄存器
+關注
關注
31文章
5336瀏覽量
120230 -
效率
+關注
關注
0文章
149瀏覽量
20051 -
TriCore
+關注
關注
0文章
15瀏覽量
11748
原文標題:TC3xx分析--如何提高系統運行效率
文章出處:【微信號:eng2mot,微信公眾號:汽車ECU開發】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論