STM32H7-MPU- P- V* [, } U' ]
一、MPU的作用
' I" ]( K! I! Y; u防止不受信用的应用程序访问受保护的内存区域
" W% h* S$ P& A- C防止用户应用程序破坏操作系统使用的数据
2 b, F- H" t/ E1 D& C- E通过阻止任务访问其他任务的数据区4 l* `* s4 E0 M4 q( K, q
允许将内存区域定义为只读,以便保护重要数据。
# [. A& b$ A! K, D! H检测意外的内存访问) e9 V, T- F/ b7 i' i
简单来说,就是内存保护、外设保护和代码访问保护。0 W4 c: a/ c; I* M
2 J- l% k0 Q3 K二、MPU的功能实现* l9 S G0 q0 Z i/ I0 Q8 \9 {
MPU可以配置保护16个内存区域,每个区域都是独立配置的。每个区域的最小要求是32字节,同时每个区域还可以配置为8个子区域,通过寄存器对应的bit来使能。
/ B: P+ p9 l; J: n8 T
& [/ P+ m- R1 _ MPU可配置的16个内存区的序号范围是0-15,还有一个默认区(背景区)序号为-1,这些内存区可以重叠以及嵌套——序号为15的优先级最高、背景区的优先级最低。例如下图,共有七个内存区:一个背景区+序号为0-5的内存区。内存区4和内存区0、1有重叠部分,则重叠部分按照内存区4的配置规则执行;内存区5被完全包含在内存区3里面,则这部分内存区的配置按照内存区5的配置规则进行。
" S6 X# P; Y6 f @( b* M7 |" t( s) @. c
( v! B* D6 F: b, ~+ P7 y. U" o( y( b7 b+ C$ g+ Y/ s' n
* E' J/ E5 P! D) x三、MPU常用的寄存器(RASR寄存器和控制寄存器)
0 D q8 y! p/ O( Y6 t+ M
' \ V& {. g9 s2 N q$ O
& r6 Z% f. g9 E6 J+ ]
# F8 K2 h7 y# ^( HXN位:表示是否使能指令的提取
* I: Y/ ]: S# }XN=0:使能指令提取,即这块内存可以执行程序代码
8 ` g |7 K: L6 f/ u0 R0 ZXN=1:禁止指令提取,机这块内存禁止执行程序代码
) I7 ^3 V7 w/ ?8 w3 f. _; EAP位:设置指定区域的访问权限类型& u ^& P. @4 w5 A5 p
1 R2 H0 s- L. h5 z; f0 @
5 D( M2 g# E7 u/ D' U+ M, b0 B
4 K) c# r: e9 y/ S2 S1 H |TEX、C、B、S位:用于配置Cache的策略: M5 e: i8 m/ G' L
3 l, [9 G$ u P4 w8 w, X, {C位:用于使能或者禁止Cache+ b+ C9 i5 i7 l4 J! d5 {* @
B位:用于配合C位实现Cache下是否使用缓冲6 l( i2 N2 B: F) }- z. Z
S位:用于解决多总线或者多核访问的共享问题
9 y& P* p9 d' j" O; t* }: `, g
. ?* H8 {( _8 m6 H% L1 H2 o
, x' @" t$ o5 t& o1 ]& o; Z6 W/ Z# W! p4 P
: z7 L" U5 C5 P, C0 a) ?0 O
5 l; h- s% A1 C2 x" X" tread/write-through/back/allocate的区别:, d3 X. r1 p0 a Y, A
/ M" F& s+ R+ J. z& J* g, @, ?. U* ^一、CPU读Cache
' n8 G7 {. k5 _6 y: c9 m: d3 O
p* i2 P0 O8 v3 N# QRead through:直接从内存区读取数据
; A0 W, q9 x) t' _Read allocate:先把数据读取到Cache中,再从Cache中读取数据
7 p0 N" D: v( U$ l' x% n7 R二、CPU写Cache
& a3 ~0 N; k# ^7 k) l& f
4 P5 U( Y/ d$ S若hit命中,有两种处理方式:3 g' N: e6 d2 P; O3 c, w
3 t/ C# W- r2 ?/ ^ Q9 u" PWrite-through:在数据更新时,把数据同时写入Cache和存储区0 n `+ r3 Y) P% _6 o0 G9 ]2 W
操作简单,但是写入速度慢
( |' j0 u3 U! U( S/ dWrite-back:只有在数据被替换出缓存时,被修改的缓存数据才会被写到后端存储。& P, N1 V. \! c$ O, F) ^2 }
写入速度快,但是一旦更新后的数据未被写入时出现断电,则数据无法找回
- v; f9 R+ F6 `* o0 u6 O# a) t若miss,有两种处理方式:, y( Y8 F/ l1 w. E7 L
6 B( k( Z$ ^/ i' e ~
Write allocate:先把要写的数据载入到Cache中,写Cache,然后再通过flush的方式写入到内存中。 K( n6 q4 C l6 Z: j
No-write allocate:并不将写入位置读入缓存,直接把要写的数据写入到内存中。
W) p6 y; F7 M; c1 p什么叫hit/miss:
( G/ G. j1 `5 _6 v一、读操作
; J: D8 P' ]" z& V! ^如果CPU要读取的SRAM区数据在Cache中已经加载好,这就叫读命 中(Cache hit),如果Cache里面没有怎么办,这就是所谓的读Cache Miss。0 l5 o$ s5 c5 [/ V
( B6 G0 _/ Y5 S N二、写操作
& }* V$ c6 A# g6 U6 Y# B! u如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域(专业词汇叫Cache Line,以32字节为单位),这就叫写命中(Cache hit),如果Cache里面没有开辟对应的区域怎么办,这就是所谓的写Cache Miss。! S- a, s: W) X) _5 V, G
! e; a9 C2 N# E1 H0 R5 W: _
SRD位:用于控制内存区的子区域,一共有8bit,一个bit控制一个子区域,一般都开启5 m7 q4 h9 q2 I, z
SIZE位:配置保护的内存的大小8 {) n5 o1 r+ R* n7 t9 T
- o9 n2 z& z( z8 e& b; c" p
& B5 c1 L: v; w5 O
四、MPU的HAL库配置函数* r6 i+ a/ B* W
HAL_MPU_Disable:配置前要禁止MPU( h- m! ~3 o1 Z3 {
HAL_MPU_Enable:使能- Q8 y x, q4 a4 Q7 a5 \% B
一般使用参数MPU_PRIVILEGED_DEFAULT: v' y& S) f+ }. V; _# @- R
HAL_MPU_ConfigRegion:配置MPU" Y2 B) W J3 J& J
- static void MPU_Config( void )
& e0 V! E, q! ^" q - {; }. k' [5 I* z# H. G) |
- MPU_Region_InitTypeDef MPU_InitStruct;" a E$ U+ I$ ]: ~8 Q1 k3 j& C2 o
& J! k- V- A% }8 \( {+ x- /* 禁止 MPU */
) j4 Z7 ^/ ^1 U$ U - HAL_MPU_Disable();
1 U% z2 S7 Q0 _9 w& x7 l - /* 配置 AXI SRAM 的 MPU 属性为 Write back, Read allocate Write allocate */0 `2 q4 t# F0 |8 J D% ]( H
- 2 H2 c2 }3 c" P6 j) S% O# g% d
- //使能MPU5 u6 R7 o0 g) B. [( I- P. ?
- MPU_InitStruct.Enable = MPU_REGION_ENABLE;
- ]3 c& k' X( V( W' h5 U - //指定MPU保护的内存起始地址,注意要和下面的大小进行对齐/ Q( J; @; i! v, l, Q
- MPU_InitStruct.BaseAddress = 0x24000000;6 a b/ q# q6 |+ \- A
- //配置保护的内存大小
% q3 B6 o$ r# s8 ` - MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;& Z1 ^: y/ D1 E& |; K
- //配置区域访问权限类型
5 j/ f% T% k$ u - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
2 ]7 b; b9 x* o. p - //在开启Cache下是否使用缓冲
0 u ]- F. U- J+ Y$ @ - MPU_InitSt ruct.IsBufferable = MPU_ACCESS_BUFFERABLE;; b2 ^4 Q7 E1 D3 Y% v; p2 V
- //是否开启Cache
( M" P! C1 O. F; k& G - MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
7 X9 r2 J6 x2 u+ B- Y - //是否开启共享
g2 y% v( P* t. X0 C( E - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
2 X: m/ ]6 w3 p! j - MPU_InitStruct.Number = MPU_REGION_NUMBER0;
9 I) P& `2 B u, `! |( b) ? - //配置缓存的策略8 b0 E X3 P6 ?
- MPU_InitStruct.TypeExtField = M PU_TEX_LEVEL1;
. c$ t+ q1 \- _1 V$ S- A+ x: E8 v# A* P - //是否开启子区域) P4 }. d6 M" I! d
- MPU_InitStruct.SubRegionDisable = 0x00;
" j- v; ?. y' Z - //指定指令访问状态9 h# q3 K: H0 K1 S/ Z4 m
- MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;# E) W/ i- ~ m6 m4 h3 q, P. x
- HAL_MPU_ConfigRegion(&MPU_InitStruct);
2 R7 x% L! y" J3 P& T" b' i - 3 N7 t- x. I3 j
- HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);2 k# n" l& B2 i
- }- V2 _7 t/ E4 V5 w( M! B
- # x1 Q4 O M0 a
复制代码 5 ~% x# B) z; ^0 c/ k0 h# @
# N, g' |& V w" Y+ o! v
|