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

【经验分享】STM32F7 MPU笔记

[复制链接]
STMCU小助手 发布时间:2021-12-12 21:00
MPU(内存保护单元)
: T  E# F; R4 t+ V8 b# b* L1. 前言9 d* i* C, t: ~8 O/ p$ N
在跟项目过程中,使用的F7和H7两个芯片,在用FSMC和FPGA通信时,由于其CACHE的原因,导致数据一直出错,后来通过加入MPU顺利解决此问题。因此,去学习了一下MPU,在此记录下学习的笔记,可能有理解错误的地方,欢迎指出。2 j. h7 d3 k, k1 S" K& }) E' r
参考:' q9 F, u8 }& C4 m3 O3 F, w! a
STM32F7中文参考手册.pdf
1 a, b+ U) u8 \+ Z& [STM32F7编程手册.pdf
# f- A' H6 ?/ d- }" c: FSTM32 MPU说明.pdf
. R( ~1 G6 I  E& b) |Cortex M3权威指南(中文).pdf
5 o8 g0 p6 n% y$ Z: hSTM32F7开发指南-寄存器版本_V1.0.pdf( b: R% s, ]. t
5 v! r: v0 ?$ q4 d  Z' y
2. 操作模式和特权级别
& j9 Q' c& k0 E: [% R* Q详情------Cortex M3权威指南(中文).pdf-----chpt02. D3 W+ B" N* [* k$ u- D& o
6 m7 \( G, E' L) I
2.1操作模式" f; I% d; F4 e- v1 a$ a
Handler模式:异常服务相关的代码! c; i. Y- V5 u0 \# m8 a3 y
线程模式:普通应用相关的代码
! K  ~4 e$ |8 i' T个人理解是如中断服务程序的代码与正常执行的代码。: \$ ]4 p' x! Q: X- d  K+ F% f

0 m0 W5 L$ {. H2 e: N" r0 f2.2 特权级别
1 e  }8 {& X5 N# a3 a6 k" p分:a.特权级 b.用户级3 j' a7 r5 w0 N- H: ^
区别在于对存储器的访问权限不同,特权级相当于管理员权限,除了MPU限制的区域外其他都可以访问,而并不是所有区域都对用户级开放。
, h. u, D/ z: Q" v  K: }
8 ]+ G$ t% G( M" }8 s2.3 联系
% }! d, A" c0 u& C  P3 F
20191228150751310.png
) c* u% z* A3 J7 R
, w5 }  j  e8 A1 u, p
正常执行的应用程序代码,对特权级和用户级开放;但是异常代码如中断服务程序,仅能对特权级开放。3 p4 L, o$ I) k! ]/ W* ]

3 k& b. {& T. g- z
20191228150918107.png

' n3 b& k' H( ~9 `% Z& S0 p# }+ z$ B$ A0 D, _) n$ V9 }2 q$ K
如图:当产生异常时要去执行异常代码,执行完成返回到断点。而无论在用户级还是特权级线程模式下,即使是用户级,在进入handler代码时也会暂时被提升到特权级模式,因为handler模式不能被用户级访问。: c9 t  [% b6 R! v. I0 n, {
特权级可任意访问,包括切换到用户级,仅需要修改CONTROL寄存器即可。
6 }6 z, V( F8 a3 a" U+ `' m0 t8 a6 n但是用户级切换到特权级不同,需要先申诉(执行SVC指令,触发该异常,进入异常服务代码),由于异常服务代码中是特权级模式,因此可以任意修改CONTROL寄存器,这样才能将用户级----转换---->特权级。6 y: F# ], j6 R5 i; E1 M! A
: q0 t6 e2 B5 K5 F8 f4 y+ N' D
3. MPU9 s4 Y$ r: S  m0 c
Memory Protect Uint-----内存保护单元' T6 A; v* `1 e- F, V% J; a
$ M# Z  E( O' H- V# k1 I8 |/ G; |( h( h
3.1 作用6 o- q9 B6 [1 S7 g/ w
参考了以上的PDF,大致说了以下的作用。
$ o4 o. l% V: n& e- l, ]. O- E' H% S; T, {  i& w1 d* t& m" C% ?
20191228154605163.png
( A- K& M* h. M- u& N7 k6 j) P8 b

: O# g! B* `1 h# j% d其实更多给我的理解是:通过MPU对存储器的某些区域进行属性设置,设置其对特权级/用户级开放,可读可写/只读/只写、禁止访问、全访问、支持/禁止CACHE、缓冲等等的属性,通过MPU管理存储器,不至于某块内存被非法访问、数据破坏、CACHE等等。/ }- L# x& {) F- j2 B& h! ]3 H, O5 ?
( r# \$ u" f& a/ `
3.2 REGION(区)
. a- s" L+ k7 g2 y! Q0 M' N0 xSTM32F7支持8个区,也就是说,MPU控制器通过8个区来管理存储器。
' _! i( r- ^4 l如果8个区不够,每个区都可以再细分为8个子区。大概理解图如下
& Y  C7 w( j9 Q& W6 S. q# |9 y+ v: K$ z1 S& d: S6 w* d$ V' s2 B
2019122815582658.png
, P# s2 P) l0 ^" }! O; T1 Y
, R6 E( ?' z; H; h3 |3 h1 j
背景区
/ \6 h: n1 U8 ^- l! |# e% l背景区,即没有被设置到MPU管理区的其他所有地址,背景区只能被特权级访问。否则出现MemManage异常,如果开了MemManage,会进入MemManage中断服务程序。: S# g9 a5 |2 [( K8 {, A. a9 ~
/ }/ k/ w' K& Z* B1 ?' L$ T8 ]9 _
3.3 MPU寄存器

- q2 v5 \8 e0 L/ x% F6 OM3权威指南中的MPU寄存器; J3 u4 e$ Q  p6 d8 X
4 J2 q4 Y% n3 D; y2 n
20191230094650359.png

) {" i6 r  I7 R& g5 B8 L+ G
: [9 O: Z; A4 G) l. L原子教程中的寄存器- y2 H  @4 B/ o# E

. w9 P3 y" C) b0 y7 @8 H( g: c' ^" @
20191230094823372.png
: `. ?& U: m& _  ?; {

$ H5 M: {. z5 t0 ]( g3 ZM7 MPU手册
' y1 _$ M$ b, |5 Z; ^; R7 A5 r# E8 H$ W7 k
20191230100630574.png
5 e+ s; h  a, B1 P" i0 }

! H1 h/ E% b2 c  `4 e- {MDK工程中MPU控制器的寄存器/ S: p& L) z7 }9 D/ a  ]5 w/ h" I$ p! [' R
& e/ [* N9 B$ [" Q8 R6 ~
20191230094954114.png

6 H* ^8 C- ^9 z9 L) E
8 ?/ R9 h' A$ y" b  `! }4 \其中! T" I9 S( V5 @8 |& C5 }$ h
  1. #if (__MPU_PRESENT == 1U)
    6 N  k* L+ B5 s6 d: d6 J7 Q
  2.   #define MPU_BASE          (SCS_BASE +  0x0D90UL)                    /*!< Memory Protection Unit */
    * P, e# V. b# n
  3.   #define MPU               ((MPU_Type       *)     MPU_BASE      )   /*!< Memory Protection Unit */& ]& T0 ^7 a: W: I
  4. #endif9 E) h1 q6 R1 K! Y

  5. " ?+ K. a3 K" e

  6. + b: ^5 }  @4 ]9 n
  7. #define SCS_BASE            (0xE000E000UL)                            /*!< System Control Space Base Address */
复制代码
/ v0 \- n& p4 C* E. |" N
可以看出MPU指向0xE000ED90,并结合MPU_Type类型,可以推算出,其每个寄存器的地址,都和M3权威手册中的寄存器对得上,因此放心操作。. d  I8 }4 Q6 i, a
$ i. B2 ^; ]5 \- A/ }1 v4 e
MPU 控制寄存器(CTRL)3 k( y. c' K2 F9 ~/ W) A0 a: L8 [: V
7 v1 Z2 k- w' f% h1 e
20191230100816571.png

( X/ M3 N0 Q6 T* R9 l/ f  ]; i3 U0 ^! C" Q$ S7 Y0 p) t+ {
仅三个位有效
" B/ y3 x3 V3 e. g2 A* gPRIVDEFENA:配置为1,特权级能访问背景区,用户级不行,而配置为0,仅能访问REGION区,其他都会出错,包括属于背景区的区域。
, w: U% f  J4 e2 HHFNMIENA:用于在NM1或者FAULT中断关闭MPU
% ~& z# [3 P) k! X/ \" iENABLE:使能
  [0 M: r8 X' J* A: r+ y/ ?% ?: [( {) i. e7 v/ }* r  H
编号寄存器(RNR)
# T+ E! v! F) j  Z" J

/ g$ e' Z  L* x& U5 u$ j. F
20191230101328822.png

+ z' d. O7 n& Q5 P9 q/ ?0 E% J3 K+ w6 X) ~! j. u
配置每个区时要先写该寄存器,MPU控制器就知道在配置哪个区。比如要配置REGION 1,需要向RNR寄存器写入一个1;配置好后需要配置REGION5,仍向RNR写入5。. {( E: A8 X4 H
" C! V- J/ n& Q+ N, J% n6 T
MPU 基地址寄存器(RBAR)
. |9 ^+ Q& k# d- t2 H
% W% z/ {, J4 g" m* Z
20191230101535603.png

& |" `6 v  h) u; u/ B. l
% G8 Q$ N% M8 B' E; O* a一般不适用VALID位和REGION位,这两位的意思是覆盖RNR里面的值,也就是这两个的值才是我们正在配置的REGION,RNR不生效。2 S% [) }% B, X" U
* ]- @/ A# y: D. i3 m
ADDR:配置MPU某个REGION管理的存储器的基地址,要求是----需要该地址需要是REGION大小的整数倍,比如REGION1设置为64K,那么ADDR的值需要如0X0001 0000、0X0002 0000等,0X0001000065536/102464K刚刚好5 v0 x& t4 H3 Y) `4 _3 U7 a
0 R% ^/ e7 _% L" i) K3 v
MPU 区域属性和容量寄存器(RASR)- ~2 V' S$ N. Y; l7 g, _
" d; n' c( t8 n
20191230103223269.png

( U% o' Y9 u; x: [0 y; Y
7 H5 ]- Q+ I  j& t. q  eXN:设置的REGION区管理范围是否允许取指
- Y3 q% i! k5 t6 W. ?AP:基本是6种形式。
8 n" L! C6 l+ {9 u; x1 G# ]$ ?1 s3 ~! ~& _  E  W6 {
20191230103426788.png
/ m  U; ]- q5 @' N, Q8 K& z

8 Q: J( M) U* G: P  [分别是:全禁止(任何级别不可读写),只特权可读可写,用户级不可写,任何级别可读可写,只特权只读,只读。6 Y' w% g* h8 E1 f
TXE,C,B,S
, u& F: M0 B/ y5 U3 E8 T) N; O" U4 H4 F' t. J* O, q
20191230103747475.png
, Q& y% z4 d" L% y- ]# G! v- d

5 v+ C2 h( d, U1 F* E
20191230103850819.png

3 ^0 ^3 i2 a* T! z* H1 w! T( k$ w0 [/ _. T% j. |
其中:% T& Y' [$ P5 p& m$ N: ]/ ^. v' A3 Q
强序-------------按照程序一条指令一条指令顺序执行。. d) I: {+ K& b  D- y1 l2 |& d
共享------------一块内存可同时被多个设备访问,比如两个DMA同时访问某个区域。
& k) Y: ^) {% N9 c$ D7 s' T缓冲------------类似有个缓冲器,但是要考虑是否有数据缓冲的阈值,未验证。5 ^" S7 V: T) G) _# _  @
缓存-----------CACHE,有命中和MISS,可能造成数据不一致,但是效率较快。
$ {# G1 Y/ j6 \$ K( L8 k' E& [- m写回-----------CPU更新到CACHE,仅当需要丢弃时CPU将数据更新到主存,期间数据不一致。  p0 K* _2 B$ g! g; F
写通-----------CPU更新数据时,CACHE和主存都更新。
6 V: Z: u- F" |( S# T; p$ Q3 v- R  |2 L1 k
注意
' x0 b" H' l5 G% sM3权威指南中,P195,需要SHCSR使能MEM中断。( \* A# X0 W0 u& R( t

9 _) x3 P- o2 R
20191230105312512.png
6 j" X- G2 Q( ~/ U5 l

, u7 ?! n% t- w, h3.3 相关代码

- l% B/ B6 v% T& i$ o初始化,将SRAM 0X20002000设置为128字节,不可共享/缓冲/CACHE,且只能特权级读- W3 }1 [- ~: y3 ~

) J- q0 ~: O( t9 h# p
  1. /**************************
    2 K+ K. [; i$ r% @0 P
  2.         名称:STM32F7_MPU_INIT; ^% J! `% T5 g; t3 P
  3.         功能:MPU初始化7 s# M7 G. M2 W% ^3 R+ [! l
  4.         参数:无- W- v, A1 N% F/ T% }
  5.         返回值:无2 v/ y3 l* q& u: t
  6. ***************************. h* }3 d+ W( N' @' z) b
  7. */
    / Q% x8 I4 U* ~  ^, D
  8. void STM32F7_MPU_INIT(void)/ e* s( u3 n3 h! V7 Y0 |
  9. {6 l4 T6 x/ K6 O4 p3 z( ?- a4 v
  10.                 u8 i = 0;4 M4 p% V. P7 @4 \
  11.                 u32 rasr = 0;+ E/ e3 A" H/ Y( C- u1 S( A; ~
  12.                   j: a, \4 b; [% O$ e
  13.                 STM32F7_MPU_DISABLE();                // 关闭MPU        
    ' S; H, x# s: n7 v. p$ @, Y! E7 p# k
  14.                 //MPU->CTRL &= ~(1<<2);                        // 背景区) E* {' z( ^# V  ?: ]2 _
  15.                 MPU->CTRL |= (1<<2);                        // 背景区4 c( q- Y8 H1 z
  16.                 MPU->CTRL &= ~(1<<1);                        // 不强制除能MPU
    ; L# w7 j6 i; w# ~' t6 M. C
  17.                 MPU->RNR &= ~(0X7<<0);                // 配置哪个区,只有低3位有效  @' X- m/ k4 R2 C; c% o) {
  18.                 MPU->RNR |= ((0)&(0X7));        // 使用1区; p. E7 G1 `6 d3 i7 l: h
  19.                 MPU->RASR=0;                                                        // RASR清0
    4 ?! {  G1 p% }. R/ _6 h8 ~  F; ?
  20.                 MPU->RBAR&=~(0X1F);                                // 不认可region位3 K9 y5 e6 K7 K" ^7 X
  21.                 MPU->RBAR|=0X20002000;                // 地址0x20020000
    . m& q; u, ?6 D! I: p
  22.                 rasr &= ~(1<<28);                        // XN : 1禁止取指  0允许取指$ D5 x+ |) c& B8 S1 T6 @' N0 B
  23.                 //rasr |= (1<<28);                        // XN : 1禁止取指  0允许取指% i7 Z8 j4 c: S% T' V$ l, y$ Y2 j% K
  24.                 rasr &= ~(0X7<<24);        // AP:101只读
    / S% V& D8 A: w
  25.                 rasr |= (5<<24);
    2 w$ r7 K) J% ~# v
  26.                 rasr &= ~(0X7<<19);        // TEX:001  C:0 B:0  S:0  片内外不可缓存型内存/ d- \1 \1 C6 N4 S1 U
  27.                 //rasr |= (1<<19);, E4 P+ P, A1 l, P6 N
  28.                 rasr &= ~(7<<16);
    : Y$ F, Z0 p* V, W
  29.                 //rasr |= (1<<16);: y9 [+ n' z5 C: {* \0 \: w2 S
  30.                 rasr &= ~(8<<8);                        // 不使用子区域
    * H. E; @+ H1 l; h. x2 v
  31.                 rasr &= ~(0X1F<<1);        // 64K = 2^(15+1)
    6 s( _; d  v# ]
  32.                 rasr |= (6<<1);2 O- ^5 w% o# v$ P# d' \
  33.                 rasr|= (1<<0);                        // 使能该区) m/ B/ S* O/ U/ P
  34.                 MPU->RASR = rasr;
    , E  \; [3 I; V" @5 ~
  35.                 // 使能MPU4 h5 G8 U' s+ O* ^
  36.                 SCB->SHCSR|=1<<16;                //使能MemManage5 h, |' q, _2 {/ M( f; c0 y* u
  37.                 MPU->CTRL |= (1<<0);8 V( i6 g; ?1 B; K, _* K# z
  38. }
复制代码

$ M- x$ s3 P8 C* l1 C测试,写入一个值,即进入MEM中断- M  c- d. ~! ^9 ~0 R$ Y& h0 t
! o! H4 T/ h3 N5 C5 x( g
  1. u32 mpu_test __attribute__((at(0X20002000)));
    / U! U0 k8 h3 g: ~( W+ b
  2. void MPU_Test(void)
    ; V5 h* x8 T; S6 X- G# p
  3. {
    ' s% f9 F3 k* U1 H* ?2 j0 k" X
  4.                 u8 key = 0;
    ) j0 b+ N: E2 `8 O: s
  5.                 key = KEY_Scan(1);9 H6 a2 U; y  w( K3 r0 t4 K
  6.                 if (key!=0); N$ o* V6 m, s8 w: l( @! W7 j
  7.                 {* V( }/ F( f5 I& @+ G5 _, {# ?
  8.                                 mpu_test = 20;
    3 S& k! T0 x! p. k2 |
  9.                 }% x; Y  [4 I- f5 N* x% b
  10. }
    ! M) p" _6 _( W, m
复制代码

/ Q) f0 y! A( p4 l7 n8 A
& V# e6 v* B9 C) ^, _9 a
; q! G# e( p! k& p7 M7 X
赞 收藏 评论0 发布时间:2021-12-12 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版