|
理解与应用 MPU的特权与用户模式 前言% ^* `% b1 a+ Y% S6 c7 M: U# b0 @ STM32系列支持MPU内存保护单元,可用来设定内存的属性和访问权限。MPU的应用笔记提到,将属性寄存器(MPU_RASR)配置成某一个值,在特权(Privileged permissions)和用户模式(Unprivileged permissions)的访问许可是不同的,甚至可将用户模式的权限设置成不可访问。那么,什么是MPU的特权模式和用户模式呢? 接下来我们在这篇文章来理解这些名词,并讨论在STM32 MCU代码中如何使用内存保护单元MPU的特权与用户模式。 & c0 i8 e* o* B( U& L$ h MPU(Memory Protection Unit) MPU内存保护单元可以用来使嵌入式系统更加健壮与安全。它可以阻止用户应用程序破坏系统关键数据。它可以通过将内存SRAM区域定义成不可执行,来阻止代码注入型攻击。也可以用来改变内存的性质,例如是否允许缓存(Cache)。' o7 X0 `7 [6 ~2 o 用来设置内存属性的 MPU_RASR寄存器字段描述如下:; Q# G, ~+ i. J M" B) \. N
图表 1 MPU_RASR字段* C. _( R. { m & N* w- r. H8 [. ^ 在MPU_RASR中用来设置数据访问许可的AP字段详细设置选项如下: 3 y0 ?& E- v0 t- p- t5 U3 f5 ?
图表 2 内存访问权限设置 4 a6 ~. K2 z. u 特权模式(Privileged mode)与用户模式(UnPrevileged mode)' Q1 f* m3 ?. D7 H1 i* C. k 特权模式与用户模式是指Cortex内核的执行模式。它不是MPU的一部分,但与MPU单元有关联。当代码运行在特权模式下,代码拥有所有的访问许可;而代码运行在用户模式,则访问权限受限制。限制包括在系统设计阶段就定义的可运行指令限制,可访问内存以及外设限制。也包括由MPU单元动态所定义的内存访问规则。 从特权模式进入用户模式,只需使用MSR指令操作CONTROL寄存器。但是,不可以直接从用户模式转入特权模式,必须经过一个异常处理操作模式,比如SVC( Supervisor Calls)。在异常处理通过操作CONTROL寄存器,可从用户模式回到特权模式。请注意,特权线程与异常处理线程,都是在特权模式下运行。 如下图所示:: G I7 L, ~% [6 ]
: N; Y# _' @$ ~1 \! t! b 在代码中结合特权与用户模式使用MPU 1. 开发环境6 {* H" z8 d+ s- ^ 开发板: STM32 L476RG NUCLEO4 e/ G+ N+ w& }2 O% I, Y0 @ 开发工具:STM32Cube_FW_L4_V1.7.0 S$ n' ^" B/ Q! t IAR/Keil0 H' J& Z# h4 E0 Q$ {; N 注:也可以选择其他STM32系列并选择相应的开发板与固件库。7 L+ c* l6 I5 q+ `/ e 2. 开发目标定义' m4 Q# Z8 O$ v9 E/ d3 k. e 在软件中定义一块数组,使用MPU将该区域配成仅可从特权模式下进行访问,并验证用户模式下访问会导致内存管理异常或者硬错误。 9 K1 g, x# n7 j A6 n5 u
图表 3 特权模式与用户模式的切换 7 J* @5 f4 P( O% v3 a% U9 p 3. 代码资源与整合 H- k2 D. k. o/ i t2 Y2 h STM32 Cube固件库提供了大量的例程供学习和重用。查找STM32Cube_FW_L4_V1.6.0可以发现,固件库已分别实现了特权模式与用户模式的切换(CORTEXM_ModePrivilege),和MPU的配置(CORTEXM_MPU)。- _$ S, A# D \* p; u8 N* t
- b& z* M+ I: m' B 我们需要将两个例程整合在一起来实现我们的开发目标。注意你选择其他STM32系列也是没有问题的,也支持MPU功能。2 \' y, ?5 _/ d1 b* j* ?. i+ ^6 o 复制CORTEXM_MPU\Src\stm32_mpu.c 到CORTEXM_ModePrivilege\Src目录下
复制CORTEXM_MPU\Inc\stm32_mpu.h到CORTEXM_ModePrivilege\Inc目录下
打开CORTEXM_ModePrivilege工程文件,将stm32_mpu.c和stm32_mpu.h添加到工程文件中。IAR与Keil略有不同,在IAR下只需添加C文件。* Q: p1 ~& g9 G6 W! v; ` 0 \8 [/ u5 I2 g& C ( b/ f# J" D5 n& N( ?* G 4. 修改与增加代码* I) C" s) \# ~( h1 d" O" [ 新增加的代码以红色表示' Q0 {1 U) M C6 c1 ?2 } ●在主程序中包含stm32_mpu.h3 Z4 `7 @; B+ M: E4 m
●在主程序里调用MPU配置函数+ P8 w+ S5 k; ]6 S8 Z% Z 要对使用的内存进行MPU配置,未被MPU配置的资源将视之为不可访问。这是MPU_Config必须被使用的原因。6 x$ \# ^6 E9 k, {' g L# \" @* S
●修改MPU_AccessPermConfig将数组区域配置成我们设计的权限并增加测试代码。2 ^8 { S( ?' A' r MPU_AccessPermConfig在特权模式下运行,故测试代码不会触发异常。. _' y4 P- t7 I
●在用户模式下尝试读写数组 参考代码中直接访问数组,很容易被编译器优化掉而不能发挥测试作用。这里加了个判断后写的操作,使编译器不去优化它。 # G" x" z! B: {1 U2 w# d
至此,可以编译成功运行来体会特权模式与用户模式的MPU的不同配置。执行到主程序中新加的数组访问代码,会产生内存管理异常。 : {' R1 K# J* p5 i 7 {% X: C ]$ j 5. 关键代码分析 ●从特权模式进入用户模式。直接设置CONTROL寄存器。
●从用户模式回到特权模式,需要触发异常处理$ r, j- E' h' I2 W
●在异常处理中将线程回到特权模式执行
●若用户模式下代码试图访问无权限数据将产生内存管理异常,从而进入下述函数。
3 O" @; S- A) X 结论) v3 _1 r2 f" W: U" F y* E. M, d 本文档介绍了MPU的特权与用户模式,并整合与修改已有代码进行了应用。在实际中可将MPU与Cortex运行模式结合,可使应用更加健壮与安全。& v; X0 b) {' v$ u3 A) f5 f & G2 r2 G1 [# l, ? " }, }8 e1 z$ _$ _1 g( ^0 W- C0 Q 文档下载 ^+ s: r5 y$ V* y% T5 p' z 3 l# n! Z# X, B! y. J- i+ H 更多实战经验 |
STM32MP157双A核Linux + 自研RTOS双系统镜像免费下载
STM32MP1 自举程序编程:USB DFU/USART 协议全解析
实战经验 | 如何配置STM32MP257的RMII Switch
OpenSTLinux 6.1发布:M33-TD加持+安全升级,STM32MPU开发效率翻倍!
STM32MP135 MP157 MP257 CoreMark移植&&跑分对比&&多核心负载不均衡问题排查与解决
实战经验 | 1小时在STM32MPU上运行YOLOv8——训练篇
实战经验 | 1小时在STM32MPU上运行YOLOv8——训练篇
利用STM32MP1和STM32MP2为嵌入式Linux提供有效的安全措施:供当今决策者参考的3条宝贵经验
有奖直播 | STM32MP2x 资源隔离架构 (RIF) 介绍与使用
白皮书下载|边缘 AI 变革:MCU集成 NPU 的破局与领航
微信公众号
手机版
谢谢分享