# Page 197 — MPU Assembly Code

## 基本 MPU 区域配置

以下代码演示了基本的 MPU 区域配置过程：

```assembly
; R3 = attributes
; R4 = address
LDR R0,=MPU_RNR           ; 0xE000ED98, MPU region number register
STR R1, [R0, #0x0]        ; Region Number
BIC R2, R2, #1            ; Disable
STRH R2, [R0, #0x8]       ; Region Size and Enable
STR R4, [R0, #0x4]        ; Region Base Address
STRH R3, [R0, #0xA]       ; Region Attribute
ORR R2, #1                ; Enable
STRH R2, [R0, #0x8]       ; Region Size and Enable
```

## 内存屏障指令要求

Software must use memory barrier instructions:

- **Before MPU setup**：如果存在可能受 MPU 设置更改影响的未完成内存传输（如缓冲写入），则需要在 MPU 设置前使用内存屏障指令
- **After MPU setup**：如果 MPU 设置包含必须使用新 MPU 设置的内存传输，则需要在设置后使用内存屏障指令

> **注意**：如果 MPU 设置过程从异常处理程序进入，或之后跟随异常返回，则不需要内存屏障指令，因为异常入口和异常返回机制本身具有内存屏障行为。

由于通过 PPB（高性能总线）访问 MPU，PPB 是强序内存区域（Strongly-Ordered memory region），因此在 MPU 设置期间不需要内存屏障指令。

### DSB 和 ISB 指令使用

如果希望所有内存访问行为在编程序列后立即生效，需要使用 DSB 和 ISB 指令：

- **DSB**：在更改 MPU 设置后需要（如上下文切换结束时）
- **ISB**：如果编程 MPU 区域的代码通过分支或调用进入时需要；如果通过异常返回进入或触发异常，则不需要 ISB

## 多字写入更新 MPU 区域

### 逐字编程方式

```assembly
; R1 = region number
; R2 = address
; R3 = size, attributes in one
LDR R0, =MPU_RNR
; 0xE000ED98, MPU region number register
STR R1, [R0, #0x0]
; Region Number
STR R2, [R0, #0x4]
; Region Base Address
STR R3, [R0, #0x8]
; Region Attribute, Size and Enable
```

### 使用 STM 指令优化

```assembly
; R1 = region number
; R2 = address
; R3 = size, attributes in one
LDR R0, =MPU_RNR
; 0xE000ED98, MPU region number register
STM R0, {R1-R3}
; Region Number, address, attribute, size and enable
```

## 使用 RBAR 预打包信息

可以使用两个 word 完成预打包信息的编程。此时 RBAR 包含所需的区域号，且 VALID 位设置为 1。

参见 **MPU region base address register (MPU_RBAR)**（第 203 页）。

适用于数据静态打包的场景，例如 bootloader。
