再上一篇:第14章
上一篇:14.0 译者添加的引子
主页
下一篇:14.3 启用MPU
再下一篇:14.4 MPU 的典型设置
文章列表

14.2 MPU 的寄存器组

《Cortex-M3 权威指南》,嵌入式处理器开发教程。

操作MPU是通过访问它的若干寄存器来实现的,如下表所示。
(译者注:此表摘自Cortex-M3 TRM)

名字

访问

地址

初值

MPU类型寄存器 MPUTR

RO

0xe000,ed90

A

MPU控制寄存器 MPUCR

RW

0xe000,ed94

0x0000,0000

MPU region号寄存器MPURNR

RW

0xe000,ed98

-

MPU region基址寄存器MPURBAR

RW

0xe000,ed9c

-

MPU region属性及容量寄存器(s) MPURASR

RW

0xed00,eda0

-

MPU region基址寄存器的别名1

D9C的别名

0xed00,eda4

-

MPU region属性及容量寄存器的别名1

DA0的别名

0xed00,eda8

-

MPU region基址寄存器的别名2

D9C的别名

0xed00,edac

-

MPU region属性及容量寄存器的别名2

DA0的别名

0xed00,edb0

-

MPU region基址寄存器的别名3

D9C的别名

0xed00,edb4

-

MPU region属性及容量寄存器的别名3

DA0的别名

0xed00,edb8

-

让我们来详细地介绍上述寄存器,第一个就是MPU类型寄存器(MPUTR),如表14.1所示
表 14.1 MPU 类型寄存器MPUTR (地址:0xE000_ED90)

位段

名称

类型

复位值

描述

23:16

IREGION

R

0

MPU支持的指令 region数量。因为 ARMv7-M

只使用单个统一的 MPU,此位段永远为零

15:8

DREGION

R

0

MPU 支持的数量。若系统中配了 MPU 则为 8,

否则为零

0

SEPARATE

R

0

固定为零

从表中我们可以看出,通过读取DREGION的值,能够判断芯片中是否配了MPU。
接下来我们看一看MPU控制寄存器MPUCR如表14.2所示
表 14.2 MPU 控制寄存器MPUCR (地址:0xE000_ED94)

位段

名称

类型

复位值

描述

2

PRIVDEFENA

RW

0

是否为特权级打开缺省存储器映射(即背景

region)。

1=特权级下打开背景 region

0=不打开背景 region。任何访问违例以及对

region外地址区的访问都将引起 fault

1

HFNMIENA

RW

0

1=在NMI和硬fault服务例程中不强制除能MPU

0=在 NMI和硬 fault服务例程中强制除能 MPU

0

ENABLE

RW

0

使能 MPU

通过把PRIVDEFENA置位,可以在没有建立任何region就使能MPU的情况下,依然允许特权级程
序访问所有地址,而只有用户级程序被拒之门外。然而,如果设置了其它的region并且使能了MPU, 则背景region与这些region重合的部分,就要受各region的限制。为了方便理解,让我们作一个对比, 看看PRIVDEFENA在置位与清零时,系统对访问的限制有何不同,如图14.1所示。

图14.1 PRIVDEFENA的影响 要注意,只要没有极另类的考虑,就要到万事就绪后,最后一步才置位ENABLE位。否则,就有
可能因region没有配置好而意外地产生MemManage fault。很多条件下,为安全起见,最好在执行配 置MPU的子程前先除能MPU,待执行后再重新使能MPU。 注意:这里有个例外:不管MPU如何限制,响应异常时的取向量操作,以及对系统分区(system partition)的访问总是不受影响的。

译注:这里所说的“系统分区”,作者并没有解释过。估计有可能是包含在前面提到的“SCS”区

When the MPU is enabled, only the system partition and vector table loads are always accessible.

配置任何一个region之前,都需要在MPU内选中这个region,这可以通过把region号写入MPU

region号寄存器(MPURNR)来完成,其定义如表14.3所示

表 14.3 MPU region 号寄存器 MPURNR (地址:0xE000_ED98)


选好了region后,就可以在另外两个寄存器中配置该region的所有属性了。 为了能快速地配置多个regions,还有另一种快捷方式。在MPU region基地址寄存器(MPURBAR)
中有两个位段:VALID和REGION,它们配合使用可以绕过MPURNR。MPURBAR的定义如表14.4所示
表 14.4 MPU region 基址寄存器 MPURBAR (地址:0xE000_ED9C)

位段

名称

类型

复位值

描述

31:N

ADDR

RW

-

Region 基址字段。N 取决于region 容量,以使基址在数值

上能被容量整除。在 MPU region 属性及容量寄存器中有 个SZENABLE 位段,它决定ADDR 中有多少个位被采用。

4

VALID

RW

-

决定是否理会写入REGION字段的值

1=MPU region号寄存器被REGION覆盖

0=MPU region号寄存器的值保持不变

3:0

REGION

RW

-

MPU region 覆写位段

从表中我们可以看出,基址必须对齐到region容量的边界。举例来说,如果你定义的region容量
是64KB,那么它的基址就必须能被64KB整除。这里,像0x0001,0000;0x0002,0000这样的,就是合 法的基址(低16位为0)。
如果读取REGION位段,返回的总是当前的region号,并且VALID总返回0。通过设置VALID=1和 REGION=n,也可以改变一个region的编号。相比于先设置MPU region号寄存器再设置本寄存器的正 统做法而言,这是一个快捷方式。
注意:必须以字的方式来访问本寄存器,否则结果不可预知。
配置好了基地址,我们还需要详细定义region的其它方方面面。这需要设置MPU属性及容量寄 存器。这个寄存器是全体可读可写的,且复位值未知,如下表14.5所示:


表14.5 MPU region属性及容量寄存器MPURASR(地址:0xE000_EDA0)

位段

名称

功能

31:29

3

-

保留

28

1

XN

1=此区禁止取指

2=此区允许取指

27

1

-

保留

26:24

3

AP

访问许可,如下表所示

26:24

3

AP

特权级下的许可

用户级下的许可

典型用法

26:24

3

AP

0b000

禁地

禁地

该区没有存储器,是空地址

26:24

3

AP

0b001

RW

禁地

OS以及系统软件使用的数据区

26:24

3

AP

0b010

RW

RO

禁止在用户级下更改的高危地带

26:24

3

AP

0b011

RW

RW

共享内存,或彻底开放的设备

26:24

3

AP

0b100

n/a

n/a

n/a

26:24

3

AP

0b101

RO

禁地

OS使用的常量数据

26:24

3

AP

0b110

RO

RO

常量数据或只读存储器的地址区

26:24

3

AP

0b111

RO

RO

常量数据或只读存储器的地址区

23:22

2

保留

21:19

3

TEX

类型扩展

18

1

S

Sharable(可否共享)

1=共享可

0=共享不可

17

1

C

Cachable(可否缓存)

1=缓存可

0=缓存不可

16

1

B

Buffable(可否缓冲)

1=缓冲可

0=缓冲不可

15:8

8

SRD

子region除能位段。每设置SRD的一个位,就会除能与之对应的一个子region。

容量大于128字节的region都被划分成8个容量相同的子region。容量小于等于

128字节的region不能再分。更多信息,请参见对子Region的论述。

7:6

2

-

保留

5:1

5

REGIONSIZE

Region容量,单位是字节。容量为1<<(REGIONSIZE+1),但是最小容量为32字节

0

1

SZENABLE

1=使能此region 0=除能此region

表中提到了“子region”的概念([15:8])。原来,8个region的定义过于粗枝大叶,因而允许再
精雕细琢,把每个region的内部进一步划分成更小的块,这就是子region。但是子region的使用有限 制:每个region必须8等分,每份是一个子region,而且所有子region的属性都与“父region”的是相 同的。每个子region可以独立地使能或除能(相当于可以部分地使能一个region):SRD中的8个位, 每个位控制一个子region是否被除能。如SRD.3=0,则3号子region被除能。如果某个子region被除能, 且其对应的地址范围又没有落在其它region中,则对该子region覆盖范围的访问将引发fault。最后, 能被“大卸八块”的region,最小也要有256字节。如果是对128字节或者是更小的region划分子region, 则后果是不可预料的。
再看它的AP位段,为了详细说明把它做成了一个表中表。AP位段用于限定各种访问权限,这也 是加以分区保护的最重要组成部分。
位段[28]的名字是XN(eXecute Never),它决定在本region中是否允许取指。如果不允许取指(清 零),则任何指令预取都将触发MemManage fault。这有什么用?通常,可以把新得到的还不受信 任的代码先存储到此区,待经过身份鉴定后,再允许它执行。
表中楷体的TEX, S, B和C(整体位于[21:16]),对应着存储系统中比较高级的概念。CM3中没有 缓存(cache),但是CM3是以v7-M的架构设计的,而v7-M支持外部缓存(差不多是L2缓存的地位)以 及更先进的存储器系统。按v7-M的规格说明,可以通过对这些位段的编程,来支持多样的内存管理 模型。从v6开始,ARM架构支持两级缓存(与x86的缓存系统是异曲同工的),分别是:内部缓存和 外部缓存,它们可以有不同的缓存方针(policy),这些位组合的详细功能如下表所示:
表14.6 TEX,C,B对存储器类型的决定

TEX

C

B

描述

存储器类型

可否共享

000

0

0

严格按顺序

严格按顺序

总是可以

000

0

1

共享的设备

设备

总是可以

000

1

0

片外或片内的“写通”型内存,没有写allocate

普通

S位决定

000

1

1

片外或片内的“写回”型内存,没有写allocate

普通

S位决定

001

0

0

片外或片内的“缓存不可”型内存

普通

S位决定

001

0

1

n/a

n/a

n/a

001

1

0

实现者您说了算

您说了算

您说了算

001

1

1

片外或片内的“写回”型,带读和写的allocate

普通

S位决定

010

1

x

共享不可的设备

设备

总是不可

010

0

1

n/a

n/a

n/a

010

1

x

n/a

n/a

n/a

1BB

A A

带缓存的内存。BB=适用于片外内存, AA=适用于片

内内存

普通

S位决定

表中最后一项越发离奇,它是TEX的MSB=1时的情况。此时,如果该region是片内存储器,则由C和B
决定其缓存属性(AA);如果是片外存储器,则由TEX的[1:0]决定其缓存属性(BB)。不管是AA还 是BB,每个数值的含义都是相同的,如下表所示:
表14.7 缓存方针编码

存储器属性编码 (AA and BB)

高速缓存策略

00

缓存不可

01

写回,读写均有allocate

10

写通,写没有allocate

11

写回,写没有allocate

欲知缓存行为和缓存方针的更多详情,请参阅《ARM Architecture Application Level Reference

Manual(Ref2)》。 再看本章开头的寄存器表,最后的8个其实是4对,且后3对都第1对的别名,这可真是“狡兔三

窟”啊。再仔细看,你会发现它们的地址是连续的。这下是不是有看出一些端倪了?请看下段译自

Cortex-M3 TRM的解释:

9.2.3 使用别名(alias)寄存器访问MPU

通过寄存器别名机制,你可以使用STM指令加速对regions的初始化——一次可以最多初 始化4个。一共有3组别名寄存器。别名以完全相同的方式来访问(真实的)寄存器,它们的 存在是为了让你能以“顺序写”(STM指令)来一次更新1-4个region。当无需在某些“临界” 区域中以“除能region/更改region属性/使能retgion”的小心方式,来一个个地进行配置时, 这个机制就显得特别有用。

下面举一个一次更改4个region的代码例子:

; R1 = 一个指针,指向某RTOS进程控制块中的4个region对子(共8个字)

MOV R0, #NVIC_BASE

ADD R0, #MPU_REG_CTRL

LDM R1, [R2-R9] ; 加载4个region的信息

STM R0, [R2-R9] ; 一句话完成4个region的配置

这么一来,只要事先做好一个配置表格,就可以一气呵成了。

注意

你不能使用这些别名来读取regions的内容,因为必须要先写region号。 在C/C++下通常使用memcpy()函数来完成上段汇编的功能。但是,你必须验证CRT库,在

实现memcpy()时必须是按字拷贝的——也就是两个long* 指针之间的拷贝,而不得是char*, short*什么的。

本章后面还有一个“一题多解”的例子,最后的解法就是使用这里讲到的思路