3. MPU核心寄存器详解:SPROT、DPROT、GPR、LPR寄存器组
好,咱们进入正题。MPU的配置,说白了就是跟这几个寄存器打交道。你想想看,CPU要访问内存,总得有个「交通规则」吧?SPROT、DPROT、GPR、LPR就是制定规则的那几张纸。我刚开始接触TC3xx时,对着寄存器手册看了三天,头都大了。后来发现,其实核心就四个寄存器组,搞懂了它们,MPU也就通了八成。
3.1 SPROT寄存器——代码区的「守门员」
SPROT,全称是代码段保护寄存器。它管的是指令读取,也就是CPU取指令时的访问权限。
我个人习惯,先把SPROT分成两部分看:
- SPROT_ACCENx:使能位。你得先告诉MPU,「嘿,我要对这段代码区做保护了」。否则配置了也白搭。
- SPROT_APx:权限位。读?执行?还是读写都行?这里定。
举个例子,假设你想保护0x80000000开始的64KB代码区,只允许CPU读和执行,不允许写。配置大概是这样的:
// 伪代码示意
SPROT_ACCEN0.B.ENABLE = 1; // 使能保护
SPROT_AP0.B.AP = 0b10; // 只读+执行,不可写
SPROT_ADDR0.B.ADDR = 0x8000; // 起始地址(高16位)
SPROT_MASK0.B.MASK = 0xFF; // 64KB范围
嗯,这里要注意:地址对齐要求很严格。起始地址必须是保护区域大小的整数倍。我在项目中遇到过有人把起始地址写成了0x80000100,结果MPU直接罢工,CPU跑飞了。排查了半天才发现是地址没对齐。
3.2 DPROT寄存器——数据区的「安检员」
DPROT跟SPROT长得几乎一模一样,但管的是数据访问。说白了,就是CPU读写数据时的权限控制。
你想想看,如果某个关键数据区(比如系统配置参数)被意外篡改,后果可能很严重。DPROT就是干这个的——谁可以读,谁可以写,全由它说了算。
DPROT的寄存器结构:
| 寄存器 | 功能 | 位宽 |
|---|---|---|
| DPROT_ACCENx | 使能控制 | 32位 |
| DPROT_APx | 访问权限(读/写/无) | 2位 |
| DPROT_ADDRx | 保护区域起始地址 | 16位(高地址位) |
| DPROT_MASKx | 区域大小掩码 | 16位 |
我建议你把DPROT和SPROT当成一对兄弟来记。一个管指令,一个管数据。配置方法几乎一样,只是应用场景不同。
3.3 GPR寄存器——全局的「总闸」
GPR,全局保护寄存器。它不直接定义某个区域的权限,而是控制MPU的全局行为。
GPR里最重要的几个位:
- PROTEN:MPU总使能。关了它,所有保护都失效。调试时常用。
- SPROTEN:代码保护使能。单独开关代码保护。
- DPROTEN:数据保护使能。单独开关数据保护。
- LOCK:锁定位。一旦置1,MPU配置就不能再改了。产品发布前记得锁上。
我记得有一次,客户反馈说设备在运行中突然失去保护。查了半天,发现是某个中断服务程序里不小心把GPR的PROTEN位清零了。从那以后,我写代码时都会在MPU初始化最后加上LOCK操作。
3.4 LPR寄存器——本地的「分闸」
LPR,本地保护寄存器。它跟GPR的区别在于:GPR是全局的,LPR是每个CPU核心独立的。
TC3xx是多核架构,每个核都有自己的LPR。这意味着你可以给Core0开一个权限,给Core1关掉。这在多核系统中非常实用。
LPR的核心字段:
- LPR_ACCENx:本地使能位
- LPR_APx:本地权限位
- LPR_ADDRx:本地地址范围
- LPR_MASKx:本地掩码
说白了,LPR就是每个核自己的「小MPU」。你可以用它来隔离不同核之间的数据访问。比如Core0的堆栈区,Core1不能碰。这在功能安全项目中是标配。
为什么会这样设计?你想想看,如果所有核共享一套保护规则,那一个核的配置错误就可能影响整个系统。LPR的存在,让每个核都能「自扫门前雪」。
- SPROT:管代码(指令读取)
- DPROT:管数据(读写访问)
- GPR:全局总开关,控制MPU整体行为
- LPR:每个核自己的本地保护,实现核间隔离
嗯,这四个寄存器组搞明白了,MPU的骨架就有了。下一节咱们会讲怎么用它们搭出实际的内存保护方案。到时候我会拿一个真实的汽车ECU项目做例子,手把手带你配一遍。