首先需要使用STM32CubeProgrammer软件对芯片的模式进行配置。
: Z' H o% H: C0 u8 A* g! r
% A( M" n- K/ {7 i
连接上芯片后,选择OB选型卡,找到User Configuration
* _# U4 X- J8 i
3 f& n- F8 }6 I+ j ^将其中的TZEN选项打上对号,使用Apply写入到芯片。
9 M- g" U! r% X
, b+ P: p6 l: J# ?9 P6 t7 Y+ F1 P# O6 d4 Y
如图所示配置Secure Area 1与Secure Area 2选项,使用Apply写入到芯片。. ~& w3 N/ I L2 W) u
* A! _: f4 ^/ x2 c) J! R2 h/ B/ l' F# }5 P$ B. B$ H9 ` J3 M* Y
打开STM32CubeMX,找到STM32U585AI,这一次就要选择第二项开启TrustZone了。
& W$ G& d- c3 y% s1 B
5 J& ~, G. Q# O7 \+ C1 u
7 z6 x. A' B8 L$ f2 i8 U看看新的外设界面,嗯,与之前大大不同啊。$ v6 r! n# i7 U% {, l
( C, Z, J! Y& B8 J7 g v( A3 a2 o$ K
4 U* Y8 P) J1 I! C" C简单配一下时钟。* k1 e6 P) r6 P8 @2 I6 z
2 @4 V' Z3 i/ w7 q
+ \( Y* U6 @% K; n4 w
配一下SWD,这里就让他使用安全区域那边的初始化。
# y* ^0 [& A! e6 i
# N: F, E, o8 o2 Q0 M" y) z! c
2 A) J! B; F! s- n配一下IO,就是板子上的两个小灯,一个配置到安全区域、一个配置到非安全区域。; G! ~ }* z; V. v# d
' R$ p* o3 r% R
4 @$ z9 I9 n$ A$ v" F7 ~8 R3 y
生成代码,打开keil,嚯,两个工程啊(工程之间的区别以后再聊)。
' q/ W2 ^5 g/ C. m4 u
; x# ?$ h# ~: q5 l
! L5 [: W! S0 u: k* ~3 A. l& f右键可以切换选中工程。
: S& H+ z7 E7 p8 l! E. o
3 a3 w1 k) j, u. M( ]: u: ~: l1 `3 A
看看代码
0 k! m0 F& W% g6 M6 q" E0 [( r安全区域的GPIO初始化
) {7 E4 y, F$ t( _; L6 A- void MX_GPIO_Init(void)4 ~' h) M5 _, N
- {6 \ |9 e8 x6 s6 Q* |
- 7 K: X3 E* v* q3 ~
- GPIO_InitTypeDef GPIO_InitStruct = {0};
6 P, W5 b3 ~ m2 h8 k8 r9 T/ c* t - 1 D' L- [9 ?& X9 u U' c; j
- /* GPIO Ports Clock Enable */- e. n+ y1 S" Y# P3 N
- __HAL_RCC_GPIOA_CLK_ENABLE();
- m$ `0 n, X) `+ H) `/ l) _1 b2 D - __HAL_RCC_GPIOH_CLK_ENABLE();
' d1 B9 O6 U5 R. R6 i+ q( [0 U - / |% U2 D7 f/ J! \2 F/ f0 @* S
- /*Configure GPIO pin Output Level */. `3 e e" D9 h @
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET);& g) r" Q% X8 ]+ i4 Y
( g, v j/ t) p5 M7 y- t7 O& f- /*IO attributes management functions *// K. V( y! ]5 X1 d
- HAL_GPIO_ConfigPinAttributes(GPIOH, GPIO_PIN_6, GPIO_PIN_NSEC);
1 G1 E5 O/ `; q: x - ; n Z# G; W; M1 h- K
- /*Configure GPIO pin : PH7 */ E. e1 [$ t) v2 |/ K7 M
- GPIO_InitStruct.Pin = GPIO_PIN_7;
: A9 |+ j0 D$ P, f; J# m - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;& D, \7 V7 g- A) I1 [4 f: i
- GPIO_InitStruct.Pull = GPIO_NOPULL;! I0 c5 L0 E4 p* C: j3 z- K* o
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;' g6 J: y7 ^4 H0 p9 u4 m6 J6 |9 p, k
- HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
6 g. U' e( P2 L# A2 s9 j! U - % {' B( g8 S" ~5 U0 F( c
- }
复制代码
) u F8 E. X# }& I非安全区域的GPIO初始化
( d% n+ l1 ^& [- void MX_GPIO_Init(void)
7 p/ @& G$ Z: o' b - { T& s/ R) E" { a; @* L
- $ G' I8 Z( @0 v2 j
- GPIO_InitTypeDef GPIO_InitStruct = {0};
% [" s% J4 e$ V8 m- ~" Q - - l7 t7 a0 X* F- z3 o) f% v
- /* GPIO Ports Clock Enable */
$ a1 l y1 `9 f9 l9 N' o" c - __HAL_RCC_GPIOH_CLK_ENABLE();
) |: N( q7 s% A; ~1 { - & L7 z" y# K8 r9 f
- /*Configure GPIO pin Output Level *// W$ Q2 ?3 Q- H
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_RESET);+ M8 T6 j3 O+ f
- 5 H1 e/ C3 O# Q! ^/ J2 J* p" ?( I
- /*Configure GPIO pin : PH6 */
) k9 W3 O9 [9 D' v - GPIO_InitStruct.Pin = GPIO_PIN_6;5 W! A J( o0 G% ^6 |' w
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;) p9 e* [9 L% n% p& O8 `" y
- GPIO_InitStruct.Pull = GPIO_NOPULL;
8 F8 L8 y$ l* r( U, j/ y) o7 O) } - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
5 d F" B1 Q4 L7 `+ @4 K - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
# [! v( t4 S% h- E
; Y. x5 o4 G( f- O- }
复制代码 : t2 _6 o9 x% |1 P% \' R# w
区分还是很明显的。
, K. [- M3 k7 W
' y9 w+ e" g! w& a! N/ H4 ]8 j接下来写写代码看看8 F( h' P3 W8 S+ s9 K
安全区域
; J) |' y5 j6 `7 ?3 X# B8 H& l- while (1)- E0 q" D W F- Y
- {9 Z. L Q1 @9 ]9 Z
- HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_7);
% ~8 B3 L( K4 v9 y( D. C - HAL_Delay(1000);
7 j+ a9 r u) ?/ M3 _ - /* USER CODE END WHILE */
/ }0 Z1 t1 `' Y; e @3 s
}0 y; ]" u$ ]0 L' Y4 ~- /* USER CODE BEGIN 3 */+ _ M" c- x* T1 @6 B
- }
复制代码
: S8 o/ N7 e0 A! J: `1 w' F' u' |非安全区域
7 V- n% b4 l# n. P- while (1)
" a2 {6 A$ t$ e - {7 w/ b) t4 R( n% y# h, n* Q
- HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_6);. ^. o$ j1 ?3 a- g3 r# c
- HAL_Delay(1000);" m8 s. } g U8 ` x6 C
- /* USER CODE END WHILE */2 k) M# m( N6 ], g' K9 _8 L
% o/ ]/ L9 z: ~& D) \* h: @- /* USER CODE BEGIN 3 */
9 b/ m' ~) a2 Q# |% ]2 ? - }
复制代码 ' P( r+ O9 J# n6 A; }4 ]8 E( l: r
写了两个闪灯的程序,各自是各自的。看看会发生什么。把两个代码都下载到芯片内部。1 d X: G; j2 O3 ?/ p7 r
# x) k0 w9 J# _$ [结果是,非安全区的代码while(1)里面的代码正常执行,而安全区while(1)里面的代码没有正常执行。板卡红灯闪烁,而绿灯常亮(图片看不太出来)。6 j* O/ |' n4 O8 S% J# a
1 {- z5 v3 t5 W* k: p8 `" U2 ~原因也很简单,安全区代码是上电之后优先执行的,然后运行到NonSecure_Init,把非安全区堆栈初始化好,然后调用非安全区的复位函数(具体调用方式与逻辑请关注后续文章)。然后代码就跳转到非安全区了。
7 M- x/ E% }- w6 r/ Q1 v2 @
" B, v2 P; D3 N- H" F也就是说,两套代码,并不是真两个核,内部还是只有一个内核滴。* a8 n3 p& _/ d
|4 ]" ~6 E+ F4 E8 q |
你有测试过吗?M33只是为了安全在NVIC、MPU、SYSTICK等资源提供了双份,本身控制还在在切换安全区与非安全区运行实现的。核心资源只会提供一份的。
用过NXP的LPC55S69 里面有两个M33 ,理解错了
[md]嗯嗯,你说的这一颗芯片比较特殊,他虽然是双核M33,不过仅有第一个核是支持TrustZone的