ARM926EJ-S/ARM920T 協處理器 CP14, CP15詳解
ARM 微處理器可支援多達 16 個協處理器,用于各種協處理操作,在程式執行的過程中,每個協處理器隻執行針對自身的協處理指令,忽略 ARM 處理器和其他協處理器的指令。ARM 的協處理器指令主要用于 ARM 處理器初始化 ARM 協處理器的資料處理操作,以及在ARM 處理器的寄存器和協處理器的寄存器之間傳送資料,和在 ARM 協處理器的寄存器和存儲器之間傳送資料。 ARM 協處理器指令包括以下 5 條:
— CDP 協處理器數操作指令
— LDC 協處理器資料加載指令
— STC 協處理器資料存儲指令
— MCR ARM 處理器寄存器到協處理器寄存器的資料傳送指令
— MRC 協處理器寄存器到ARM 處理器寄存器的資料傳送指令
1、CDP 指令
CDP 指令的格式為:
CDP{條件} 協處理器編碼,協處理器操作碼1,目的寄存器,源寄存器1,源寄存器2,協處理 器操作碼2。 CDP 指令用于ARM 處理器通知ARM 協處理器執行特定的操作,若協處理器不能成功完成特定的操作,則産生未定義指令異常。其中協處理器操作碼1 和協處理器操作碼2 為協處理器将要執行的操作,目的寄存器和源寄存器均為協處理器的寄存器,指令不涉及ARM 處理器的寄存器和存儲器。
指令示例:
CDP P3 , 2 , C12 , C10 , C3 , 4 ;該指令完成協處理器 P3 的初始化
2、LDC 指令
LDC 指令的格式為:
LDC{條件}{L} 協處理器編碼,目的寄存器,[源寄存器]
LDC 指令用于将源寄存器所指向的存儲器中的字資料傳送到目的寄存器中,若協處理器不能成功完成傳送操作,則産生未定義指令異常。其中,{L}選項表示指令為長讀取操作,如用于雙精度資料的傳輸。
指令示例:
LDC P3 , C4 , [R0] ;将 ARM 處理器的寄存器 R0 所指向的存儲器中的字資料傳送到協處理器 P3 的寄存器 C4 中。
3、STC 指令
STC 指令的格式為:
STC{條件}{L} 協處理器編碼,源寄存器,[目的寄存器]
STC 指令用于将源寄存器中的字資料傳送到目的寄存器所指向的存儲器中,若協處理器不能成功完成傳送操作,則産生未定義指令異常。其中,{L}選項表示指令為長讀取操作,如用于雙精度資料的傳輸。
指令示例:
STC P3 , C4 , [R0] ;将協處理器 P3 的寄存器 C4 中的字資料傳送到 ARM 處理器的寄存器R0 所指向的存儲器中。
4、MCR 指令
MCR 指令的格式為:
MCR{條件} 協處理器編碼,協處理器操作碼1,源寄存器,目的寄存器1,目的寄存器2,協處理器操作碼2。
MCR 指令用于将ARM 處理器寄存器中的資料傳送到協處理器寄存器中,若協處理器不能成功完成操作,則産生未定義指令異常。其中協處理器操作碼1 和協處理器操作碼2 為協處理器将要執行的操作,源寄存器為ARM 處理器的寄存器,目的寄存器1 和目的寄存器2 均為協處理器的寄存器。
指令示例:
MCR P3,3,R0,C4,C5,6;該指令将 ARM 處理器寄存器 R0 中的資料傳送到協處理器 P3 的寄存器 C4 和 C5 中。
5、MRC 指令
MRC 指令的格式為:
MRC{條件} 協處理器編碼,協處理器操作碼1,目的寄存器,源寄存器1,源寄存器2,協處理器操作碼2。
MRC 指令用于将協處理器寄存器中的資料傳送到ARM 處理器寄存器中,若協處理器不能成功完成操作,則産生未定義指令異常。其中協處理器操作碼1 和協處理器操作碼2 為協處理器将要執行的操作,目的寄存器為ARM 處理器的寄存器,源寄存器1 和源寄存器2 均為協處理器的寄存器。
指令示例:
MRC P3,3,R0,C4,C5,6;該指令将協處理器 P3 的寄存器中的資料傳送到 ARM 處理器寄存器中.
The ARM920T 有兩個具體協處理器
CP14調試通信通道協處理器
調試通信通道協處理器DCC(the Debug Communications Channel)提供了兩個32bits寄存器用于傳送資料,還提供了6bits通信資料控制寄存器控制寄存器中的兩個位提供目标和主機調試器之間的同步握手。
通信資料控制寄存器
以下指令在 Rd 中傳回控制寄存器的值:
MRC p14, 0, Rd, c0, c0

此控制寄存器中的兩個位提供目标和主機調試器之間的同步握手:
位 1(W 位) 從目标的角度表示通信資料寫入寄存器是否空閑:
W = 0 目标應用程式可以寫入新資料。
W = 1 主機調試器可以從寫入寄存器中掃描出新資料。
位 0(R 位) 從目标的角度表示通信資料讀取寄存器中是否有新資料:
R = 1 有新資料,目标應用程式可以讀取。
R = 0 主機調試器可以将新資料掃描到讀取寄存器中。
注意
調試器不能利用協處理器 14 直接通路調試通信通道,因為這對調試器無意義。 但調試器可使用掃描鍊讀寫 DCC 寄存器。 DCC 資料和控制寄存器可映射到 EmbeddedICE 邏輯單元中的位址。 若要檢視 EmbeddedICE 邏輯寄存器,請參閱您的調試器和調試目标的相關文檔。
通信資料讀取寄存器
用于接收來自調試器的資料的 32 位寬寄存器。 以下指令在 Rd 中返
回讀取寄存器的值:
MRC p14, 0, Rd, c1, c0
通信資料寫入寄存器
用于向調試器發送資料的 32 位寬寄存器。 以下指令将 Rn 中的值寫
到寫入寄存器中:
MCR p14, 0, Rn, c1, c0
注意
有關通路 ARM10 和 ARM11 核心 DCC 寄存器的資訊,請參閱相應的技術參考手冊。 ARM9 之後的各處理器中,所用指令、狀态位位置以及對狀态位的解釋都有所不同。
目标到調試器的通信
這是運作于 ARM 核心上的應用程式與運作于主機上的調試器之間的通信事件
順序:
1. 目标應用程式檢查 DCC 寫入寄存器是否空閑可用。 為此,目标應用程式使
用 MRC 指令讀取調試通信通道控制寄存器,以檢查 W 位是否已清除。
2. 如果 W 位已清除,則通信資料寫入寄存器已清空,應用程式對協處理器 14
使用 MCR 指令将字寫入通信資料寫入寄存器。 寫入寄存器操作會自動設定
W 位。如果 W 位已設定,則表明調試器尚未清空通信資料寫入寄存器。此
時,如果應用程式需要發送另一個字,它必須輪詢 W 位,直到它已清除。
3. 調試器通過掃描鍊 2 輪詢通信資料控制寄存器。 如果調試器發現 W 位已設
置,則它可以讀 DCC 資料寄存器,以讀取應用程式發送的資訊。 讀取資料
的程序會自動清除通信資料控制寄存器中的 W 位。
以下代碼顯示了這一過程
AREA OutChannel, CODE, READONLY
ENTRY
MOV r1,#3 ; Number of words to send
ADR r2, outdata ; Address of data to send
pollout
MRC p14,0,r0,c0,c0 ; Read control register
TST r0, #2
BNE pollout ; if W set, register still full
write
LDR r3,[r2],#4 ; Read word from outdata
; into r3 and update the pointer
MCR p14,0,r3,c1,c0 ; Write word from r3
SUBS r1,r1,#1 ; Update counter
BNE pollout ; Loop if more words to be written
MOV r0, #0x18 ; Angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC 0x123456 ; ARM semihosting (formerly SWI)
outdata
DCB "Hello there!"
END
調試器到目标的通信
這是運作于主機上的調試器向運作于核心上的應用程式傳輸消息的事件順序:
1. 調試器輪詢通信資料控制寄存器的 R 位。 如果 R 位已清除,則通信資料讀
取寄存器已清空,可将資料寫入此寄存器,以供目标應用程式讀取。
2. 調試器通過掃描鍊 2 将資料掃描到通信資料讀取寄存器中。 此操作會自動
設定通信資料控制寄存器中的 R 位。
3. 目标應用程式輪詢通信資料控制寄存器中的 R 位。 如果該位已經設定,則
通信資料讀取寄存器中已經有資料,應用程式可使用 MRC 指令從協處理器
14 讀取該資料。 同時,讀取指令還會清除 R 位。
以下顯示的目标應用程式代碼示範了這一過程
AREA InChannel, CODE, READONLY
ENTRY
MOV r1,#3 ; Number of words to read
LDR r2, =indata ; Address to store data read
pollin
MRC p14,0,r0,c0,c0 ; Read control register
TST r0, #1
BEQ pollin ; If R bit clear then loop
read
MRC p14,0,r3,c1,c0 ; read word into r3
STR r3,[r2],#4 ; Store to memory and
; update pointer
SUBS r1,r1,#1 ; Update counter
BNE pollin ; Loop if more words to read
MOV r0, #0x18 ; Angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC 0x123456 ; ARM semihosting (formerly SWI)
AREA Storage, DATA, READWRITE
indata
DCB "Duffmessage#"
END
CP15系統控制協處理器
CP15 —系統控制協處理器 (the system control coprocessor)他通過協處理器指令MCR和MRC提供具體的寄存器來配置和控制caches、MMU、保護系統、配置時鐘模式(在bootloader時鐘初始化用到)
CP15的寄存器隻能被MRC和MCR(Move to Coprocessor from ARM Register )指令通路
MCR{cond} p15,<Opcode_1>,<Rd>,<CRn>,<CRm>,<Opcode_2>
MRC{cond} p15,<Opcode_1>,<Rd>,<CRn>,<CRm>,<Opcode_2>
其中L位用來區分MCR(L=1)和MRC(L=0)操作. CP15包括15個具體的寄存器如下:
-R0:ID号寄存器
-R0:緩存類型寄存器
-R1:控制寄存器
-R2:轉換表基址寄存器(Translation Table Base --TTB)
-R3:域通路控制寄存器(Domain access control )
-R4:保留
-R5:異常狀态寄存器(fault status -FSR)
-R6:異常位址寄存器(fault address -FAR)
-R7:緩存操作寄存器
-R8:TLB操作寄存器
-R9:緩存鎖定寄存器
-R10:TLB 鎖定寄存器
-R11-12&14:保留
-R13:處理器ID
-R15:測試配置寄存器 2-24
要注意有2個R0,根據MCR操作數的不同傳送不同的值,這也一個隻讀寄存器
-R0:ID号寄存器 這是一個隻讀寄存器,傳回一個32位的裝置ID号,具體功能參考ARM各個系列型号的的CP15 Register 0說明.
MRC p15, 0, <Rd>, c0, c0, {0, 3-7} ;returns ID
以下為ID Code詳細描叙(ARM926EJ-S); ARM920T Part Number為0x920,Architecture (ARMv4T) 為0x2具體可參照ARM各型号.
-R0:緩存類型寄存器(CACHE TYPE REGISTER),包含了caches的資訊。讀這個寄存器的方式是通過設定協處理操作碼為1.
MRC p15, 0, <Rd>, c0, c0, 1; returns cache details
以下為CP15的一些應用示例
U32 ARM_CP15_DeviceIDRead(void)
{
U32 id;
__asm { MRC P15, 0, id, c0, c0; }
return id;
}
void ARM_CP15_SetPageTableBase(P_U32 TableAddress)
{
__asm { MCR P15, 0, TableAddress, c2, c0, 0; }
}
void ARM_CP15_SetDomainAccessControl(U32 flags)
{
__asm { MCR P15, 0, flags, c3, c0, 0; }
}
void ARM_CP15_ICacheFlush()
{
unsigned long dummy;
__asm { MCR p15, 0, dummy, c7, c5, 0; }
}
void ARM_CP15_DCacheFlush()
{
unsigned long dummy;
__asm { MCR p15, 0, dummy, c7, c6, 0; }
}
void ARM_CP15_CacheFlush()
{
unsigned long dummy;
__asm { MCR p15, 0, dummy, c7, c7, 0; }
}
void ARM_CP15_TLBFlush(void)
{
unsigned long dummy;
__asm { MCR P15, 0, dummy, c8, c7, 0; }
}
void ARM_CP15_ControlRegisterWrite(U32 flags)
{
__asm { MCR P15, 0, flags, c1, c0; }
}
void ARM_CP15_ControlRegisterOR(U32 flag)
{
__asm {
mrc p15,0,r0,c1,c0,0
mov r2,flag
orr r0,r2,r0
mcr p15,0,r0,c1,c0,0
}
}
void ARM_CP15_ControlRegisterAND(U32 flag)
{
__asm {
mrc p15,0,r0,c1,c0,0
mov r2,flag
and r0,r2,r0
mcr p15,0,r0,c1,c0,0
}
}
void ARM_MMU_Init(P_U32 TableAddress)
{
ARM_CP15_TLBFlush();
ARM_CP15_CacheFlush();
ARM_CP15_SetDomainAccessControl(0xFFFFFFFF);
ARM_CP15_SetPageTableBase(TableAddress);
}
void Enable_MMU (void)
{
__asm {
mrc p15,0,r0,c1,c0,0
mov r2, #0x00000001
orr r0,r2,r0
mcr p15,0,r0,c1,c0,0
}
printf("MMU enabled/n");
}
void Disable_MMU (void)
{
__asm {
mrc p15,0,r0,c1,c0,0
mov r2, #0xFFFFFFFE
and r0,r2,r0
mcr p15,0,r0,c1,c0,0
}
printf("MMU disabled/n");
}