本帖最后由 baiyongbin2009 于 2014-12-19 18:12 编辑
/ S& \* X/ H5 P, m
- O+ i$ H) \: L2 ?特别说明:
2 G; V, Z# K0 K1. 本教程是安富莱电子原创。% u$ n2 c1 M T% s0 a
2. 安富莱STM32F407开发板资料已经全部开源,开源地址:地址链接
3 ?6 z/ Y+ x; e: T; O) r3. 当前共配套300多个实例,4套用户手册。
0 ?5 C( Z2 R* j5 J第6章 内存保护单元MPU
! b$ z; M- m1 b+ v& ^ 本期教程带领大家学习内存保护单元MPU的使用,在前面的几期教程中曾多次的提到MPU的使用,MPU在RTOS的安全关键设计中也十分的重要,μCOS-III和μCOS-II就有配套的μC/OS-MPU,不过没有对外开源,对于想学习其源代码的人来说有点可惜,而FreeRTOS也支持MPU的配置,有兴趣的可以去学习了解。本期教程主要学习M4内核支持的MPU单元。 6.1 MPU的介绍 6.2 实验例程说明 6.3 实验总结 6.1 MPU的介绍 关于MPU的基础知识在Cortex-M3权威指南中文版的第14章有非常详细的介绍,或者看Cortex-M4权威指南英文版第11章。如果打算学习MPU,这两章一定要认真的看完。这个是下面几个MPU实验的基础,也是以后学习RTOS中关于MPU的基础。 6.2 实验例程说明 一共为本期教程制作了3个例子,下面就跟大家详细讲解这3个例子。前两个工程都不需要添加额外的文件,将代码都放在了main.c文件中实现,第三个工程专门做了一个驱动文件,方便后面教程配套实验中调用。 ( d) {' G( c6 k! }, u# }3 ?' v
6.2.1 实验一:MPU简易使用例子一实验目的: 1.学习MPU的配置 实验内容: 1.初始化串口,LED和MPU 2.主程序实现LED的闪烁 实验现象: 请用USB转串口线连接PC机和开发板。PC机上运行SecureCRT软件,波特率设置为115200bps,无硬件流控。从PC机的软件界面观察程序执行结果(如果访问MPU范围之外的空间将出现下面现象): 7 X6 I' t8 n- P! h' P$ J2 K' s
进入了硬件异常。 程序设计: 本程序主要分为两个部分: Ø MPU的配置 Ø 主程序 1. MPU的配置 MPU的配置相对比较容易,前提是一定要看权威指南上面对这个的介绍。 - /*) q# ?1 d/ a) ^6 F$ m
- *******************************************************************************************
; S; m0 ]# n" ^ `6 E- [' ~ - * 函 数 名: mpu_setup
; m2 o; M }4 u - * 功能说明: mpu配置' n& @5 E. ~+ }- F% s$ g, v
- * 形 参:无! J3 ^: |) O& E3 O+ A, F
- * 返 回 值: 无( P9 r- L- {( k/ Z& f% u9 L0 N. g/ L, S d
- *******************************************************************************************
1 Z8 |# P* O% K5 t6 r/ C - */
* b0 Z; X% A0 d* }- P - static int mpu_setup(void)
]( p! y' R) I( _4 R3 M1 Y - {
& K, f# J0 f i' V9 C2 E, ] - uint32_t i;
. U8 `& i8 N+ d; P% a7 N, P6 b -
: k! v5 z( R% T! a* c# y - uint32_t const mpu_cfg_rbar[4] =1 T. d3 S. C; C. i% f
- {* h7 [- [$ c7 L& k8 A7 S6 r2 u' S! j
- 0x08000000, // Flash0 A9 [( o& Q. v g4 L0 i, W
- 0x20000000, // SRAM
) H* g8 g% @3 N h# e% p - GPIOF_BASE, // GPIO F base address1 }4 n' h- |2 V" L) M' W: x
- RCC_BASE // Reset Clock CTRL base address
, b( C/ x) \7 y' ^: U# ] - };
' C n7 _ n& i+ w. x% M( a& E - ( y! d, n) F. C
- uint32_t const mpu_cfg_rasr[4] =
3 D* J1 H" w5 u! @0 h - {& h2 N0 f& y2 E6 U3 F5 m% L
- (MPU_DEFS_RASR_SIZE_1MB | MPU_DEFS_NORMAL_MEMORY_WT |3 z% \& a+ i, X8 G& o
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // Flash. r% K, x Q4 A$ J+ v% E' `
- (MPU_DEFS_RASR_SIZE_128KB | MPU_DEFS_NORMAL_MEMORY_WT |
! ]5 r6 V/ m7 q- ?( y% C! u. d - MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // SRAM# p: x2 B% t' a, f; X0 v
- (MPU_DEFS_RASR_SIZE_1KB | MPU_DEFS_SHARED_DEVICE |# m" o n( @" k+ B$ i
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // GPIO D* p2 m5 m' \ G" H: Z0 x
- (MPU_DEFS_RASR_SIZE_1KB | MPU_DEFS_SHARED_DEVICE |& ~6 I: h& _- R' j5 C
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk) // RCC* a* J7 q/ h6 b, l3 X
- };8 h& @! x0 J) {; o
-
H- d3 W" X# A& K - /* 通过读取此寄存器的DREGION位值,够判断芯片中是否配了MPU */ [: }, j; h% i u8 I1 |
- if (MPU->TYPE==0)
0 Z; E o$ b x& \ - {( U( u/ U/ ~9 I- S# f& s, C
- return 1;" w0 z6 P4 J: ?* C+ D
- }
6 h) e$ \+ k; R: Z; } - __DMB(); // Make sure outstanding transfers are done
& y, A/ n" v( @% e* O1 ~ -
8 l6 q+ a- L3 M - /* 禁止MPU */
4 @7 s9 l, Z0 e" ^, n9 l' u - MPU->CTRL = 0;
2 _+ C. P/ Q1 O C: n d -
9 U. l( ?" p- g7 _ L - /* 配置MPU的4个region */ * K* U, q: J2 g% F
- for (i=0;i<4;i++)# k4 P/ J9 l# M" r+ _
- { 3 W" N1 Z+ f. O# O n
- MPU->RNR = i; // 选择配置那个region4 X0 |& g! K$ h6 H$ N5 g) D4 F* G
- MPU->RBAR = mpu_cfg_rbar[i]; // 配置地址9 `! T; L6 L, p9 V4 ?: {! e
- MPU->RASR = mpu_cfg_rasr[i]; // 配置属性和大小& t9 Z9 Z% Z% }* Z( { L8 X9 Q+ ]
- }
: X+ p$ [# C- c" U -
, }% ?0 {+ U/ A - /* 下面的配置,相当于禁止*/
% U) M& V8 S( f! ?# D - for (i=4;i<8;i++)
5 s) {5 g% J9 n5 |# l: [8 a N' @ - {
. m& ?2 r4 \ T9 F - MPU->RNR = i; & ^* [7 f, r. {, R. k
- MPU->RBAR = 0; ! X/ t5 C3 A5 Y! q( y4 K/ w& A9 J8 k
- MPU->RASR = 0; . h. r( y' L# T# b3 {
- }
; X" P B4 g: ^$ }/ V. j - . z9 {' V% q! H1 R
- /* 使能MPU */7 f6 l: _* t) e, X" b( w" b
- MPU->CTRL = MPU_CTRL_ENABLE_Msk;2 {) I. _& M5 l# ]
- __DSB(); // Ensure MPU settings take effects S# e6 T: B1 S. ]$ P7 m0 J9 L
- __ISB(); // Sequence instruction fetches using update settings5 H% M$ g+ \" M8 ^+ R0 ~9 j
- }
复制代码2. 主程序 主程序的功能也比较的简单,就是实现LED的闪烁。 - #define MPU_DEFS_RASR_SIZE_32B (0x04 << MPU_RASR_SIZE_Pos)
, s0 ^# P) H% K - #define MPU_DEFS_RASR_SIZE_64B (0x05 << MPU_RASR_SIZE_Pos)
& v: a& H& u' `, ]( E! z - #define MPU_DEFS_RASR_SIZE_128B (0x06 << MPU_RASR_SIZE_Pos)
) X: A9 U7 e- M' Z - #define MPU_DEFS_RASR_SIZE_256B (0x07 << MPU_RASR_SIZE_Pos)# t* d) F: G5 z! n' f+ x
- #define MPU_DEFS_RASR_SIZE_512B (0x08 << MPU_RASR_SIZE_Pos)% m) N! N8 G; a. g* N
- #define MPU_DEFS_RASR_SIZE_1KB (0x09 << MPU_RASR_SIZE_Pos)$ G2 F4 j4 B, e D0 t7 ]8 t
- #define MPU_DEFS_RASR_SIZE_2KB (0x0A << MPU_RASR_SIZE_Pos)3 F4 q/ r$ ~- m+ o
- #define MPU_DEFS_RASR_SIZE_4KB (0x0B << MPU_RASR_SIZE_Pos)4 b9 b+ k3 m" j' F6 `( J, R3 g& w
- #define MPU_DEFS_RASR_SIZE_8KB (0x0C << MPU_RASR_SIZE_Pos)
. }3 I9 l. ~+ }+ ` - #define MPU_DEFS_RASR_SIZE_16KB (0x0D << MPU_RASR_SIZE_Pos)$ ^; ^# Z% E0 W8 c
- #define MPU_DEFS_RASR_SIZE_32KB (0x0E << MPU_RASR_SIZE_Pos); | z e( |, v w" L3 d
- #define MPU_DEFS_RASR_SIZE_64KB (0x0F << MPU_RASR_SIZE_Pos)
' ~ n# I$ b( r+ ]9 `0 O - #define MPU_DEFS_RASR_SIZE_128KB (0x10 << MPU_RASR_SIZE_Pos)
/ s# H% S T X- b$ V( ] - #define MPU_DEFS_RASR_SIZE_256KB (0x11 << MPU_RASR_SIZE_Pos) v; k. z$ A0 Q5 Y; A2 D
- #define MPU_DEFS_RASR_SIZE_512KB (0x12 << MPU_RASR_SIZE_Pos)% x0 }3 J, x( Y) ~
- #define MPU_DEFS_RASR_SIZE_1MB (0x13 << MPU_RASR_SIZE_Pos)5 I1 X2 R$ H: o3 _' I
- #define MPU_DEFS_RASR_SIZE_2MB (0x14 << MPU_RASR_SIZE_Pos)$ M; x9 `7 h6 H; B- h! |) b
- #define MPU_DEFS_RASR_SIZE_4MB (0x15 << MPU_RASR_SIZE_Pos)2 a! o8 ^% k3 k1 { \
- #define MPU_DEFS_RASR_SIZE_8MB (0x16 << MPU_RASR_SIZE_Pos)
% D% W2 W: W* S - #define MPU_DEFS_RASR_SIZE_16MB (0x17 << MPU_RASR_SIZE_Pos)
. j7 G# d2 i+ @' E$ T - #define MPU_DEFS_RASR_SIZE_32MB (0x18 << MPU_RASR_SIZE_Pos)
* O+ d' k8 ~/ J$ R) {5 J - #define MPU_DEFS_RASR_SIZE_64MB (0x19 << MPU_RASR_SIZE_Pos)
/ ?" `6 I0 }" R; s% a4 L: |" q5 [1 U - #define MPU_DEFS_RASR_SIZE_128MB (0x1A << MPU_RASR_SIZE_Pos)3 O& [$ ^" C0 X, t
- #define MPU_DEFS_RASR_SIZE_256MB (0x1B << MPU_RASR_SIZE_Pos)
* F) }0 D) x' O3 [" e - #define MPU_DEFS_RASR_SIZE_512MB (0x1C << MPU_RASR_SIZE_Pos). k5 o' d! E$ z8 d
- #define MPU_DEFS_RASR_SIZE_1GB (0x1D << MPU_RASR_SIZE_Pos) m3 i( M( l/ n' @2 f
- #define MPU_DEFS_RASR_SIZE_2GB (0x1E << MPU_RASR_SIZE_Pos)$ V e& ]. X7 V2 d
- #define MPU_DEFS_RASR_SIZE_4GB (0x1F << MPU_RASR_SIZE_Pos)
" l @; I/ v6 c& l8 G - #define MPU_DEFS_RASE_AP_NO_ACCESS (0x0 << MPU_RASR_AP_Pos)
, Q1 S. @4 @* p. D! N - #define MPU_DEFS_RASE_AP_PRIV_RW (0x1 << MPU_RASR_AP_Pos)4 W& u' s) a& c8 o+ {" a0 e
- #define MPU_DEFS_RASE_AP_PRIV_RW_USER_RO (0x2 << MPU_RASR_AP_Pos)0 P7 d: s5 Z/ S# Y" A3 V
- #define MPU_DEFS_RASE_AP_FULL_ACCESS (0x3 << MPU_RASR_AP_Pos)
' M+ h: \/ B; @6 p& _5 k - #define MPU_DEFS_RASE_AP_PRIV_RO (0x5 << MPU_RASR_AP_Pos)0 L+ H H6 P6 E4 T) C& C0 D
- #define MPU_DEFS_RASE_AP_RO (0x6 << MPU_RASR_AP_Pos) o! x& r4 A) z" Y
- #define MPU_DEFS_NORMAL_MEMORY_WT (MPU_RASR_C_Msk)8 V) H' c$ o2 E; o
- #define MPU_DEFS_NORMAL_MEMORY_WB (MPU_RASR_C_Msk | MPU_RASR_B_Msk)
$ m- [2 @; P( w/ x - #define MPU_DEFS_NORMAL_SHARED_MEMORY_WT (MPU_RASR_C_Msk | MPU_RASR_S_Msk)# g, `9 l. o8 K
- #define MPU_DEFS_NORMAL_SHARED_MEMORY_WB (MPU_DEFS_NORMAL_MEMORY_WB | MPU_RASR_S_Msk)
$ y3 Y ^: U4 Q0 w% V; G% P0 T! O2 A - #define MPU_DEFS_SHARED_DEVICE (MPU_RASR_B_Msk | MPU_RASR_S_Msk)
2 K4 O j! g+ I1 V2 ?7 v/ p4 \ - #define MPU_DEFS_STRONGLY_ORDERED_DEVICE (0x0)
2 n0 {$ h5 d' a% H" h -
# b2 V' R" u" ^; o* @3 r$ C - #define LOOP_COUNT 0x3FFFFF A# ~ O j9 v, ^* w
- I7 y- a" G4 R4 b3 ]" k
- /* 仅允许本文件内调用的函数声明 */& @" j7 ?6 t- p: s; P L: {
- static void PrintfLogo(void);
0 C3 A5 V7 \3 r- y* v - static int mpu_setup(void);
$ i: f9 J: p& C; W0 {& Z) _' K - static void Delay(uint32_t nCount);! S5 ]6 w% N% d) ?# V1 O
-
' I0 H; j/ |% U+ {. I+ o4 z - /*6 R$ B4 X' d/ x* C; j z/ Z9 Q/ k
- *******************************************************************************************
6 q1 l4 ~! b6 s+ ] - * 函 数 名: main
8 u1 S- W/ }* l; \8 d - * 功能说明: c程序入口8 r4 D0 ^, c/ V- q% D; m* @, M
- * 形 参:无9 S* r) f* L. m$ K
- * 返 回 值: 错误代码(无需处理)
A! B# O; _: D6 |+ s, w - *******************************************************************************************
* x6 Z1 w3 e: k$ \/ D - */& t! R) v4 Z9 t! }9 i2 E; e
- int main(void)% C4 c. K L6 A3 b* ]. h0 v
- { : m( Z, Q4 N. q0 a' J
- //(在Cortex-M3 r1p1中推荐使用, 在Cortex-M3 r2px 和 Cortex-M4中默认支持)/ y! p( S) Q! x5 v$ i: P: a
- SCB->CCR |= SCB_CCR_STKALIGN_Msk; // 使能堆栈的双字对齐模式
" l8 o {1 M) o! r; U - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; // 使能 MemManage fault) ]4 l, W) y( s U; _1 L
-
& P8 |/ w- }' L' i. R6 O - bsp_InitUart();
, v, ]2 m3 u4 E7 L# Q) h# @ - PrintfLogo();
9 Y6 q1 x. ^& ` H - bsp_InitLed(); /* 初始LED指示灯端口 */
4 Z) `3 b) m( Z) q5 \& t% d$ G* f - mpu_setup();
1 o W7 e# \2 P9 c4 k6 b7 {) q4 L -
; g/ V! a5 p( a, i0 D7 m. w - /* 进入主程序循环体 */
8 O9 @( D8 Y2 j - while (1)5 N. E" L( p/ T3 N
- {# Q% M. ?" J) o! _' R- ]. [! ~
- bsp_LedToggle(1);
. Q7 } X, u6 @* J, ~( B - bsp_LedToggle(3);
; e) G, u' V, t, E7 x - Delay(LOOP_COUNT);
) U" w+ F7 C# P - }; D3 {# Q9 N) l, r% T( f) d9 g4 W% ?
- }
" ?8 c! C. `1 V% y3 i - 8 F; Q# a# W; g
- /*% U( O) m( | H0 F9 J% s. t- F
- *******************************************************************************************, }/ d! R; A* L! m1 B, M# \9 h
- * 函 数 名: Delay
! }5 z+ u! t: L% }. R' u$ h: ] - * 功能说明: nCount 延迟
* H! C( I8 ~9 M% U - * 形 参:无% M! I v) S4 S0 O
- * 返 回 值: 无
/ v8 X- t6 ?( u - *******************************************************************************************
+ J/ B8 B" \2 ^% e8 a - */
7 R8 V2 F! E! H2 E - static void Delay(uint32_t nCount)
% ?3 i6 F' u8 @/ L. A$ u - {: e" R# ]+ r7 M5 _% o5 K6 P
- while(nCount--)
9 H# e: h2 @0 ^* X; }8 { - {
1 c R! F. f s" } - __DSB();7 n3 F2 ^+ M# q* F# G6 s K6 K
- } ^$ V/ ^9 r0 }, k
- }
复制代码
J4 A- U: y6 Q/ | |