tiny4412開發板icache操作程式
首先,來介紹關於cache的概念。
cache的作用:
基於程式訪問的侷限性,在主存和CPU通用暫存器之間設定了一個高速的、容量相對較小的儲存器,把正在執行的指令地址附近的一部分指令或資料從主存調入這個儲存器,供CPU在一段時間內使用,這對提高程式的執行速度有很大的作用。這個介於主存和CPU之間的高速小容量儲存器稱作快取記憶體儲存器(Cache)。
啟用Cache後,CPU讀取資料時,如果Cache中有這個資料的複本則直接返回,否則從主存中讀入資料,並存入Cache中,下次再使用(讀/寫)這個資料時,可以直接使用Cache中的複本。
啟用Cache後,CPU寫資料時有寫穿式和回寫式兩種方式。
(1)寫穿式(Write Through)
任一從CPU發出的寫訊號送到Cache的同時,也寫入主存,可以保證主存的資料能同步地更新。它的優點是操作簡單,但由於主存的慢速,降低了系統的寫速度並佔用了匯流排的時間。
(2)回寫式(Write Back)
為了克服貫穿式中每次資料寫入時都要訪問主存,從而導致系統寫速度降低並佔用匯流排時間,儘量減少對主存的訪問次數,又有了回寫式。
它是這樣工作的:資料一般只寫到Cache,這樣有可能出現Cache中的資料得到更新而主存中的資料不變(資料陳舊)的情況。但此時可在Cache中設一標誌地址及資料陳舊的資訊,只有當Cache中的資料被換出或強制進行清空操作時,才能將更新的資料寫入主存相應的單元中。這樣保證了Cache和主存中的資料一致。
先介紹Cache的兩個操作。
(1)清空:把Cache或Write buffer中已經髒的(修改過,但未寫入主存)資料寫入主存。
(2)使無效:使之不能再用,並不將髒的資料寫入主存。
ICache的使用比較簡單。系統剛上電或復位時,ICache中的內容是無效的,並且ICache功能是關閉著的。往Icr(CP15協處理器中暫存器1的第12位)寫1可以啟動ICache,寫0可以停止ICache。
ICache一般在MMU開啟之後被使用,此時頁表中描述符的C位用來表示一段記憶體是否可以被ICache。若Ctt=1,則允許ICache,否則不允許被ICache。但是,即使MMU沒有開啟,ICache也可以被使用的,這時CPU讀取指令時所涉及的記憶體都被當做是允許ICache的。
ICache被關閉時,CPU每次讀取指令都讀取主存,效能非常低。所以,通常儘早啟動ICache。
ICache被開啟後,CPU每次讀取指令時都會先在ICache中檢視是否能找到所要的指令,而不管Ctt是0還是1。如果找到了,稱為Cache命中,如果找不到,稱為Cache缺失。ICache被開啟後,CPU的取指分為如下3種情況。
(1)Cache命中且Ctt為1時,從ICache中取出指令,返回給CPU。
(2)Cache缺失且Ctt為1時,CPU從主存中讀出指令。同時,一個被稱為"8-word linefill"的動作將發生,這個動作把該指令所處區域8個word寫進ICache的某個條目中。這有可能會覆蓋某個條目,可以使用Pseudo-random演算法或round-robin演算法在ICahe中選出某個沒有被鎖定的條目。可以通過CP15協處理器中暫存器1的第14位來選擇使用哪種演算法。
(3)Ctt為0時,CPU從主存中讀取指令。
OK,關於Cache的基本知識已經介紹完畢了。要開啟DCache需要先開啟MMU,所以這裡我們只講解關於ICache的操作。
在上面已經介紹了,如果要開啟ICache,需要操作CP15協處理的暫存器1的bit12,寫入1表示開啟,寫入0表示關閉。
先來看兩條操作CP15協處理器的指令:MCR和MRC指令。
MCR:
MCR指令將ARM處理器的暫存器中的資料傳送到協處理器的暫存器中。如果協處理器不能成功地執行該操作,將產生未定義的指令異常中斷。
指令的語法格式:
MCR{<cond>} p15, {opcode_1} , <Rd>, <CRn>, <CRm> {,<opcode_2>}
其中,<cond>為指令執行的條件碼。當<cond>忽略時指令為無條件執行。
<opcode_1>為協處理器將執行的操作的操作碼。對於CP15協處理器來說,<opcode_1>永遠為0b000,當<opcode_1>不為0b000時,該指令操作結果不可預知。
<Rd>作為源暫存器的ARM暫存器,其值被傳送到得協處理器暫存器中。<Rd>不能為PC,當其為PC時,指令操作結果不可預知。
<CRn>作為目標暫存器的協處理器暫存器,其編號可能為C0,C1....C15。
<CRm>附加的目標暫存器或者原運算元暫存器,用於區分同一個編號的不同物理暫存器。當指令中不需要提供附加資訊時,將C0指定為<CRm>,否則指令操作結果不可預知。
<opcode_2>提供附加資訊,用於區別同一個編號的不同物理暫存器。當指令中指定附加資訊時,省略<opcode_2>或者將其指定為0,否則指令操作結果不可預知。否則指令操作結果不可預知。
MRC:
MRC指令將協處理器的暫存器中數值傳送到ARM處理器的暫存器中。如果協處理器不能成功地執行該操作,將產生未定義的指令異常中斷。
指令的語法格式:
MRC{<cond>} p15, {opcode_2}, <Rd>, <CRn>, <CRm> {,<opcode_2>}
操作ICache程式示例;
我們使用前面操作LED迴圈點亮的程式。首先,不開啟ICache,檢視LED的亮滅時間間隔。然後開啟ICache,檢視LED的亮滅時間間隔。
start.S檔案內容如下:
.text
.global _start
_start:
//注意:在晶片的iROM中已經開啟了ICache;即使這裡開啟也觀察不到什麼變化;
//所以這裡將ICache關閉,觀察LED的亮滅情況;可以和原來的對比發現,速度慢了很多
//將CP15協處理器的C1暫存器的值儲存到R0暫存器中
mrc p15, 0, r0, c1, c0, 0
//將R0中的資料的BIT12置0
bic r0, r0, #0x00001000
//將R0中的資料寫回CP15協處理器的C1暫存器中
mcr p15, 0, r0, c1, c0, 0
ldr sp, =0x02027400 //設定棧
bl main //跳轉到mian函式開始執行
halt_loop: //死迴圈
b halt_loop
上面的程式中已經做了詳細的註釋,將ICache禁止了。可以將程式編譯並燒寫。檢視LED的閃亮時間間隔。發現和原來的程式相比LED閃亮週期大了很多。
本文完畢!