在ARMv4架构中,内存管理单元(MMU)是连接处理器核心与物理内存的关键组件。它的核心功能是将程序使用的虚拟地址(VA)转换为物理地址(PA),同时实施内存保护策略。ARM720T采用的MMU设计具有以下典型特征:
关键提示:ARMv4的MMU设计特别考虑了嵌入式系统的需求,通过域控制机制减少了上下文切换时的TLB刷新操作,这对实时系统性能至关重要。
当TLB未命中时,MMU会启动完整的页表遍历过程:
一级描述符获取:
b00表示无效,b01表示页表描述符,b10表示段描述符二级描述符处理(当一级描述符为页表类型时):
b00(无效页)物理地址生成:
对于大页(64KB)和小页(4KB),ARM设计了独特的子页权限机制:
c复制// 小页的子页划分(每1KB一个权限区域)
#define SUBPAGE_PERM_4KB(ap) { ap3, ap2, ap1, ap0 } // apX对应AP[3:0]的各个位域
// 大页的子页划分(每16KB一个权限区域)
#define SUBPAGE_PERM_64KB(ap) { ap3, ap2, ap1, ap0 } // 每个apX控制16KB区域
当子页权限不一致时,只有被访问的子页条目会写入TLB。例如访问16KB大页的第二个子页时:
操作注意:使用子页权限时,执行TLB失效操作必须对所有四个子页分别执行无效化指令,否则可能导致权限控制失效。
ARM的16个域每个都有2位的状态控制:
| 编码 | 模式 | 访问检查规则 |
|---|---|---|
| 00 | 无访问 | 任何访问都会触发域错误(domain fault) |
| 01 | 客户端 | 需检查页表描述符中的访问权限位(AP) |
| 10 | 保留 | 当前行为与无访问模式相同 |
| 11 | 管理器 | 绕过权限检查,即使AP位禁止访问也允许操作 |
域配置寄存器格式如下:
code复制31 28 27 24 ... 7 4 3 0
| Domain 15 | Domain 14 | ... | Domain 1 | Domain 0 |
访问权限位与系统控制寄存器中的S、R位共同决定最终权限:
| AP | S | R | 特权模式权限 | 用户模式权限 | 典型应用场景 |
|---|---|---|---|---|---|
| 00 | 0 | 0 | 无访问 | 无访问 | 保护内核数据结构 |
| 00 | 1 | 0 | 只读 | 无访问 | 用户只读共享库 |
| 00 | 0 | 1 | 只读 | 只读 | 只读内存映射区域 |
| 01 | x | x | 读/写 | 无访问 | 内核堆栈空间 |
| 10 | x | x | 读/写 | 只读 | 进程间共享内存(写时复制) |
| 11 | x | x | 读/写 | 读/写 | 用户堆空间 |
特别警示:当[S:R]=b11时,任何AP值都会触发权限错误,这是硬件保留的非法配置。
MMU按固定顺序检查各种故障条件,优先级如下表所示:
| 优先级 | 故障类型 | 状态编码 | 触发条件 |
|---|---|---|---|
| 最高 | 对齐错误 | b0001 | 数据访问地址未按访问宽度对齐(A=1时) |
| 段转换错误 | b0101 | 一级描述符标记为无效(b00) | |
| 页转换错误 | b0111 | 二级描述符标记为无效(b00) | |
| 段域错误 | b1001 | 域配置为无访问(b00)或保留(b10) | |
| 页域错误 | b1011 | 同上 | |
| 段权限错误 | b1101 | 客户端模式下AP位检查失败 | |
| 最低 | 页权限错误 | b1111 | 同上 |
故障发生时,MMU会:
除MMU生成的故障外,系统还可能产生外部中止:
可中止的访问类型:
特殊情形处理:
assembly复制SWP R1, R2, [R3] ; 如果读取阶段发生中止,写入阶段会被自动取消
assembly复制; 步骤1:配置TTB寄存器
MRC p15, 0, r0, c2, c0, 0 ; 读取当前TTB
ORR r0, r0, #0x8000 ; 设置新的页表基址
MCR p15, 0, r0, c2, c0, 0 ; 写入TTB
; 步骤2:配置域控制寄存器
MOV r0, #0xFFFF ; 设置所有域为客户端模式
MCR p15, 0, r0, c3, c0, 0
; 步骤3:启用MMU
MRC p15, 0, r0, c1, c0, 0 ; 读取控制寄存器
ORR r0, r0, #0x1 ; 设置M位(bit0)
MCR p15, 0, r0, c1, c0, 0 ; 写入控制寄存器
重要细节:
assembly复制; 必须按顺序操作:
1. 禁用数据缓存
2. 等待所有缓存操作完成
3. 禁用MMU
4. 执行分支指令
; 典型代码序列:
MRC p15, 0, r0, c1, c0, 0
BIC r0, r0, #(1<<2) ; 清除C位(数据缓存)
MCR p15, 0, r0, c1, c0, 0 ; 写入控制寄存器
... ; 等待缓存排空
MRC p15, 0, r0, c1, c0, 0
BIC r0, r0, #0x1 ; 清除M位(MMU)
MCR p15, 0, r0, c1, c0, 0 ; 写入控制寄存器
MOV pc, #new_location ; 强制刷新流水线
当发生数据中止时,可通过以下方式获取调试信息:
c复制struct fault_info {
uint32_t far; // 故障地址寄存器
uint32_t fsr; // 故障状态寄存器
uint32_t domain:4; // 域编号
uint32_t status:4; // 状态编码
};
void data_abort_handler(void) {
struct fault_info fi;
__asm__ __volatile__ (
"MRC p15, 0, %0, c6, c0, 0\n" // 读取FAR
"MRC p15, 0, %1, c5, c0, 0\n" // 读取FSR
: "=r"(fi.far), "=r"(fi.fsr)
);
fi.domain = (fi.fsr >> 4) & 0xF;
fi.status = fi.fsr & 0xF;
// 根据状态码分析故障类型
switch(fi.status) {
case 0x1: /* 对齐错误 */ break;
case 0x5: /* 段转换错误 */ break;
// 其他状态码处理...
}
}
无效化整个TLB:
assembly复制MOV r0, #0
MCR p15, 0, r0, c8, c7, 0 ; 使令所有TLB条目失效
无效化单个VA:
assembly复制MCR p15, 0, r0, c8, c5, 1 ; 使令指令TLB中VA对应的条目失效
MCR p15, 0, r0, c8, c6, 1 ; 使令数据TLB中VA对应的条目失效
锁定关键条目:
assembly复制; 先查询TLB条目
; 然后通过CP15 c10寄存器锁定特定条目
性能建议:在实时性要求高的场景中,可将关键内存区域的映射锁定在TLB中,避免换出导致的性能波动。
域配置与AP位冲突:
TLB一致性维护不足:
内存属性配置不当:
必须严格遵循以下启用顺序:
错误顺序可能导致:
页表描述符中的C、B位控制缓存行为:
| C | B | 模式 | 典型应用 |
|---|---|---|---|
| 0 | 0 | 非缓存非缓冲 | 设备寄存器访问 |
| 0 | 1 | 非缓存缓冲 | 帧缓冲区写入 |
| 1 | 0 | 写通缓存 | 只读或频繁读数据 |
| 1 | 1 | 写回缓存 | 普通可写内存区域 |
调试技巧:在早期启动阶段,建议先将所有内存区域配置为不可缓存,待MMU完全初始化后再调整缓存策略。
通过深入理解ARM MMU的这些工作机制,开发人员可以更有效地设计内存管理策略,优化系统性能,并快速定位与内存相关的异常问题。在实际项目中,建议结合具体芯片手册完善上述通用知识,因为不同ARM处理器可能在细节实现上存在差异。