你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F7 MPU笔记

[复制链接]
STMCU小助手 发布时间:2021-12-12 21:00
MPU(内存保护单元): w6 L. q6 l. U5 j; ?
1. 前言" L9 s1 f6 X: R  n' z5 g
在跟项目过程中,使用的F7和H7两个芯片,在用FSMC和FPGA通信时,由于其CACHE的原因,导致数据一直出错,后来通过加入MPU顺利解决此问题。因此,去学习了一下MPU,在此记录下学习的笔记,可能有理解错误的地方,欢迎指出。2 Q3 Z6 T7 @1 K& x2 T9 l
参考:. X5 M+ n8 L  q5 I( ?
STM32F7中文参考手册.pdf# r3 H9 y: ?, O# C2 H8 @
STM32F7编程手册.pdf
, H% U9 |1 d; C- U0 pSTM32 MPU说明.pdf
2 R: U6 P& [1 f- Y3 r& S" i0 ~Cortex M3权威指南(中文).pdf: G# \8 r7 \! g/ _# [7 r
STM32F7开发指南-寄存器版本_V1.0.pdf# J* ~: u! T' G, {2 C1 {" _
; |' w9 C- w1 R% j
2. 操作模式和特权级别2 Z! S9 ]0 S( s
详情------Cortex M3权威指南(中文).pdf-----chpt02
: G' |; B6 t; n0 N; y. i# S# X: g% p  D* `/ R
2.1操作模式
: Y& e* f- h, b5 UHandler模式:异常服务相关的代码7 Z+ X0 g$ G6 p
线程模式:普通应用相关的代码; S2 E: a; o7 S, \5 u
个人理解是如中断服务程序的代码与正常执行的代码。. a" r3 q( Q/ [: C
. @5 [* M+ ?1 }9 l1 g/ R7 {/ f3 Q
2.2 特权级别+ B" b4 b- M- }9 b
分:a.特权级 b.用户级
' G0 r3 l$ W* Q# H) S区别在于对存储器的访问权限不同,特权级相当于管理员权限,除了MPU限制的区域外其他都可以访问,而并不是所有区域都对用户级开放。
' Z& B- \% x6 b' D0 X  ^5 C
  m/ k  k/ m# j- R/ \2.3 联系
  T4 M$ A3 z, J* \) w3 x0 F
20191228150751310.png

  g5 d+ ?+ {' [7 p- @& \. Q: r" D9 ?
正常执行的应用程序代码,对特权级和用户级开放;但是异常代码如中断服务程序,仅能对特权级开放。
1 V, z6 x$ c- y) O8 l0 p: {7 t0 b& K1 Z
20191228150918107.png

2 v. L8 k+ D2 I. e0 Q7 e, f
  q3 X+ V( `9 K) l4 d" x如图:当产生异常时要去执行异常代码,执行完成返回到断点。而无论在用户级还是特权级线程模式下,即使是用户级,在进入handler代码时也会暂时被提升到特权级模式,因为handler模式不能被用户级访问。
* o6 J  C) A( o+ g  v6 X1 a特权级可任意访问,包括切换到用户级,仅需要修改CONTROL寄存器即可。- P$ |8 A1 ^; l' N, ]0 e
但是用户级切换到特权级不同,需要先申诉(执行SVC指令,触发该异常,进入异常服务代码),由于异常服务代码中是特权级模式,因此可以任意修改CONTROL寄存器,这样才能将用户级----转换---->特权级。
1 C0 D2 p! v" q% X: i
. ^; ?! y: z/ Z; \+ w9 U1 T3. MPU( Z8 b: }5 M* V! j1 W
Memory Protect Uint-----内存保护单元0 D0 f' ]2 w+ f$ F
5 N1 r, _0 E2 }3 `
3.1 作用
2 B$ ]. M3 K& L参考了以上的PDF,大致说了以下的作用。7 J& {# u7 t& u2 f: `% p  K
$ Q# S" p* `' h0 ?$ G" c. Y/ s
20191228154605163.png

8 d& s/ W5 C' E  d
/ W; F2 Z2 I, s. H& |其实更多给我的理解是:通过MPU对存储器的某些区域进行属性设置,设置其对特权级/用户级开放,可读可写/只读/只写、禁止访问、全访问、支持/禁止CACHE、缓冲等等的属性,通过MPU管理存储器,不至于某块内存被非法访问、数据破坏、CACHE等等。
2 k% U- L* Z  W, I
+ y2 G" C, Q0 R  \, H3.2 REGION(区)
0 @: v, Z. U+ w* g+ B6 m3 q1 V9 iSTM32F7支持8个区,也就是说,MPU控制器通过8个区来管理存储器。# j2 T- f3 ^- F7 `) ?" D# @
如果8个区不够,每个区都可以再细分为8个子区。大概理解图如下$ Y/ c: L- _- u4 Z, D0 A8 ^4 ]
* Y7 B9 N7 |$ _' n7 h1 t& m
2019122815582658.png

- x; d5 N2 j! Q) g3 R5 x0 Z' H0 ]3 {1 e7 K6 m; b
背景区5 \' U( Z' H/ y/ T8 N, o
背景区,即没有被设置到MPU管理区的其他所有地址,背景区只能被特权级访问。否则出现MemManage异常,如果开了MemManage,会进入MemManage中断服务程序。
. F6 W+ K7 k* n+ ~- \
$ P" ^: d% W, K9 T3.3 MPU寄存器
/ l: S* Q& ?' X: K: p" g& L
M3权威指南中的MPU寄存器' \) ~8 K9 }5 b

' T8 ]0 y( p! i6 e5 z* w# d5 g# q
20191230094650359.png

5 h/ x* r" h1 {% d
1 t  B0 ~  s  \) |原子教程中的寄存器+ n2 ], z# }2 z6 b- V4 i7 c; a8 }, s
6 S* `/ r8 m) i  _2 n
20191230094823372.png
! F- I$ j' e6 z3 e/ D2 z! ?
, \1 e/ `5 I$ \7 N* B
M7 MPU手册
$ B2 [+ I3 g* V/ {" A. _" ^& R5 k7 E
20191230100630574.png
) p! V& N; }- u0 T5 R2 {* c
/ L' l- }" J. @, B. U
MDK工程中MPU控制器的寄存器
0 d/ W3 M# w" h0 E2 e/ n, J% u
# \! B, z7 J2 E
20191230094954114.png

- g0 y9 ~$ f9 Y) K8 T7 w' S/ R
. f0 Y! M) [+ I' q+ R其中
# y$ ?- y$ h# J+ p' z
  1. #if (__MPU_PRESENT == 1U)% P* U; H/ [% w) F- P4 |. W6 S3 v
  2.   #define MPU_BASE          (SCS_BASE +  0x0D90UL)                    /*!< Memory Protection Unit */
    . a( V# H* D4 j* t# ^3 P4 O; x
  3.   #define MPU               ((MPU_Type       *)     MPU_BASE      )   /*!< Memory Protection Unit */9 g1 L+ c  M2 s4 f( F
  4. #endif
    7 N8 [0 l  v/ k+ R6 n$ ?( X
  5. - w# {) E" w0 f/ _: u

  6. 4 s- \0 T! U- \0 G- C7 F1 N
  7. #define SCS_BASE            (0xE000E000UL)                            /*!< System Control Space Base Address */
复制代码

& c( F: G! t! W( @+ Y7 Q! A可以看出MPU指向0xE000ED90,并结合MPU_Type类型,可以推算出,其每个寄存器的地址,都和M3权威手册中的寄存器对得上,因此放心操作。
% U9 k5 A. r! T) @0 o3 h% E5 }  j  N) W, F+ I1 @
MPU 控制寄存器(CTRL)
3 f$ p4 M7 U& Q# z  F" g$ U" q/ K* h8 y7 d
20191230100816571.png
- s0 L) W; @7 R( g# j: E1 h9 b
% z1 W- w  t7 I
仅三个位有效8 f  c4 ?& {* Y- `2 I
PRIVDEFENA:配置为1,特权级能访问背景区,用户级不行,而配置为0,仅能访问REGION区,其他都会出错,包括属于背景区的区域。; q  ^% k+ E1 w4 [, I( ]( K
HFNMIENA:用于在NM1或者FAULT中断关闭MPU* Q2 q# n) I5 `6 s6 v  o6 E
ENABLE:使能6 M7 ^. A; i( P) A9 T0 w: F: R

1 r. E% z' r9 N3 i1 L编号寄存器(RNR)
' x+ C2 [8 O- n( |. w9 p8 v: |

. D9 W( G- C. l4 N) s: e
20191230101328822.png
/ f6 R0 P6 O2 j6 _- c

4 \  T* `0 I% j配置每个区时要先写该寄存器,MPU控制器就知道在配置哪个区。比如要配置REGION 1,需要向RNR寄存器写入一个1;配置好后需要配置REGION5,仍向RNR写入5。8 m" v4 l8 {8 |) T" ]
$ ~7 J; b2 O2 Y1 @9 k
MPU 基地址寄存器(RBAR)
/ h+ ]% o& M4 Y
% }7 K$ ^- _0 e( M
20191230101535603.png
- S0 `3 r. p# D$ O* S4 i) P

, A1 {7 f- G: H一般不适用VALID位和REGION位,这两位的意思是覆盖RNR里面的值,也就是这两个的值才是我们正在配置的REGION,RNR不生效。
/ [& R" t, f* q3 ^9 P; _7 h; z: ^3 ?3 X3 F+ T) j: |
ADDR:配置MPU某个REGION管理的存储器的基地址,要求是----需要该地址需要是REGION大小的整数倍,比如REGION1设置为64K,那么ADDR的值需要如0X0001 0000、0X0002 0000等,0X0001000065536/102464K刚刚好: \. J% y' |3 M# D  R0 J% Y9 T

& |! M+ \# [6 _6 Q. [1 P( dMPU 区域属性和容量寄存器(RASR)0 I  z3 p* h- f/ |" z* P

7 P, X) m, F, D% K" K
20191230103223269.png
4 G1 F# U# ]# q, J6 X5 t

* t; [- L+ H- f% YXN:设置的REGION区管理范围是否允许取指+ H$ [+ p$ M, |5 U5 ]4 H
AP:基本是6种形式。
: _' _' C. T2 _, i* V! }( n
- E  j; C1 j) p5 ?8 Y5 l* `5 d
20191230103426788.png
; [! Q5 B# ]6 i8 B; ~7 J) t6 s2 x0 ?

+ m" W+ E# v! S% a! y分别是:全禁止(任何级别不可读写),只特权可读可写,用户级不可写,任何级别可读可写,只特权只读,只读。
2 l9 A- w* }6 h8 e0 ATXE,C,B,S
* n, K. e" {- T7 L& O5 s3 a$ n- G" U$ v/ [+ z$ i4 Q, P& E* n
20191230103747475.png
) l0 a' H( g7 \3 M) y; ~
' V$ M3 q9 X$ Z6 i8 M
20191230103850819.png

; i- j5 N/ _  Q- j1 v( \4 M( V5 ^7 H+ @0 X1 m  m% v( e# I2 P9 z
其中:
) o& G) o3 B6 @6 d' Z8 c# c! ~2 Y6 g强序-------------按照程序一条指令一条指令顺序执行。+ d0 \4 t1 G$ G9 f) R
共享------------一块内存可同时被多个设备访问,比如两个DMA同时访问某个区域。
, H* w4 [7 R4 d% E; Y! p6 J缓冲------------类似有个缓冲器,但是要考虑是否有数据缓冲的阈值,未验证。* G: D5 p; \! P+ R
缓存-----------CACHE,有命中和MISS,可能造成数据不一致,但是效率较快。9 d: w  W8 a3 r9 ^. `
写回-----------CPU更新到CACHE,仅当需要丢弃时CPU将数据更新到主存,期间数据不一致。
. O. \. }$ k  O# k- v/ V写通-----------CPU更新数据时,CACHE和主存都更新。% g5 V" s: p9 D& b6 ^1 ?

: @1 n% r. Y2 n6 R, F& _注意2 A8 h, i* L" z+ X& O) V
M3权威指南中,P195,需要SHCSR使能MEM中断。
- F' \" V  f/ L% R6 I+ @/ j9 [2 u) _1 F1 C& V0 Y6 Q: _  {" ?3 k
20191230105312512.png
7 V# p; a$ E" }( r$ I& u# e
# `1 _( l3 L# a. D
3.3 相关代码

0 l/ A5 b- h7 x初始化,将SRAM 0X20002000设置为128字节,不可共享/缓冲/CACHE,且只能特权级读* m/ M0 }& f  S% M. t
6 w( p0 v% O5 s( n6 }0 m
  1. /**************************2 A9 ], g9 O: }/ a' I. ?4 C0 h+ c1 o
  2.         名称:STM32F7_MPU_INIT
    & A  R$ H# z1 V1 G/ D- e5 A, r
  3.         功能:MPU初始化
    & T9 J4 Y% A5 ^% D9 q
  4.         参数:无
    $ S; ?" m9 f! O$ c4 `3 O0 d
  5.         返回值:无
    5 s2 F) ?( E" p' \
  6. ***************************, _3 `( Z9 [4 }
  7. */4 @: @* P' ?: c! a# O+ S. b" I
  8. void STM32F7_MPU_INIT(void)2 N% B$ ^4 D+ s1 |3 L; @
  9. {
    8 \5 T7 Q; o" [1 Z; M4 p
  10.                 u8 i = 0;5 F2 g1 c( l& a+ m( e
  11.                 u32 rasr = 0;3 t" _6 G+ {( H5 u
  12.                 4 s7 L  V" b. Y
  13.                 STM32F7_MPU_DISABLE();                // 关闭MPU        8 ]0 Q/ p; t$ A4 r& ?, J
  14.                 //MPU->CTRL &= ~(1<<2);                        // 背景区% j9 e( [& @: M5 `) N8 F& u
  15.                 MPU->CTRL |= (1<<2);                        // 背景区
    : {5 T# f% c  R: s( {
  16.                 MPU->CTRL &= ~(1<<1);                        // 不强制除能MPU6 ]! M* s% H( K' Y4 u0 u/ X
  17.                 MPU->RNR &= ~(0X7<<0);                // 配置哪个区,只有低3位有效
    & h6 y) P- ~2 i' M/ V5 A
  18.                 MPU->RNR |= ((0)&(0X7));        // 使用1区
    1 P. S' Y, v6 Q9 }# w* g
  19.                 MPU->RASR=0;                                                        // RASR清0
    $ Y$ V8 \6 S( S- n) v
  20.                 MPU->RBAR&=~(0X1F);                                // 不认可region位/ W# t* |2 q6 y- x% c5 I* P
  21.                 MPU->RBAR|=0X20002000;                // 地址0x20020000) i6 L  Z+ ?/ ?
  22.                 rasr &= ~(1<<28);                        // XN : 1禁止取指  0允许取指: F8 Q/ v8 F( a( Y
  23.                 //rasr |= (1<<28);                        // XN : 1禁止取指  0允许取指
    & _4 b9 N4 N8 e7 |1 A8 z  Y
  24.                 rasr &= ~(0X7<<24);        // AP:101只读* x3 S6 A. a; y% I! A4 k
  25.                 rasr |= (5<<24);1 i3 X3 @# m& g) T9 i. F
  26.                 rasr &= ~(0X7<<19);        // TEX:001  C:0 B:0  S:0  片内外不可缓存型内存, j2 r+ s  n- l5 ~+ l" O
  27.                 //rasr |= (1<<19);
    & w# G" c, [. Y5 l$ n6 Z
  28.                 rasr &= ~(7<<16);  |1 O+ ]% e+ S  c- ^
  29.                 //rasr |= (1<<16);
    : d5 T( X' `" ^% [1 s
  30.                 rasr &= ~(8<<8);                        // 不使用子区域# x% D- p) B+ ~$ W% K
  31.                 rasr &= ~(0X1F<<1);        // 64K = 2^(15+1)9 L  r( }* A% U# u% o0 F
  32.                 rasr |= (6<<1);
    : Y3 l+ s, U1 M1 O/ X5 [! u
  33.                 rasr|= (1<<0);                        // 使能该区5 W( |0 i' b9 V( o& U# k
  34.                 MPU->RASR = rasr;
    8 y8 c* Z! {7 P. n( `
  35.                 // 使能MPU7 @6 k" F( F% G
  36.                 SCB->SHCSR|=1<<16;                //使能MemManage
    % `  b# A2 p! x3 Z
  37.                 MPU->CTRL |= (1<<0);; t- X  `8 S) E; I& Q  r# u
  38. }
复制代码

" s2 ~6 V+ S" d. R! E. B测试,写入一个值,即进入MEM中断
' K1 j$ W. Y% N" \
$ H% E: R' L2 D3 P% @3 I* P
  1. u32 mpu_test __attribute__((at(0X20002000)));* |8 i2 B$ M' U2 C! [
  2. void MPU_Test(void)! A: [4 |( ~1 @7 h9 L* [- q2 S5 s% |
  3. {+ D! q- F- m+ B6 L8 q
  4.                 u8 key = 0;6 ?' L. y  l; _9 P
  5.                 key = KEY_Scan(1);
    0 ?: U- o4 S% T+ L
  6.                 if (key!=0)) n: v: }  F+ U/ B! C2 T" H9 \
  7.                 {
    + Q5 K& T- e, ~+ {8 a9 b
  8.                                 mpu_test = 20;
    - Z5 R) @6 {$ e5 K7 G! R
  9.                 }
    2 F- g" u4 u# f
  10. }: L* E' ^7 P- b1 t* u; S
复制代码
/ ?: p. Z4 C" m( U  V- [. g1 O
8 a. d& u$ V; F$ G8 i8 R) Z: J' J' d

! G2 V" t" H# f3 w# b6 |0 L
收藏 评论0 发布时间:2021-12-12 21:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版