以童話的方式深入淺出地講述了 Cortex M7 核心 MCU 的 ITCM 和 ICache 的原理、優勢和用法。 ...
"叮鈴鈴… 叮鈴鈴…"
"誰呀?"黛絲博士打開了家門,"哇,高飛,你怎麼來了?"
高飛狗:"好久不見,想來看看你,還買了你最喜歡吃的純黑巧克力。"
黛絲:"以往都是布魯托領著你來的,今天你獨自上門,必定不懷好意。買了這麼多巧克力,必是別有他圖吧?"
高飛狗:"你這說的什麼話,咱倆一塊長大的,怎麼會不懷好意? 別有他圖倒是真的。"
黛絲:"我就知道你無事不登八寶殿! 說吧,又遇到什麼傷腦筋的難題了。"
高飛狗:"是這樣的,這兩年以Cortex-M7(以下簡稱CM7)為核心的MCU越來越多,CPU周圍新增了幾種部件,例如ITCM和ICache,最新的STM32H743,ITCM容量高達64KB,ICache容量高達16KB,我對其功能一知半解,對其用法一頭霧水,你能不能給詳細講解一番?"
黛絲:"高飛,你什麼時候變得勤奮好學了,居然研究起高大上的科技來了。"
高飛狗心想:"只要能把你這白富美搞到手,再高大上的困難也要不惜一切代價剋服。"
黛絲:"ITCM和ICache還真是很時尚的東西,畢竟是新事物,我研究的時間也不長,談不上講解,說錯的地方還請及時指正。"
高飛狗:"你太謙虛了!"
黛絲:"咱們還是從實際問題出發吧。"
黛絲:"以堆棧空間為例。堆棧空間及其存儲的各種數據(含應用程式中的所有局部變數),只有CPU才會訪問,而且是頻繁訪問。但是,在CM7出現以前,堆棧空間只能放在SRAM中,而SRAM是共用資源,DMA可以訪問,其它匯流排Master也都可以訪問。導致了以下問題:"
黛絲:"Q1:CPU要和其它匯流排Master爭奪SRAM訪問控制權,最慘的時候,CPU只有50%的時間可以訪問SRAM,極大地降低了程式性能。"
黛絲:"Q2:其它匯流排Master有可能篡改堆棧空間上的數據,嚴重威脅應用程式的安全。"
高飛狗:"對對對,我就有過這樣的經歷。"
黛絲:"ITCM的出現,徹底解決了以上兩個問題。ITCM就是CPU的後宮,歸CPU專享、專用、私有、獨占。我們把堆棧空間安排在ITCM內,CPU就可以零等待、單周期、全速訪問堆棧空間和頻繁用到的數據對象,大大提升應用程式性能,且其中的數據不會被其它匯流排Master篡改,大大提升了應用程式的安全性。"
高飛狗:"茅塞頓開!"
高飛狗:"除此之外,ITCM還有什麼用?"
黛絲:"在複雜應用程式中,常常高頻地、隨機地發生各種中斷。發生中斷時,就要讀取中斷向量表(IVT),然後跳轉到中斷服務程式(ISR)。在CM7出現之前,CPU應對中斷存在以下幾個頭疼的問題:"
黛絲:"Q1:IVT與被中斷代碼的物理地址相距(簡稱空距)通常較遠,需要耗費多個機器周期才能讀取中斷向量。"
黛絲:"Q2:而ISR與IVT的空距通常也較遠,又需要耗費多個機器周期才能跳轉到ISR。"
黛絲:"於是,產生一次中斷,要耗費許多機器周期才能跳轉執行到ISR。"
黛絲:"Q3:ISR返回到被中斷代碼又要耗費許多個機器周期。"
黛絲:"執行一次ISR,花費在代碼跳轉上的時間看似不多。但是,高度頻繁、隨機發生的各種中斷,將使CPU在程式跳轉上耗費極其巨大的時間。在複雜、實時性要求較高的應用中,其代價還是很可觀的。"
黛絲:"ITCM的出現,完美解決了以上3個問題。程式設計者可以人為地把IVT和ISR安排在一塊連續地址空間內,在系統啟動時將其全部裝入ITCM中,由於CPU訪問ITCM總是單周期的,以上3個問題中的程式跳轉均可以單周期完成,大幅提升了ISR的實時性能。"
高飛狗:"我記得MCU內部通常都配有自適應實時加速器 (ART-Accelerator™),為什麼還需要ITCM來做這項工作呢?"
黛絲:"在順序讀取連續存放的指令時,ART- Accelerator有明顯的提速效果。而以上3個問題的情形,基本上是隨機讀取指令,也就是代碼間的空距較遠,ART- Accelerator的效果就大打折扣,基本沒什麼提速作用,這正是ART- Accelerator的短板,而ITCM的出現則大大提升了隨機讀取指令和數據的性能,補上了ART- Accelerator的短板。"
高飛狗:"我明白了。"
高飛狗:"親愛的,我發現,STM32H743的ITCM容量高達64KB,除了緩存IVT、ISR、堆棧空間之外,把整個RTOS緩存進去也沒問題。如此,CPU就可以獨占地、單周期訪問高頻度用到的代碼和數據,應用程式的性能提高幅度將是不可想象的。"
黛絲:"你還是很開竅的! 比以前聰明多了!"
高飛狗:"我明白為什麼要把ITCM的容量設計得這麼大了。"
高飛狗:"CM7是32位核心,為何ITCM被設計為64位寬度?"
黛絲:"雖然CM7的整數運算能力多為32位,但也有少量64位整數運算指令和大量64位雙精度浮點數運算指令,傳送64位數據的需求還是很多的,而且很多指令需要一次傳送多個32位數據,如下表所示,與32位匯流排寬度相比,64位的匯流排寬度可以節省50%的數據傳送時間,性能提升是非常可觀的。"
例子:一次傳送64位寬度數據的指令 |
說明 |
LDRD R8, R9, [R3]; |
以R3為地址指針,將一個64位雙字載入R8和R9 |
LDM R8, {R0-R3} |
以R8為地址指針,讀取4個32位數據到寄存器中 相當於傳送2個64位雙字 |
STM R1, {R3-R6,R11,R12} |
以R1為地址指針,存儲6個32位寄存器數據 相當於傳送3個64位雙字 |
PUSH {R4-R7}; |
將4個32位寄存器推入堆棧,相當於2個64位雙字 |
64位雙精度浮點數的讀取和存儲指令 |
不再列出具體指令 |
高飛狗:"聽你講了這麼多,勝讀多年書。有點累了吧? 我給你泡杯咖啡,吃塊巧克力如何?"
黛絲:"你倒反客為主了!還有啥問題,一氣問了,我還要出去辦事呢。"
高飛狗心想:"還這麼厲害,一絲咸聊的機會都不給。"
高飛狗:"既然ITCM這麼好,為什麼還出了個ICache,又有什麼用呢? 總有種既生高飛,何生黛絲的感覺!"
黛絲:"巧言令色,看我不踩死你!"
黛絲:"這還得看一個小例子,才能說得明白。如下表所示。"
// 迴圈1億次 while (…) { function1(); // 函數地址在0x10000 function2(); // 函數地址在0x20000 function3(); // 函數地址在0x30000 } |
黛絲:"這段小程式有2個特點:
F1:3個函數順序得到執行,在執行時間上是相鄰的,簡稱時距相鄰。
F2:3個函數的物理地址相距很遠,簡稱空距很遠。
因為空距很遠,前一個函數執行完畢後,跳轉執行到下一個函數,至少需要花費3個機器周期,迴圈的1次執行花費在跳轉上的時間至少9個機器周期,迴圈的1億次執行相應的開銷至少9億個機器周期!
有了ICache之後,情況大不相同。
ICache的特點是自動地把時距相鄰的代碼儘可能集中存放在自己體內,而不管這些代碼的空距有多遠,且CPU以單周期訪問ICache。"
黛絲:"以上述小迴圈為例,在執行function1()期間,ICache會把function1()儘可能緩存在自己體內,在執行完一次迴圈後,如果3個函數的總容量不超過ICache的容量,那麼3個函數的全部代碼均已緩存在ICache體內。從迴圈的第2次執行開始,CPU只需訪問ICache就可以執行整個迴圈,不必再訪問FLASH,所有指令的獲取都是單周期的。前一個函數執行完畢後,跳轉執行到下一個函數,只需1個機器周期,迴圈的1億次執行花費在函數跳轉上的時間只需3億個機器周期!"
黛絲:"通常,函數function1/2/3()還會調用其它許多函數,函數之間的跳轉切換數量要遠遠多於如上所說。只要容量足夠大,ICache還會把被function1/2/3()調用的其它函數通通緩存到體內,由此而節約的執行時間遠遠大於如上所述。"
黛絲:"所以,ICache的優勢是智能地、自動地將時距相鄰而空距很遠的代碼段放置在體內,CPU以單周期訪問這些代碼,大大提升了程式性能。"
黛絲:"而ITCM的優勢是大大提升了時距不相鄰而空距相鄰的代碼段的執行性能,且需要人為地把代碼組織成空距相鄰。"
高飛狗:"ICache會不會緩存ITCM中的代碼?"
黛絲:"由於CPU能夠以單周期訪問ITCM中的全部內容,所以ITCM中的內容不必緩存到ICache。在CPU硬體設計上就確保做到這一點。所以,ICache中緩存的代碼一定是ITCM之外的內容。"
高飛狗:"ITCM和ICache還真的各有所長。"
高飛狗:"你講了這麼多,我來總結一下,你看對不對。"
高飛狗:"結論1:ITCM既能緩存代碼也能緩存數據,但需要人為地把頻繁執行的代碼、IVT、ISR和堆棧空間連成一片(空距相鄰),人為地裝入其中。從而使CPU以單周期、獨占方式訪問這些代碼和數據,大幅提升應用程式的性能和安全性。"
高飛狗:"結論2:ICache只能緩存代碼,但智能地、自動地將時距相鄰而空距很遠的代碼段放置在體內,CPU以單周期訪問這些代碼,大幅提升程式性能。"
高飛狗:"簡而言之,ITCM和ICache是CPU的貼身侍衛。"
黛絲:"概括得非常好。"
黛絲:"對於STM32H743,ITCM和ICache的總容量已達到80KB,如果程式設計者精心安排,使得80%的時間CPU是在這兩者內部執行程式,應用程式的性能提升將會極其巨大。"
高飛狗:"ITCM是Instruction Tightly Coupled Memory的縮寫,似乎其中只能存放代碼?"
黛絲:"你還挺細心的!ITCM也可以存放數據,例如堆棧空間。所以,這個名詞的確有些詞不達意。"
高飛狗:"對了,CM7核心還新增了DCache部件。最近做了一些實驗,涉及DMA傳送,好像一啟用DCache,數據讀寫和傳送就出問題;只要禁用DCache,一切都正常。你能不能給我詳細講解一番?"
黛絲:"今天時間不早了,我還得出去辦事,下次再說吧。"
高飛狗:"那我請吃晚飯,聊表謝意!"
黛絲:"飯和謝就免了,你再不走我就打跑了你!"
高飛狗:"這麼厲害呀!那我就不客氣了,先走一步了。"
"高飛的白鷺,黛絲的鵝,唐詩里有畫,唐詩里有歌,唐詩是我對你的表白…"