2440的協處理器CP15總共有c0~c15這16個協處理器寄存器,各自具有一定的功能定義。但總的來說,cp15主要跟以下功能有關:
1、擷取device id和cache type等一些CPU相關資訊。
2、MMU操作。包括MMU的使能和禁止,虛拟位址到實體位址的映射機制建立
3、通路權限控制。主要用來實作安全機制和linux的寫時複制(copy on write)。
4、設定時鐘模式。init.S中MMU_SetAsyncBusMode和MMU_SetFastBusMode這兩個函數
下面我會分别就以上4種應用詳細分析,并配合代碼進行講解。
1、擷取device id和cache type。這兩個資訊存在p15的c0寄存器中,有意思的是c0寄存器有兩個實體,一個用來存device id(叫做c0.0),另一個用來存cache type(叫做c0.1)這兩個寄存器在讀取時指令不同,請參看以下示例代碼。
U32 P15_ReadID(void)
{
U32 id;
__asm{
mrc p15,0,id,c0,c0;
}
return id;
}
U32 P15_ReadCacheType(void)
{
U32 id;
__asm{
mrc p15,0,id,c0,c0,1;
}
return id;
}
對以上代碼的說明:
(1) CPU從p15讀出寄存器隻能使用mrc指令。同樣,寫入p15寄存器隻能使用mcr指令。這兩個指令也是p15唯一可以接受的兩個指令。
(2) __asm{ }用來在c代碼中内嵌彙編。
(3) 從代碼中可以看出,讀出c0.0和c0.1的代碼,在opcode2處有所不同。(讀出c0.1時,opcode2為1.c0.0時opcode2省略)。
(4) 我使用的S3C2440實際讀出的device id為 0x41129200;cache type為:0xd172172。和Jlink Commander識别出得參數對比是相同的。
2、MMU操作。
和MMU有關的p15寄存器為c1(control register)和c2(TTB translation table base register)。其中c2比較簡單,就是用來儲存從虛拟位址到實體位址的位址轉換表的基位址的(轉換表存放在記憶體中,譬如可以放在0x30000000位址),是以我們在初始化mmu的時候,隻要将規劃的轉換表基位址用mcr指令傳送到該c2寄存器即可。而c1寄存器為控制寄存器,詳細定義如下:
Register 1 - Control (read/write)
All values set to 0 at power-up.
o Bit 0 - On-chip MMU turned off (0) or on (1) 用來關閉或使能MMU
o Bit 1 - Address alignment fault disabled (0) or enabled (1) 關閉或打開位址對齊檢查
o Bit 2 - Data cache turned off (0) or on (1) 資料cache打開或關閉
o Bit 3 - Write buffer turned off (0) or on (1)
o Bit 7 - Little-endian operation if 0, big-endian if 1 用來選擇大小端格式
o Bit 8 - System bit - controls the MMU permission system
o Bit 9 - ROM bit - controls the MMU permission system bit8(S bit ) and bit9(R bit)用來管理MMU通路權限,第3部分會詳述
o Bit 12 - Instruction cache turned off (0) or on (1)” 指令cache打開或關閉
o Bit 13 - Base location of exception registers. 0x00000000(0) or 0xffff0000(1) 上電啟動位址。
o Bit 14 - Round robin replacement ,random replacement(0) or round-robin replacement(1). 不太懂這個
o Bit 15 ~ Bit29 reserved
o Bit 30 nF bit bit30 和 bit31共同用來決定總線模式。 iA:nF = 00 FastBus mode
o Bit 31 iA bit 01 Synchronous mode 10 reserved 11 Asynchronous mode
結合以上對c1寄存器的位定義的分析,我們來看看下面這個函數:
void MMU_Init(void)
{
__asm{
mov r0,#0x30000000; // r0=TTBase 即頁表的基位址
mcr p15,0,r0,c2,c0,0; // C2中存放位址轉換表基位址
mvn r0, #0; // 資料取反傳送指令
mcr p15,0,r0,c3,c0,0; // 通路類型為管理者權限
mrc p15,0,r0,c1,c0,0; // 讀出協處理器C1
orr r0,r0,#01; // 或操作,使最低位為1
mcr p15,0,r0,c1,c0,0; // 給C1指派
}
}
函數中使用ARM寄存器r0作為和協處理器寄存器的接口。mcr p15,0,r0,c2,c0,0這句将r0中得值(0x30000000,這個是我們規劃的轉換表的基位址)放入(是以是mcr,是以是從ARM寄存器到p15協處理器寄存器)c2中。c2即是p15中的轉換表基址。
mrc p15,0,r0,c1,c0,0; // 讀出協處理器C1
orr r0,r0,#01; // 或操作,使最低位為1
mcr p15,0,r0,c1,c0,0; // 給C1指派
典型的讀-改-寫三步操作,目的就是将c1寄存器的bit0置1而同時不影響其他位。根據上面的寄存器定義可知,c1的bit0為MMU enable or disable,是以該三句代碼實際上是打開了MMU。(注意MMU打開前後,位址空間發生了變化。MMU打開前程式是工作在實體位址空間的,而MMU打開後程式便工作在了虛拟位址空間)
c1中跟MMU有關的還有data cache和instruction cache的打開和關閉,S bit和 R bit聯合組成的通路權限控制等位。另外,c1中還有其他一些我們可能會用到的資訊位。
譬如:Bit7用來選擇大小端模式,bootloader中一般會有代碼,通過設定該位來告知CPU目前闆子使用的是little endian or big endian。(因為該位上電預設是0,是以預設的模式為小端模式。); Bit13為上電啟動位址,也就是reset excetion複位異常的入口位址。上電預設也是0,是以預設的上電啟動位址為0x00000000。當我們使用mcr指令将該位置1時,便可以将reset exception設定到 0xffff0000,記得這個好像是為了WinCE的移植支援設計的。
3、通路權限控制。
通路權限控制主要由c3(domain access control register)和c1中的S bit 和R bit共同控制。詳細情況請參考 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0151c/I273867.html。
從上面連結中的介紹可以看出,c3中的32bit正好組成16組,每組占用2bit,這兩bit若為0x00,那麼具體的通路規則則由S bit + R bit決定。若為0x01或0x10或0x11則S bit和R bit不起作用。 其實所有的情況都包含在下面這張表中了
AP | S | R | Supervisor permissions | User permissions | Description |
---|---|---|---|---|---|
00 | No access | No access | Any access generates a permission fault | ||
00 | 1 | Read-only | No access | Only Supervisor read permitted | |
00 | 1 | Read-only | Read-only | Any write generates a permission fault | |
00 | 1 | 1 | Reserved | - | - |
01 | x | x | Read/write | No access | Access allowed only in Supervisor mode |
10 | x | x | Read/write | Read-only | Writes in User mode cause permission fault |
11 | x | x | Read/write | Read/write | All access types permitted in both modes |
xx | 1 | 1 | Reserved | - | - |
4、設定bus mode
bootloader中有兩個函數是用來設定bus mode的,關于這個bus mode不是很清楚具體情況,我們這裡隻是分析其操作過程。
MMU_SetAsyncBusMode
mrc p15,0,r0,c1,c0,0 ; 讀出c1
orr r0,r0,#R1_nF:OR:R1_iA ;
mcr p15,0,r0,c1,c0,0 ; R1的nF和iA位置1,11對應 Asynchronus bus mode
MOV_PC_LR
MMU_SetFastBusMode
mrc p15,0,r0,c1,c0,0
bic r0,r0,#R1_iA:OR:R1_nF ; 清零nF和iA這兩位,00對應 fast bus mode
mcr p15,0,r0,c1,c0,0
MOV_PC_LR