首先需要使用STM32CubeProgrammer软件对芯片的模式进行配置。
3 h4 B- f1 v7 Q; k
1 B! O1 ?) x6 x8 V; `
连接上芯片后,选择OB选型卡,找到User Configuration
) M g9 N4 @2 b
( K) B) f }" p* V将其中的TZEN选项打上对号,使用Apply写入到芯片。3 t0 w# u& b& e% v/ ?6 I# \
' G! `' P8 U% H) N
: g6 g0 f/ y( a: l) n
如图所示配置Secure Area 1与Secure Area 2选项,使用Apply写入到芯片。5 r. j! ?, f9 F# ]0 H
% [7 q) I' F; W4 Q+ I; Q
: A( h9 \! i9 f7 l: R& D3 K; L0 m打开STM32CubeMX,找到STM32U585AI,这一次就要选择第二项开启TrustZone了。
6 M% N& m! M+ v/ o2 o0 r
7 }* k( W5 I+ j/ [3 E. ~6 b' Y+ I. @- I/ d( H0 j
看看新的外设界面,嗯,与之前大大不同啊。
+ C" _5 ]8 d% n5 j
' {9 e5 @& V* ^) |: e$ C
( I: {, u2 Q% g# T1 E简单配一下时钟。
8 I2 i! \9 L# u* L" L) H" g
f& H8 d! k# e( M9 A: D' m) ~% t( j
配一下SWD,这里就让他使用安全区域那边的初始化。
3 v$ e: o/ ? u/ y
: [4 v+ r+ l2 a1 g5 C0 C' b# V- G
: W4 ^, s9 }8 }" ^0 I3 n配一下IO,就是板子上的两个小灯,一个配置到安全区域、一个配置到非安全区域。/ @+ \' h( k1 q$ I
7 a% j) _1 W; Q ^0 T
8 @1 P$ \: s; N8 s生成代码,打开keil,嚯,两个工程啊(工程之间的区别以后再聊)。6 I2 l3 I: g5 \: I4 q
0 w' ^. b: Z5 y+ S6 B( c& X& Y: K z! V0 f1 }& j
右键可以切换选中工程。
' W3 u/ f+ P$ N
. i( I9 [2 R# w! q: Q4 f x) K& Z9 Q3 j5 q4 A) z" S3 d
看看代码
/ e1 P* i7 \, @2 O$ Z/ s( F H$ A安全区域的GPIO初始化
) L' w. V. E6 Z( O1 H- void MX_GPIO_Init(void)' Y3 v8 M$ R7 V* V
- {
& c- S9 p8 F% r& Q& `" }3 ]& X - # z- F2 g) c, V1 o$ m+ K4 e) {4 f$ @
- GPIO_InitTypeDef GPIO_InitStruct = {0};" m: H6 r1 [. O% O" \+ ]- E
- 9 t6 U$ q9 M& G! j- O" f
- /* GPIO Ports Clock Enable */
) R) @( D3 o/ N& }* n! B' V - __HAL_RCC_GPIOA_CLK_ENABLE();
" h8 [6 p( y- p$ N7 l" @$ q# q( k# B - __HAL_RCC_GPIOH_CLK_ENABLE();9 n+ {. V& p0 E
- 3 p6 ]7 U9 G4 @- F
- /*Configure GPIO pin Output Level */+ F& d7 N* q v% Z# v; ~
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET);
6 b4 \; C) M! v) i
8 o0 m+ D- `6 Y- B2 i$ a- /*IO attributes management functions */
$ P( {* H, a4 A: {6 x% Z' h - HAL_GPIO_ConfigPinAttributes(GPIOH, GPIO_PIN_6, GPIO_PIN_NSEC);
! W/ o9 f5 n+ q. O! V) g' i9 |0 J
% l' y. U( {2 M8 P& k4 d3 C. K- /*Configure GPIO pin : PH7 */5 n- f+ ^, }& A7 [; P
- GPIO_InitStruct.Pin = GPIO_PIN_7;
- z. e2 X% V; K9 j4 y - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
2 J' h9 Q! H- v o$ {* D+ M: P - GPIO_InitStruct.Pull = GPIO_NOPULL;
4 h0 V' b+ {/ V; G4 m3 Q* ~ I - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ Y$ v0 j, N D& y" k - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
7 m+ @' @) j6 _, y* u
~' d! k( e9 E* x- }
复制代码
1 U. C9 J: |# R4 Y- G5 A) ~7 A% v* g非安全区域的GPIO初始化4 Q* k' I. l, f2 l2 T: _
- void MX_GPIO_Init(void)- b! A9 J6 ?3 H) @( S8 g6 H
- {
$ ]5 j, r! C- V2 Q* N: s- R0 {
% V$ u1 W: i2 b# h3 N7 p- GPIO_InitTypeDef GPIO_InitStruct = {0};; e- Y, }! ]# E' Y- Z6 c, g
) u3 K3 c0 O5 {6 U- /* GPIO Ports Clock Enable */
$ U' T/ r/ d) z8 i, r- o' M8 {. @ - __HAL_RCC_GPIOH_CLK_ENABLE();
0 e# \- k) G. G8 d/ X. |/ H% }
' q" H; O+ P# w; b: z- ^4 E- /*Configure GPIO pin Output Level */ R5 G8 s! |$ Z: g; a
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_RESET);
3 d8 a9 g6 J3 G2 o - ; O) r3 D3 m e+ {8 N% R
- /*Configure GPIO pin : PH6 */8 q \. o! ]7 i, I$ v
- GPIO_InitStruct.Pin = GPIO_PIN_6;
- [" B) a- Z9 d2 ]6 F) J0 O: l - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;1 n5 Z0 h" U4 g/ `& v
- GPIO_InitStruct.Pull = GPIO_NOPULL;
! S6 c! U0 Q1 _6 y2 x - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
2 z7 B' f$ w$ Z1 S* ^7 s% @( m2 L5 ] - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
( E) |5 D l7 Z; s' }$ e2 \
( [: E+ c$ ~2 c t( T6 H1 k- }
复制代码
" {' u4 F" R3 p* W区分还是很明显的。6 I1 Q) U: |2 z7 ]2 g4 F+ y" w
% M/ e) R# b: W接下来写写代码看看
; v( r1 O" S0 u安全区域! a+ [, p$ s+ S+ o( P
- while (1)# \# L% g8 r: ]
- {7 D$ n( e) I1 h; h1 d
- HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_7);, Y S8 Y0 a5 b0 R
- HAL_Delay(1000);7 V% O# h- ?( s5 S
- /* USER CODE END WHILE */
% Z# q3 Q8 J0 ^2 V. H8 I- v
, k% c4 i. G3 z8 G/ W6 R+ D1 D0 K- /* USER CODE BEGIN 3 */
1 @$ s( ?1 u! o9 ~2 Z* B+ l - }
复制代码 + `; U d2 O" Q
非安全区域3 N. e& X- j' J, \0 p3 T
- while (1)! L+ m' E5 [& [9 i* x
- {
1 Z7 o# A2 ~( o8 G( Y9 h6 x - HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_6);
7 o) G# }( s0 l# i4 j8 q1 w - HAL_Delay(1000);9 i- G" j5 g. K4 k
- /* USER CODE END WHILE */
* J+ _" b5 r3 o - 0 {7 ^1 o& O! g4 U
- /* USER CODE BEGIN 3 */
2 z7 u, F8 |) b) d# B* y - }
复制代码
5 D* B0 S$ S) a- h' Q, J1 M写了两个闪灯的程序,各自是各自的。看看会发生什么。把两个代码都下载到芯片内部。
/ a0 P+ S1 }; R g; C3 z8 `
% ]# w3 a' K5 U3 ?" s: `结果是,非安全区的代码while(1)里面的代码正常执行,而安全区while(1)里面的代码没有正常执行。板卡红灯闪烁,而绿灯常亮(图片看不太出来)。
( |# q) F( [: v: ^
( h& r6 I4 o( p
原因也很简单,安全区代码是上电之后优先执行的,然后运行到NonSecure_Init,把非安全区堆栈初始化好,然后调用非安全区的复位函数(具体调用方式与逻辑请关注后续文章)。然后代码就跳转到非安全区了。/ P* }$ } K6 E
4 Y+ ~) S8 R3 b/ {
也就是说,两套代码,并不是真两个核,内部还是只有一个内核滴。) I3 O6 n& ^3 V# J7 ^
0 m6 S( M$ R# R1 p0 }8 t2 G# v
|
你有测试过吗?M33只是为了安全在NVIC、MPU、SYSTICK等资源提供了双份,本身控制还在在切换安全区与非安全区运行实现的。核心资源只会提供一份的。
4 X) D% d- `9 |- m. c2 A% A
用过NXP的LPC55S69 里面有两个M33 ,理解错了
[md]嗯嗯,你说的这一颗芯片比较特殊,他虽然是双核M33,不过仅有第一个核是支持TrustZone的