再上一篇:14.2 MPU 的寄存器组
上一篇:14.3 启用MPU
主页
下一篇:第15章
再下一篇:15.2 CoreSight 技术概览
文章列表

14.4 MPU 的典型设置

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

在典型的情况下,当需要阻止用户程序访问特权级的数据和代码时,可以启用MPU。在设计MPU

regions时,需要考虑到下列的regions:

1. 代码region

a) 特权极代码,包括初始的向量表

b) 用户级代码

2. SRAM region

a) 特权级数据,包括主堆栈

b) 用户级数据,包括进程堆栈

c) 特权级位带别名区

d) 用户级位带别名区

3. 外设

a) 特权级外设

b) 用户级外设

c) 特权级外设的位带别名区

d) 用户级外设的位带别名区

4. 系统控制空间(NVIC以及调试组件)

a) 仅允许特权级访问 看,上面列出了11个region,已经超出了MPU支持的最多8个,这可如何是好?不怕,还记得有

个“背景region”吗?(忘了的话快去看图14.1)。我们可以把所有的特权级regions都归入背景region 中(PRIVDEFENA=1)。这样一来,就只需要明确定义用户级的regions——才5个。剩下3个后备的“槽”, 可以用于在外部RAM中(如果有的话)设置额外的regions,也可以用于保护只读数据,还能用于“没 收”一部分的RAM等,总之这是大虾们绽放智慧光芒的地方。

14.4.1 使用子 region除能的示例

在上面的分析中,外设是对用户开放的。但是如果误用某个外设可能导致严重后果的话,我们 就需要禁止用户级程序随意访问它。这样一来,就会从外设存储器空间中割下几块肉,使一个完整 的空间变成若干个更小的。对付这种情况,有如下的办法:
 定义多个用户级外设regions
 在用户级外设region中重叠地定义一个特权级的region
 在用户级外设region中启用“子region除能机制”。 前两个办法很容易耗尽宝贵的8个“region槽”。芯片在设计时应为每个外设都开出相同容量的
外设空间(用不完的就空着),这样才能让开发者容易使用第3种方法,即除能子region。通过除能 子region,就很容易地从用户级region中擦掉一部分,让它回到背景region中了。一个例子如图14.3 所示

图14.3 “前景”的用户级region被SRD挖出子regions
该技巧也可以用在普通的存储器regions中,但这会使程序更加复杂,所以最好不要玩飘——通 常是外设才需要此功能。在使用时,只要把上例中的子region除能参数改为非0即可,如

MOV R5, #0x64 ; Region 1: 子region 2, 5, 6被除能

最后,再根据上一个例子的框架,举一个可能在实际的单片机会出现的例子:

MpuSetup ; 入口函数,它内部呼叫若干子程序来完成MPU设置

PUSH {R0-R6,LR}

LDR R0, =0xE000ED94 ; MPU 控制寄存器

MOV R1, #0

STR R1, [R0] ; 配置前先除能MPU

; --- Region #0 --- 用户级程序

LDR R0, =0x00004000 ; Region 0: 基址 = 0x00004000

MOV

R1,

#0x0

;

Region

0: Region号 = 0

MOV

R2,

#0x0D

;

Region

0: 容量 = 0x0D (16KB)

MOV

R3,

#0x3

;

Region

0: AP = 0x3 ( 全访问)

MOV

R4,

#0x2

;

Region

0: TEX=0,S=0,C=1,B=0

MOV

R5,

#0x0

;

Region

0: 子region除能=0

MOV

R6,

#0x1

;

Region

0: {XN, Enable} = 0,1

BL MpuRegionSetup

; --- Region #1 --- 用户级数据

LDR

R0,

=0x20000000

;

Region

1: 基址 = 0x20000000

MOV

R1,

#0x1

;

Region

1: Region号 = 1

MOV

R2,

#0x0B

;

Region

1: 容量 = 0x0B (4KB)

MOV

R3,

#0x3

;

Region

1: AP = 0x3 (全访问)

MOV

R4,

#0xB

;

Region

1: TEX=1,S=0,C=1,B=0

MOV

R5,

#0x0

;

Region

1: 子region除能= 0

MOV

R6,

#0x1

;

Region

1: {XN, Enable} =0,1

BL MpuRegionSetup

; --- Region #2 --- 用户级位带别名区

LDR

R0,

=0x22000000

;

Region

2: 基址 = 0x22000000

MOV

R1,

#0x2

;

Region

2: Region号 = 2

MOV

R2,

#0x10

;

Region

2: 容量 = 0x010 (128KB)

MOV

R3,

#0x3

;

Region

2: AP = 0x3 (全访问)

MOV

R4,

#0xB

;

Region

2: TEX=1,S=0,C=1,B=0

MOV

R5,

#0x0

;

Region

2: 子region除能= 0

MOV

R6,

#0x1

;

Region

2: {XN, Enable} =0,1

BL MpuRegionSetup

; --- Region #3 --- 用户级外设

LDR

R0,

=0x40000000

;

Region

3: 基址 = 0x40000000

MOV

R1,

#0x3

;

Region

3: Region号 = 3

MOV

R2,

#0x13

;

Region

3: 容量 = 0x013 (1MB)

MOV

R3,

#0x3

;

Region

3: AP = 0x3 (全访问)

MOV

R4,

#0x1

;

Region

3: TEX=1,S=0,C=1,B=0

MOV R5, #0x64 ; Region 3: 子region 2,5,6除能

MOV R6, #0x3 ; Region 3: {XN, Enable} =1,1

BL MpuRegionSetup

; --- Region #4 --- 用户级外设的位带别名区

LDR

R0,

=0x42000000

;

Region

4: 基址 = 0x42000000

MOV

R1,

#0x4

;

Region

4: Region号 = 4

MOV

R2,

#0x18

;

Region

4: 容量 = 0x018 (32MB)

MOV

R3,

#0x3

;

Region

4: AP = 0x3 (全访问)

MOV

R4,

#0x1

;

Region

4: TEX=1,S=0,C=1,B=0

MOV R5, #0x64 ; Region 4: 子region 2,5,6除能

MOV R6, #0x3 ; Region 4: {XN, Enable} =1,1

BL MpuRegionSetup

; --- Region #5 --- 外部RAM

LDR

R0,

=0x60000000

;

Region

5: 基址 = 0x60000000

MOV

R1,

#0x5

;

Region

5: Region号 = 5

MOV

R2,

#0x17

;

Region

5: 容量 = 0x010 (16MB)

MOV

R3,

#0x3

;

Region

5: AP = 0x3 (全访问)

MOV

R4,

#0xB

;

Region

5: TEX=0,S=0,C=1,B=1

MOV

R5,

#0x0

;

Region

5: 子region除能= 0

MOV

R6,

#0x1

;

Region

5: {XN, Enable} =0,1

BL MpuRegionSetup

; --- Region #6 --- 未使用,把它归零

MOV R0, #6

BL MpuRegionDisable

; --- Region #7 --- 未使用,把它归零

MOV R0, #7

BL MpuRegionDisable

(原文中,上例加灰的指令把SRD设置为0x9B,即~0x64,看起来似乎是SRD的某个位为零时才除能对应的子region, 与图14.3中给出的二进制数值相反。在译者查阅其它资料后仍然不能确定时,就求助于ARM了。感谢ARM的姜宁先 生为译者肯定了正确的答案!——译者注)。

上例的代码执行后,建立的regions如下表所示(假设单片机有32KB flash, 8KB RAM):


表14.8 上例代码执行后建立的各regions

地址范围

容量

类型

存储器属性

C,B,A,S,XN

MPU region

说明

0000_0000至

0000_3FFF

16KB

RO

C,-,A,-,-

背景

特权级程序

0000_4000至

0000_7FFF

16KB

RO

C,-,A,-,-

Region #0

用户级程序

2000_0000至

2000_0FFF

4KB

RW

C,B,A,-,-

Region #1

用户级数据

2000_1000至

2000_1FFF

4KB

特权极

RW

C,B,A,-,-

背景

特权级数据

2200_0000至

2001_FFFF

128KB

RW

C,B,A,-,-

Region #2

用户级数据的位带别

名区

2202_0000至

2203_FFFF

128KB

特权极

RW

C,B,A,-,-

背景

特权级数据的位带别

名区

4000_0000至

400F_FFFF

1MB

RW

-,B,-,-,XN

Region #3

用户级外设

4004_0000至

4005_FFFF

128KB

特权级

RW

-,B,-,-,XN

背景

Region #3中被除 能的子region 2

在用户级外设地址范 围中的特权级外设

400A_0000至

400B_FFFF

128KB

特权级

RW

-,B,-,-,XN

背景

Region #3中被除 能的子region 5

在用户级外设地址范 围中的特权级外设

400C_0000至

400D_FFFF

128KB

特权级

RW

-,B,-,-,XN

背景

Region #3中被除 能的子region 6

在用户级外设地址范 围中的特权级外设

4200_0000至

43FF_FFFF

32MB

RW

-,B,-,-,XN

Region #4

用户级外设的位带别

名区

4280_0000至

42BF_FFFF

4MB

特权级

RW

-,B,-,-,XN

背景

Region #4中被除 能的子region 2

在用户级外设位带别

名区地址范围中的特 权级外设

4340_0000至

437F_FFFF

4MB

特权级

RW

-,B,-,-,XN

背景

Region #4中被除 能的子region 5

在用户级外设位带别 名区地址范围中的特 权级外设

4380_0000至

43BF_FFFF

4MB

特权级

RW

-,B,-,-,XN

背景

Region #4中被除 能的子region 6

在用户级外设位带别 名区地址范围中的特 权级外设

6000_0000至

60FF_FFFF

16MB

RW

C,B,A,-,-

Region #5

外部RAM

E000_0000至

E00F_FFFF

1MB

特权级

-,-,-,-,XN

背景

NVIC,调试组件,以及

私有外设总线