首先需要使用STM32CubeProgrammer软件对芯片的模式进行配置。" R# b0 U! {' r( ~, X9 i
' O5 P! T. @* }' R; { C, R
连接上芯片后,选择OB选型卡,找到User Configuration! R" u* Z+ l0 ~2 e" r
5 f7 i/ \6 c6 Q" g8 L% A1 A. G, k将其中的TZEN选项打上对号,使用Apply写入到芯片。" `9 f" e% V- `0 @2 o7 M
2 y1 J1 r6 v0 N
' j/ Z& R2 a) b, J如图所示配置Secure Area 1与Secure Area 2选项,使用Apply写入到芯片。
1 o$ {. T1 z$ }8 S4 S- c
1 l' @1 H2 _) p) @" l% |2 y
& k( L; r; L% J% i8 _
打开STM32CubeMX,找到STM32U585AI,这一次就要选择第二项开启TrustZone了。. m# b# a/ y, g7 `$ W
/ c$ r* y( U) b2 s& n& t" V9 @9 X
' f3 J; m. ?- V0 t/ ^看看新的外设界面,嗯,与之前大大不同啊。
/ d% l9 M% u/ Q* D% U" E1 W
4 M) C) K# ] Q" B; I5 |/ t2 T
, ]0 b( \# V% x( s简单配一下时钟。0 g0 k: D# x* a5 f
2 l( K$ Y' Q/ O3 G, f
1 Z7 V' K. v% T R9 L# a, L配一下SWD,这里就让他使用安全区域那边的初始化。4 [$ V5 F* P* @2 ?! c
! U/ O B# J0 ?4 }" ^. k* W: U5 M% Z1 A
1 `6 J9 o" ~: C2 h4 I配一下IO,就是板子上的两个小灯,一个配置到安全区域、一个配置到非安全区域。
7 @; F' N% m" L6 Z
) q& x6 v& X& H5 H! m
9 {! b) E: _; `- T5 v
生成代码,打开keil,嚯,两个工程啊(工程之间的区别以后再聊)。7 v- ^1 z/ Z( r& w* c
7 F! n- X5 x# g& O/ K9 x+ c8 R
8 i( Y2 _2 P! |; J0 r! T( F右键可以切换选中工程。
1 s6 F3 N; @& P/ z& r$ K
' L$ H" V, q" c6 F9 X+ N. C! G3 }
看看代码7 d, l) z/ q$ n6 {- U: _( l+ ]9 }
安全区域的GPIO初始化- G/ A# u* r8 B& t1 k6 D' G2 n
- void MX_GPIO_Init(void)' O0 c8 v8 j$ z6 W; j/ z$ r
- {8 w9 X1 l) J2 B
- " d! k% I3 j/ S) E9 J8 c, ~) C
- GPIO_InitTypeDef GPIO_InitStruct = {0};! N) f8 r/ m8 _; [. r( Q$ H6 Z
- 4 q# {5 U/ v2 a3 q1 g k! U- S6 P
- /* GPIO Ports Clock Enable */
) d6 A$ {5 B+ N& k - __HAL_RCC_GPIOA_CLK_ENABLE();3 Q, W( f0 R) c
- __HAL_RCC_GPIOH_CLK_ENABLE();: }8 q, b! ]4 X% H$ W
8 {$ F1 c% \7 D3 n- /*Configure GPIO pin Output Level */* Z/ J% U- S& r6 ?
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET);
3 G9 C+ z, H' o K( h - 8 m$ l6 q6 L. [' w; g
- /*IO attributes management functions */4 U3 A' s+ v9 p# S& j
- HAL_GPIO_ConfigPinAttributes(GPIOH, GPIO_PIN_6, GPIO_PIN_NSEC);% H% d" `( p& R- W& j; o
- ) R( \4 B* @% P: W; d$ U
- /*Configure GPIO pin : PH7 */
4 x3 n( C. T) n0 u0 O4 U4 e - GPIO_InitStruct.Pin = GPIO_PIN_7;& j( N0 |& Q4 z! X+ C0 L7 E
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ \+ P- A% Y; N( J - GPIO_InitStruct.Pull = GPIO_NOPULL;' H* f3 H. C! \
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;0 ?; K' n3 ?1 [3 o4 Z$ V# [+ n
- HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
+ y7 c7 G$ I. R& c. m, a' x; X - _% A+ S% L# t/ g7 w0 V
- }
复制代码 ; A6 B. ^; y* U, S7 Q( [
非安全区域的GPIO初始化& j' l. c0 u4 k( Y
- void MX_GPIO_Init(void)
, W1 [9 T/ U7 d - {
' p, T) f' s6 P+ g0 e - # E! S* N, _, U- ]+ m
- GPIO_InitTypeDef GPIO_InitStruct = {0};
/ T9 K' y6 F# q$ y - e7 u1 Z: a% v% T% m/ n# f' `
- /* GPIO Ports Clock Enable */
8 }, h }' W7 y4 A - __HAL_RCC_GPIOH_CLK_ENABLE();$ h! Y( z h1 e. a i( A3 p+ z5 q
- 9 t6 K( }: f- G p/ s1 i
- /*Configure GPIO pin Output Level */
. k( b1 O& g+ t4 X) I: [ - HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_RESET);% S& M" }; B, @& q
/ M4 D9 D4 X8 U* F- /*Configure GPIO pin : PH6 */9 n( q9 E' q4 U+ I: y% c ~1 s! B# m4 l
- GPIO_InitStruct.Pin = GPIO_PIN_6;/ d1 [5 n1 ?& }3 A+ Y/ x9 l
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; q3 }5 Q7 B% p: ?) u
- GPIO_InitStruct.Pull = GPIO_NOPULL;9 e2 }7 h9 P. d4 \
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;/ g; C; F9 V' d4 i& F/ u
- HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
" r& E/ ]' }" `5 z
! R+ u3 s7 }! Z' N7 u! }* ^' e- }
复制代码
8 ^4 ^/ Q7 X- [: j. T: Q区分还是很明显的。
; Q- O- T2 C3 G3 C1 s" W7 `2 y
8 s4 F* G3 Q) w9 h6 ^% Z3 \接下来写写代码看看( n( A) r/ g. N" w" \* W) r
安全区域
( L# W: }0 ^1 X$ Q) n- while (1)6 u# d2 J& |0 b0 r' ]/ q2 H+ p
- {; z; r8 t7 G* M3 @# |6 ?
- HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_7);: M( A9 v* j# X" T! w
- HAL_Delay(1000);3 g9 i9 u# Z0 G9 |/ k! `
- /* USER CODE END WHILE */
2 `$ {8 r/ ]1 X1 w/ a
+ t& v6 L3 j1 p! p5 T8 X- /* USER CODE BEGIN 3 */
" e" y$ F0 d% ~7 z$ `4 {. u( J - }
复制代码 9 r7 a! B1 l1 T# @
非安全区域
7 \$ q9 n3 i) g, i! T2 F- while (1): w! V' q7 v! K* V5 O: q) {" o
- {
1 R% s* n6 B; H' U) h$ U1 O - HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_6);6 l& Z+ O6 ]3 Y6 z" D1 | v6 C
- HAL_Delay(1000);
+ ~) o# M. C( t3 ^3 A. x* l1 Z! X+ I2 a - /* USER CODE END WHILE */
* I! u8 F2 Z! S5 |7 a - ' r4 }6 L2 T& M9 N% \- T- S4 e
- /* USER CODE BEGIN 3 */
- Y; o% M+ K+ _7 ` - }
复制代码 / F4 j3 e' Z# H W5 H
写了两个闪灯的程序,各自是各自的。看看会发生什么。把两个代码都下载到芯片内部。
9 m- A3 [' o: ~: ?5 x( L5 b5 B- [& k
" ]4 P! w8 h( u" s, {# U结果是,非安全区的代码while(1)里面的代码正常执行,而安全区while(1)里面的代码没有正常执行。板卡红灯闪烁,而绿灯常亮(图片看不太出来)。8 e C5 M W }/ Z# x0 _
* T3 B' ]3 v/ N& {/ ?- R. y原因也很简单,安全区代码是上电之后优先执行的,然后运行到NonSecure_Init,把非安全区堆栈初始化好,然后调用非安全区的复位函数(具体调用方式与逻辑请关注后续文章)。然后代码就跳转到非安全区了。
& j& W5 X2 e. m
3 w, O- P9 R) P+ l( _, h也就是说,两套代码,并不是真两个核,内部还是只有一个内核滴。
+ ~5 v4 X9 W9 w: R$ N$ v( Y5 z {* x+ V
|
你有测试过吗?M33只是为了安全在NVIC、MPU、SYSTICK等资源提供了双份,本身控制还在在切换安全区与非安全区运行实现的。核心资源只会提供一份的。
: S% N/ M9 w5 b5 W" @; ?
用过NXP的LPC55S69 里面有两个M33 ,理解错了
[md]嗯嗯,你说的这一颗芯片比较特殊,他虽然是双核M33,不过仅有第一个核是支持TrustZone的
& n7 h1 K; Q4 W& x0 m
* ?+ {7 N: J7 m+ r# p5 D, S