arm v8r中MCR指令的详细用法
在ARMv8-R架构中,MCR指令(Move to Coprocessor from Register) 是用于ARM核心寄存器与协处理器寄存器间数据传输的关键指令。作为AArch32执行状态下的遗留协处理器接口,它在系统控制、调试和硬件配置中扮演重要角色。以下是深度解析:
一、MCR指令核心机制
1. 基本格式
MCR{<cond>} <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}
<cond>:条件码(可选),如EQ/NE(条件执行)<coproc>:协处理器编号(0-15),常用值:p15:系统控制协处理器(最重要)p14:调试协处理器p10:VFP/NEON协处理器
<opc1>:主操作码(0-7),指定操作类型<Rt>:源ARM核心寄存器(如R0-R12)<CRn>:目标协处理器主寄存器(c0-c15)<CRm>:目标协处理器附加寄存器(c0-c15)<opc2>:次操作码(0-7),进一步指定操作
📌 关键点:协处理器寄存器由
<CRn>+<CRm>+<opc1>+<opc2>共同寻址
2. 数据流向
[ARM Core Register <Rt>] → [Coprocessor Register <CRn>:<CRm>]
- 将ARM核心寄存器值写入协处理器寄存器
- 逆向操作为 MRC(Move to Register from Coprocessor)
二、核心应用场景(以p15协处理器为例)
1. 内存系统配置
; 设置TTBR0 (Translation Table Base Register 0)
MCR p15, 0, R0, c2, c0, 0 ; R0 = 页表基地址
; 配置DACR (Domain Access Control Register)
MCR p15, 0, R1, c3, c0, 0 ; R1 = 域权限位图
2. 缓存与TLB维护
; 使无效整个指令缓存
MOV R0, #0
MCR p15, 0, R0, c7, c5, 0 ; ICIALLU (Invalidate I-Cache)
; 使无效TLB单条目
MCR p15, 0, R2, c8, c7, 1 ; R2 = 虚拟地址 (Invalidate TLB by VA)
3. 系统控制寄存器(SCTLR)
; 禁用MMU
MRC p15, 0, R0, c1, c0, 0 ; 先读取SCTLR
BIC R0, R0, #0x1 ; 清除bit0 (M位)
MCR p15, 0, R0, c1, c0, 0 ; 写回SCTLR
DSB ; 数据同步屏障
ISB ; 指令同步屏障
4. 中断配置
; 设置VBAR (Vector Base Address Register)
MCR p15, 0, R3, c12, c0, 0 ; R3 = 异常向量表基址
三、关键参数组合速查表(p15协处理器)
| 功能 | <opc1> |
<CRn> |
<CRm> |
<opc2> |
寄存器 |
|---|---|---|---|---|---|
| SCTLR | 0 | c1 | c0 | 0 | 系统控制寄存器 |
| TTBR0 | 0 | c2 | c0 | 0 | 页表基址寄存器0 |
| DACR | 0 | c3 | c0 | 0 | 域访问控制 |
| VBAR | 0 | c12 | c0 | 0 | 向量基址寄存器 |
| ICIALLU (I-Cache) | 0 | c7 | c5 | 0 | 无效整个I-Cache |
| TLBIALL (TLB) | 0 | c8 | c7 | 0 | 无效整个TLB |
四、使用约束与注意事项
-
特权级要求:
- MCR/MRC只能在 特权模式(PL1或更高)执行
- 用户模式调用会触发 Undefined Instruction异常
-
内存屏障依赖:
; 修改关键寄存器后必须加屏障 MCR p15, 0, R0, c2, c0, 0 ; 设置TTBR0 DSB ; 保证写入完成 ISB ; 清空流水线 -
与MRC的配对使用:
; 安全修改寄存器流程 MRC p15, 0, R1, c1, c0, 0 ; 读取SCTLR ORR R1, R1, #(1 << 12) ; 设置I-Cache使能位 MCR p15, 0, R1, c1, c0, 0 ; 写回SCTLR -
协处理器差异:
- p15寄存器布局由 ARM架构定义
- 其他协处理器(如p14调试)由芯片厂商自定义,需查阅手册
五、ARMv8-R vs ARMv7的MCR变化
| 特性 | ARMv7 | ARMv8-R |
|---|---|---|
| 执行状态 | 仅AArch32 | 仅AArch32 |
| 系统寄存器访问 | 主要依赖MCR/MRC | 增加部分MSR/MRS系统寄存器 |
| 安全扩展 | 支持TrustZone (SCR寄存器) | 支持TrustZone for Armv8-R |
| PMSAv8内存模型 | 支持PMSAv7 | 升级支持PMSAv8-64 |
六、完整示例:启用MPU
; 1. 设置MPU区域基址和属性
LDR R0, =0x20000000 ; 区域基地址
ORR R0, R0, #0x1B ; 属性: XN=0, AP=Full, TEX=0, S=1, C=1, B=1
MCR p15, 0, R0, c6, c1, 0 ; 写入MPU_RBAR (Region Base Address Register)
LDR R1, =0x1FF0002D ; 大小=1MB, 启用区域
MCR p15, 0, R1, c6, c1, 2 ; 写入MPU_RASR (Region Attribute/Size Register)
; 2. 启用MPU
MRC p15, 0, R2, c1, c0, 0 ; 读取SCTLR
ORR R2, R2, #0x1 ; 设置MPU使能位 (bit0)
MCR p15, 0, R2, c1, c0, 0 ; 写回SCTLR
; 3. 屏障指令
DSB ; 确保配置生效
ISB ; 清空流水线
七、调试与问题排查
-
未定义指令异常:
- 检查当前模式(需特权模式)
- 确认协处理器是否存在(如p15必须实现)
-
配置未生效:
- 遗漏DSB/ISB屏障
- 寄存器位域配置错误(参考Technical Reference Manual)
-
工具链支持:
; GCC内联汇编示例 __asm__ volatile ( "MCR p15, 0, %0, c7, c5, 0 \n" : : "r" (0) : "memory" );
注意:在ARMv8-R中,虽然AArch64使用MSR/MRS,但AArch32仍依赖MCR/MRC进行底层硬件控制。开发者需结合《ARMv8-R Architecture Reference Manual》和具体芯片手册使用。
浙公网安备 33010602011771号