在 ARM 嵌入式應用系統中, 很多系統控制由 ARM CP15 協處理器來完成的。CP15 協處理器包含編號 0-15 的 16 個 32 位的寄存器。例如,ARM 處理器使用 C15 協處理器的寄存器來控制 cache、TCM(Tightly-Coupled Memory)和存儲器管理。CP15 的各個寄存器的概要信息如下圖,圖片來自官方資料《ARM? Cortex?-A Series Version: 4.0 Programmer’s Guide》。
在這些 C15 寄存器中和 MMU 關系較大的有 C2、C7、C17 寄存器,這些寄存器的作用,從上圖可以看出,分別是:
CP15 C2 寄存器
Memory protection and control registers,內存保護和控制寄存器,包含 Translation Table Base Register 0 (TTBR0)、Translation Table Base Register 1 (TTBR1) 和 Translation Table Base Control Register (TTBCR)。TTBR0、TTBR1 是 L1 轉換頁表的基地址,TTCR 控制 TTBR0 和 TTBR1 的使用。
CP15 C7 寄存器
Cache and branch predictor maintenance functions、Data and instruction barrier operations 用于高速緩存和寫緩存控制。
CP15 C13 寄存器
Context ID Register (CONTEXTIDR)、Software thread ID registers 用于保存進程標識符(asid 地址空間編號)。
2、ARM C15 協處理器匯編指令
訪問 CP15 寄存器的指令主要是 MCR 和 MRC 這兩個指令。本小節詳細介紹下這 2 個匯編指令。先看下指令的含義,MCR 是 ARM 處理器寄存器到協處理器寄存器的數據傳送指令,英文為 Move CPU register to coprocessor register,MRC 是協處理器寄存器到 ARM 處理器寄存器的數據傳送指令,英文為 Move from coprocessor register to CPU register。這 2 個指令的語義格式如下,可以看出語義格式是一樣的,但是讀取寫入含義會有差異。MCR 是讀取 Rt 寄存器寫入協處理器寄存器 CRn、CRm,而 MRC 是讀取協處理器寄存器 CRn、CRm 寫入 Rt 寄存器。
MCR{cond} coproc, #opcode1, Rt, CRn, CRm{, #opcode2} MRC{cond} coproc, #opcode1, Rt, CRn, CRm{, #opcode2}
MCR 詳細的語義介紹如下:
Syntax MCR{cond} coproc, #opcode1, Rt, CRn, CRm{, #opcode2} where: cond is an optional condition code. 可選的條件碼。 coproc is the name of the coprocessor the instruction is for. The standard name is pn, where n is an integer in the range 0 to 15.協處理器的名稱,標準名稱為pn,其中n為0-15,例如p14、p15。 opcode1 is a 3-bit coprocessor-specific opcode. 3位的操作碼。 opcode2 is an optional 3-bit coprocessor-specific opcode.可選的3位操作碼。 Rt is an ARM source register. Rt must not be PC. 要讀取的ARM寄存器,不能為PC寄存器。 CRn, CRm are coprocessor registers.要寫入的協處理器寄存器。
MRC 詳細的語義介紹如下:
Syntax MRC{cond} coproc, #opcode1, Rt, CRn, CRm{, #opcode2} where: cond is an optional condition code. 可選的條件碼。 coproc is the name of the coprocessor the instruction is for. The standard name is pn, where n is an integer in the range 0 to 15.協處理器的名稱,標準名稱為pn,其中n為0-15,例如p14、p15。 opcode1 is a 3-bit coprocessor-specific opcode.3位的操作碼。 opcode2 is an optional 3-bit coprocessor-specific opcode.可選的3位操作碼 Rt is the ARM destination register. Rt must not be PC.要寫入的ARM寄存器,不能為PC寄存器。 Rt can be APSR_nzcv. This means that the coprocessor executes an instruction that changes the value of the condition flags in the APSR. Rt也可以為APSR_nzcv。 CRn, CRm are coprocessor registers.要讀取的協處理器寄存器。
3、MMU 匯編代碼
在 archarmarmincludearm.h 文件中,封裝了 CP15 協處理器相關的寄存器操作匯編函數。我們主要看下 MMU 相關的部分。
3.1 CP15 C2 TTBR 轉換表基地址寄存器
代碼比較簡單,結合下圖,自行查看即可。該圖來自《ARM Cortex-A9 Technical Reference Manual r4p1》CP15 system control registers grouped by CRn order 部分。
STATIC INLINE UINT32 OsArmReadTtbr(VOID) { UINT32 val; __asm__ volatile("mrc p15, 0, %0, c2,c0,0" : "=r"(val)); return val; } STATIC INLINE VOID OsArmWriteTtbr(UINT32 val) { __asm__ volatile("mcr p15, 0, %0, c2,c0,0" ::"r"(val)); __asm__ volatile("isb" ::: "memory"); } STATIC INLINE UINT32 OsArmReadTtbr0(VOID) { UINT32 val; __asm__ volatile("mrc p15, 0, %0, c2,c0,0" : "=r"(val)); return val; } STATIC INLINE VOID OsArmWriteTtbr0(UINT32 val) { __asm__ volatile("mcr p15, 0, %0, c2,c0,0" ::"r"(val)); __asm__ volatile("isb" ::: "memory"); } STATIC INLINE UINT32 OsArmReadTtbr1(VOID) { UINT32 val; __asm__ volatile("mrc p15, 0, %0, c2,c0,1" : "=r"(val)); return val; } STATIC INLINE VOID OsArmWriteTtbr1(UINT32 val) { __asm__ volatile("mcr p15, 0, %0, c2,c0,1" ::"r"(val)); __asm__ volatile("isb" ::: "memory"); } STATIC INLINE UINT32 OsArmReadTtbcr(VOID) { UINT32 val; __asm__ volatile("mrc p15, 0, %0, c2,c0,2" : "=r"(val)); return val; } STATIC INLINE VOID OsArmWriteTtbcr(UINT32 val) { __asm__ volatile("mcr p15, 0, %0, c2,c0,2" ::"r"(val)); __asm__ volatile("isb" ::: "memory"); }
3.2 CP15 C7 高速緩存寄存器
代碼比較簡單,結合下圖,自行查看即可。該圖是 C7 寄存器的部分截圖。
STATIC INLINE UINT32 OsArmReadBpiall(VOID) { UINT32 val; __asm__ volatile("mrc p15, 0, %0, c7,c5,6" : "=r"(val)); return val; } STATIC INLINE VOID OsArmWriteBpiall(UINT32 val) { __asm__ volatile("mcr p15, 0, %0, c7,c5,6" ::"r"(val)); __asm__ volatile("isb" ::: "memory"); } STATIC INLINE UINT32 OsArmReadBpiallis(VOID) { UINT32 val; __asm__ volatile("mrc p15, 0, %0, c7,c1,6" : "=r"(val)); return val; } STATIC INLINE VOID OsArmWriteBpiallis(UINT32 val) { __asm__ volatile("mcr p15, 0, %0, c7,c1,6" ::"r"(val)); __asm__ volatile("isb" ::: "memory"); }
3.3 CP15 C13 進程標識符寄存器
代碼比較簡單,結合下圖,自行查看即可。
STATIC INLINE UINT32 OsArmReadContextidr(VOID) { UINT32 val; __asm__ volatile("mrc p15, 0, %0, c13,c0,1" : "=r"(val)); return val; } STATIC INLINE VOID OsArmWriteContextidr(UINT32 val) { __asm__ volatile("mcr p15, 0, %0, c13,c0,1" ::"r"(val)); __asm__ volatile("isb" ::: "memory"); }
4 MMU 上下文切換
在之前的系列,我們了解到每個用戶進程都有獨立的進程空間。在進程切換時,MMU 上下文也會切換,相應的函數為 LOS_ArchMmuContextSwitch ()。快速分析下該函數的代碼。
⑴處讀取 TTBCR 寄存器的狀態值,如果傳入參數 archMmu 不為空,執行⑵使能 TTBR0,否則執行⑶使其失能 TTBR0。⑷處把內核地址空間的進程空間標識符 asid 寫入 C13 寄存器。⑸處更新 TTB 頁表基地址和 TTB 狀態信息到相應寄存器。⑹處把進程空間的進程標識符寫入 C13 寄存器。
VOID LOS_ArchMmuContextSwitch(LosArchMmu *archMmu) { UINT32 ttbr; ⑴ UINT32 ttbcr = OsArmReadTtbcr(); if (archMmu) { ⑵ ttbr = MMU_TTBRx_FLAGS | (archMmu->physTtb); /* enable TTBR0 */ ttbcr &= ~MMU_DESCRIPTOR_TTBCR_PD0; } else { ⑶ ttbr = 0; /* disable TTBR0 */ ttbcr |= MMU_DESCRIPTOR_TTBCR_PD0; } #ifdef LOSCFG_KERNEL_VM /* from armv7a arm B3.10.4, we should do synchronization changes of ASID and TTBR. */ ⑷ OsArmWriteContextidr(LOS_GetKVmSpace()->archMmu.asid); ISB; #endif ⑸ OsArmWriteTtbr0(ttbr); ISB; OsArmWriteTtbcr(ttbcr); ISB; #ifdef LOSCFG_KERNEL_VM if (archMmu) { ⑹ OsArmWriteContextidr(archMmu->asid); ISB; } #endif }
審核編輯 黃宇
-
處理器
+關注
關注
68文章
19548瀏覽量
231872 -
ARM
+關注
關注
134文章
9217瀏覽量
371162 -
源碼
+關注
關注
8文章
657瀏覽量
29799 -
MMU
+關注
關注
0文章
92瀏覽量
18450 -
鴻蒙
+關注
關注
57文章
2411瀏覽量
43303
發布評論請先 登錄
相關推薦
設計了一個基于浮點數運算的協處理器,使用C語言編程時沒法輸入float型數據,請問有哪些部分需要修改?
低功耗處理器的優勢分析
EE-174:ADSP-TS101S TigerSHARC處理器引導加載程序內核操作

EE-345:SHARC處理器的啟動內核定制和固件可升級性

OpenHarmony源碼編譯后燒錄鏡像教程,RK3566鴻蒙開發板演示

全志T536系列處理器特性概述 集成RISC-V E907協處理器

使用TMS320C6416協處理器:Turbo協處理器(TCP)

使用TMS320C6416協處理器:Viterbi協處理器(VCP)

【開源鴻蒙】使用QEMU運行OpenHarmony輕量系統

評論