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 STM32 MPU说明.pdf 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 . i# S# X: g% p D* `/ R 2.1操作模式 Handler模式:异常服务相关的代码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.用户级 区别在于对存储器的访问权限不同,特权级相当于管理员权限,除了MPU限制的区域外其他都可以访问,而并不是所有区域都对用户级开放。 2.3 联系 7 p- @& \. Q: r" D9 ? 正常执行的应用程序代码,对特权级和用户级开放;但是异常代码如中断服务程序,仅能对特权级开放。 8 l0 p: {7 t0 b& K1 Z 如图:当产生异常时要去执行异常代码,执行完成返回到断点。而无论在用户级还是特权级线程模式下,即使是用户级,在进入handler代码时也会暂时被提升到特权级模式,因为handler模式不能被用户级访问。 特权级可任意访问,包括切换到用户级,仅需要修改CONTROL寄存器即可。- P$ |8 A1 ^; l' N, ]0 e 但是用户级切换到特权级不同,需要先申诉(执行SVC指令,触发该异常,进入异常服务代码),由于异常服务代码中是特权级模式,因此可以任意修改CONTROL寄存器,这样才能将用户级----转换---->特权级。 3. 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 作用 参考了以上的PDF,大致说了以下的作用。7 J& {# u7 t& u2 f: `% p K $ Q# S" p* `' h0 ?$ G" c. Y/ s 其实更多给我的理解是:通过MPU对存储器的某些区域进行属性设置,设置其对特权级/用户级开放,可读可写/只读/只写、禁止访问、全访问、支持/禁止CACHE、缓冲等等的属性,通过MPU管理存储器,不至于某块内存被非法访问、数据破坏、CACHE等等。 3.2 REGION(区) STM32F7支持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 0 Z' H0 ]3 {1 e7 K6 m; b 背景区5 \' U( Z' H/ y/ T8 N, o 背景区,即没有被设置到MPU管理区的其他所有地址,背景区只能被特权级访问。否则出现MemManage异常,如果开了MemManage,会进入MemManage中断服务程序。 3.3 MPU寄存器/ l: S* Q& ?' X: K: p" g& L M3权威指南中的MPU寄存器' \) ~8 K9 }5 b 原子教程中的寄存器+ n2 ], z# }2 z6 b- V4 i7 c; a8 }, s 6 S* `/ r8 m) i _2 n , \1 e/ `5 I$ \7 N* B M7 MPU手册 " A. _" ^& R5 k7 E / L' l- }" J. @, B. U MDK工程中MPU控制器的寄存器 其中
可以看出MPU指向0xE000ED90,并结合MPU_Type类型,可以推算出,其每个寄存器的地址,都和M3权威手册中的寄存器对得上,因此放心操作。 j N) W, F+ I1 @ MPU 控制寄存器(CTRL) $ U" q/ K* h8 y7 d % 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 编号寄存器(RNR)' x+ C2 [8 O- n( |. w9 p8 v: | 配置每个区时要先写该寄存器,MPU控制器就知道在配置哪个区。比如要配置REGION 1,需要向RNR寄存器写入一个1;配置好后需要配置REGION5,仍向RNR写入5。8 m" v4 l8 {8 |) T" ] $ ~7 J; b2 O2 Y1 @9 k MPU 基地址寄存器(RBAR) 一般不适用VALID位和REGION位,这两位的意思是覆盖RNR里面的值,也就是这两个的值才是我们正在配置的REGION,RNR不生效。 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 MPU 区域属性和容量寄存器(RASR)0 I z3 p* h- f/ |" z* P XN:设置的REGION区管理范围是否允许取指+ H$ [+ p$ M, |5 U5 ]4 H AP:基本是6种形式。 分别是:全禁止(任何级别不可读写),只特权可读可写,用户级不可写,任何级别可读可写,只特权只读,只读。 TXE,C,B,S $ n- G" U$ v/ [+ z$ i4 Q, P& E* n ' V$ M3 q9 X$ Z6 i8 M 5 ^7 H+ @0 X1 m m% v( e# I2 P9 z 其中: 强序-------------按照程序一条指令一条指令顺序执行。+ d0 \4 t1 G$ G9 f) R 共享------------一块内存可同时被多个设备访问,比如两个DMA同时访问某个区域。 缓冲------------类似有个缓冲器,但是要考虑是否有数据缓冲的阈值,未验证。* G: D5 p; \! P+ R 缓存-----------CACHE,有命中和MISS,可能造成数据不一致,但是效率较快。9 d: w W8 a3 r9 ^. ` 写回-----------CPU更新到CACHE,仅当需要丢弃时CPU将数据更新到主存,期间数据不一致。 写通-----------CPU更新数据时,CACHE和主存都更新。% g5 V" s: p9 D& b6 ^1 ? 注意2 A8 h, i* L" z+ X& O) V M3权威指南中,P195,需要SHCSR使能MEM中断。 / j9 [2 u) _1 F1 C& V0 Y6 Q: _ {" ?3 k # `1 _( l3 L# a. D 3.3 相关代码 初始化,将SRAM 0X20002000设置为128字节,不可共享/缓冲/CACHE,且只能特权级读* m/ M0 }& f S% M. t 6 w( p0 v% O5 s( n6 }0 m
测试,写入一个值,即进入MEM中断
8 a. d& u$ V; F$ G8 i8 R) Z: J' J' d |
刘氓兔的杂谈【001】-片上USB 高速PHY
【合集】STM32F7教程、资料大集合
基于STM32F746G-Discover的扩展电路板
F769 Discovery实现播放U盘音乐的播放器
STM32 VS Code Extension (在Ubuntu上开发STM32,ST官方vscode插件使用指南)
STM32F765@216MHz跑NES模拟器【代码】【视频】
基于STM32F7实现ADC软件触发+轮询采集
基于STM32F7进行ADC采集解决更新问题
基于STM32F7使用定时器经验分享
实现基于STM32F7中周期采集