首先需要使用STM32CubeProgrammer软件对芯片的模式进行配置。
: i% j. D. A+ o0 J; g V# R) b
% V! B) C( V8 l. P7 f: h连接上芯片后,选择OB选型卡,找到User Configuration
; T/ V0 v4 Y+ i
8 r5 \2 d9 w4 _2 t1 S7 o将其中的TZEN选项打上对号,使用Apply写入到芯片。
( n" _3 i: `6 Y9 M8 |( m( F
4 g2 p) G3 I6 @
9 [2 N* v; ` {* G5 Y" y如图所示配置Secure Area 1与Secure Area 2选项,使用Apply写入到芯片。
' {! o* j. E& z S! s7 R
) z- K7 S1 m; s! f" u: ] A
& L1 S3 A7 Y8 u" e5 o打开STM32CubeMX,找到STM32U585AI,这一次就要选择第二项开启TrustZone了。$ ?$ H* {; l0 I7 J; t; j
$ ?, Y6 ?+ ^3 _. i9 Z' O) r9 `5 L( W; B& @ \. e0 a
看看新的外设界面,嗯,与之前大大不同啊。
: |0 |* L7 M+ Q7 n
w4 D6 q- b5 I+ x
+ \* O' n- z4 s, j+ y简单配一下时钟。
4 J. }, e! M" ~1 G
" h! o6 k, f8 k2 V) T$ _& k7 h0 d8 Z' G; @5 w3 ?
配一下SWD,这里就让他使用安全区域那边的初始化。 `! X2 F: r t f N; t
% X+ E0 K& {. d3 Q3 m& S1 x" r1 t1 }
配一下IO,就是板子上的两个小灯,一个配置到安全区域、一个配置到非安全区域。2 I$ g0 v! H- O7 y- t
. Y( s* j, @$ e% i
) @ O3 I1 [ p7 `7 ~生成代码,打开keil,嚯,两个工程啊(工程之间的区别以后再聊)。; g5 H8 x+ X8 }6 D* h6 J- P2 \; T
( R1 ~3 G4 k% L1 [- @% a; b4 k z ^4 r, W% g1 x
右键可以切换选中工程。( ~, D; }) x4 u. W" L: O
" z( E% @6 \& {+ i- J6 \. k0 |7 N. P
看看代码, i6 m& X3 J) A6 r- i
安全区域的GPIO初始化- g+ i7 m4 h. \ B. ^7 p
- void MX_GPIO_Init(void)
1 k. n" [4 W; Z - {, d9 `/ W4 W% r! @1 D5 r( E
- 9 Q! r1 o0 N7 M1 F) m' K# r
- GPIO_InitTypeDef GPIO_InitStruct = {0};
! e9 \/ |$ Q6 p) J3 L. a
! e9 m+ c9 t* A+ w, h' l- /* GPIO Ports Clock Enable */- o+ s) A2 H, T" p$ t+ ~# g8 {
- __HAL_RCC_GPIOA_CLK_ENABLE();
3 R G$ ^3 J6 i4 q* f - __HAL_RCC_GPIOH_CLK_ENABLE();9 o+ E9 _/ ]# K' |4 F, \+ }$ n
- 9 \* b7 H$ K3 t" v6 \
- /*Configure GPIO pin Output Level */
8 p0 g# y, [' L" `4 p9 ^ - HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET);
- R5 L1 X* }/ C* K5 l- Z
5 z8 W! ~* B' m* d& ], C; g- /*IO attributes management functions */6 \5 G o1 @' i6 w: @
- HAL_GPIO_ConfigPinAttributes(GPIOH, GPIO_PIN_6, GPIO_PIN_NSEC);; a6 \* \& a Q
3 t: }1 J+ ~6 H+ C' @4 o- /*Configure GPIO pin : PH7 */& _4 `; V: R3 P7 c
- GPIO_InitStruct.Pin = GPIO_PIN_7;
0 k" D+ }8 c7 `, V' E+ d - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;3 g4 O7 X) O6 J
- GPIO_InitStruct.Pull = GPIO_NOPULL;
R$ H7 [ |7 Z! |! K! ~ - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
4 Z2 t" g& K0 Z' i6 ~! M2 q- d Q - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
( E2 l2 r, `, c+ }: Z# i2 A8 e
7 m- v4 E) h% W2 E$ B+ ?' {' c- }
复制代码 : Z9 B" O" L6 @1 f" P
非安全区域的GPIO初始化2 [& v+ o) Z2 `. F0 F
- void MX_GPIO_Init(void)
* z$ m a: A, d: f; M/ d' e5 p - {
% m4 X0 ^) p+ K$ k6 I - 2 t3 u5 Y' T$ O0 c% k% {2 F# t
- GPIO_InitTypeDef GPIO_InitStruct = {0};0 e8 g2 f8 i: P- k
- B1 ~/ t- |$ x# \ U- /* GPIO Ports Clock Enable */- O$ Q0 O* p# e# K
- __HAL_RCC_GPIOH_CLK_ENABLE();
9 a& Q9 J6 N' w* R! O6 E
) b& y# @2 z3 f0 H7 k% `- /*Configure GPIO pin Output Level */
" c+ \& A J" p# g* y- | - HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_RESET);: a1 S( n9 Q( p, F
( G6 ]4 s! T4 b3 f- /*Configure GPIO pin : PH6 */
1 x7 U2 d" T {; ~7 _ - GPIO_InitStruct.Pin = GPIO_PIN_6;
$ O: z6 {$ Q+ J2 d5 t; K3 K' y - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
0 T: P1 L+ [. `/ w+ ^/ t f, C - GPIO_InitStruct.Pull = GPIO_NOPULL;! [0 T& h' _! Q
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;( w( }$ H8 k3 i2 V+ H
- HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
5 D) L; C% A# D, x L7 R
, c7 H T9 H9 [( D0 i" C- }
复制代码 / ?. Z$ o D$ C! W$ P' V: j3 p. r
区分还是很明显的。1 D1 {4 J7 P6 H, w3 B
& L, r5 ^ \1 W3 P接下来写写代码看看( I$ @6 X) v7 e( L9 ^9 I& |
安全区域* U1 N( T. y( e- z- w
- while (1)
% ^3 Q# l9 t5 P' J( V' n+ K3 {2 F - {7 _+ F9 j; R8 V& F: z4 |! p
- HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_7);
+ m" w. l% X$ U2 L3 H5 @ - HAL_Delay(1000);& [0 f: _/ H. `; A) v
- /* USER CODE END WHILE */
! b" a4 C- U# r$ E: ~ - ; o. U8 l/ O' ^. t* y1 M9 N
- /* USER CODE BEGIN 3 */4 Z3 z M- r {
- }
复制代码 # a8 n) j* R+ w ^8 W7 {6 w# v0 X
非安全区域4 h0 s& G6 v2 P( T6 }! n
- while (1)# }2 @1 H" R. S; e* Y
- {
- q- e- }/ @" c& o V4 V - HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_6);4 Z3 K' |4 ]2 Y# M- |. n( |
- HAL_Delay(1000);
# v# c' N. n# |5 i: g2 K; ? - /* USER CODE END WHILE */: E1 @. H# W& U5 P
- % I. D7 F; _1 W4 M8 W: P
- /* USER CODE BEGIN 3 */4 Y0 v0 M/ d1 [+ O& O% y/ h
- }
复制代码
; H8 P8 A( N! m& m c2 w写了两个闪灯的程序,各自是各自的。看看会发生什么。把两个代码都下载到芯片内部。
1 Q5 @0 Q* X/ t2 V' \0 o
( l3 v) D( J3 l结果是,非安全区的代码while(1)里面的代码正常执行,而安全区while(1)里面的代码没有正常执行。板卡红灯闪烁,而绿灯常亮(图片看不太出来)。
9 z: F, h# {" ]8 s* W7 g# P
0 |1 ~& K7 V4 p( l- j" E
原因也很简单,安全区代码是上电之后优先执行的,然后运行到NonSecure_Init,把非安全区堆栈初始化好,然后调用非安全区的复位函数(具体调用方式与逻辑请关注后续文章)。然后代码就跳转到非安全区了。
- V, j# Q, n! w, L# Y- c" S0 U' o
! s( `+ l7 L, Z也就是说,两套代码,并不是真两个核,内部还是只有一个内核滴。; X: }% S/ m2 f. l
/ c3 t2 X2 b8 @7 A# q$ v
|
你有测试过吗?M33只是为了安全在NVIC、MPU、SYSTICK等资源提供了双份,本身控制还在在切换安全区与非安全区运行实现的。核心资源只会提供一份的。
用过NXP的LPC55S69 里面有两个M33 ,理解错了
[md]嗯嗯,你说的这一颗芯片比较特殊,他虽然是双核M33,不过仅有第一个核是支持TrustZone的
* _+ \3 ]4 ]" h. ^! Y# D
! D. A H% c" J) v7 J6 Y7 g& B g3 g