首先需要使用STM32CubeProgrammer软件对芯片的模式进行配置。
: Z! p2 u8 K! y( Y; H
# s% m* E2 w9 o$ R
连接上芯片后,选择OB选型卡,找到User Configuration
' \! L0 q: p- M9 E. _' [& J, l, D( V. Y0 d# r% r
将其中的TZEN选项打上对号,使用Apply写入到芯片。* R% c) ^4 |! B1 s9 z
* R7 ~0 t1 g' g
9 S0 P, g7 c2 U# h$ A- X! f( N
如图所示配置Secure Area 1与Secure Area 2选项,使用Apply写入到芯片。/ A* ~7 Q6 e6 A
$ Z3 T1 i1 l7 ~" o
$ B4 R5 \! u. h3 r1 V7 p- I打开STM32CubeMX,找到STM32U585AI,这一次就要选择第二项开启TrustZone了。7 K1 a+ e/ G8 V9 Z: z. E3 ?
% V# Q+ ?7 j% P# g3 R) f
2 r3 }3 J2 I0 [看看新的外设界面,嗯,与之前大大不同啊。
3 }; [7 r7 K" d' I. f9 Z
% z4 t: c, R: G$ B7 {: ^4 u8 {- k5 g' G5 ~3 d6 c- l
简单配一下时钟。9 _% \2 m3 w3 a! I
$ M: G. P1 ~3 c& i! e
7 x: R) _) t' [: A* [2 M: }配一下SWD,这里就让他使用安全区域那边的初始化。
+ m7 w0 h+ F% y$ |, {, u7 [
2 ^/ L4 C; s& m8 b d# |& d
# C$ u2 E( Z- p1 i# y& x% I配一下IO,就是板子上的两个小灯,一个配置到安全区域、一个配置到非安全区域。
; e# I. k" l8 E5 h; K$ @
7 x6 }- z# a1 `# b$ r6 K3 Q. D
/ E! A/ ^+ {9 ^5 F) K生成代码,打开keil,嚯,两个工程啊(工程之间的区别以后再聊)。$ d& U/ c y: j: d1 p
7 J, o& K6 ?4 Y0 X( g. @% a* x/ i& b, [. j2 F
右键可以切换选中工程。
% r- f- X, V* l/ B* y' N
& b. R* u) \ @, s' w9 \: F' E. A0 w
" h4 S( t8 k2 |: n1 @/ y看看代码
/ {1 }& f7 ~# X2 V1 h0 O8 T# [) t安全区域的GPIO初始化
0 \* q7 }4 }0 l- G2 K- void MX_GPIO_Init(void)2 Q3 d: q# g- v: i9 z9 H, F
- {
/ p! _8 K1 f! p |6 u - 7 b* d" ?3 R: B! F% H1 y4 F" u. ?
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- R! j* g. v& g- x! h
; |4 m9 \1 T8 ]0 _4 Y: ?1 u d- /* GPIO Ports Clock Enable */
: Z+ q9 `- P1 `0 t% J4 {- p - __HAL_RCC_GPIOA_CLK_ENABLE();6 m5 U! W" V$ i: D% i+ k
- __HAL_RCC_GPIOH_CLK_ENABLE();
/ a" N, j3 Q# }# m; @) {
+ k( R% H! O m4 j- /*Configure GPIO pin Output Level */
2 ~$ a! H) o. {" H: _ - HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET); x- E. G/ m J6 H
" V |) u) p4 F9 I- /*IO attributes management functions */9 R9 }. z5 x P7 ^5 O0 t( @
- HAL_GPIO_ConfigPinAttributes(GPIOH, GPIO_PIN_6, GPIO_PIN_NSEC);
& p' Z) r& Z2 I& z" h' i - : D6 \. [* @+ y* p1 @2 m+ O
- /*Configure GPIO pin : PH7 */1 ~6 c4 s8 k& j, b5 k
- GPIO_InitStruct.Pin = GPIO_PIN_7;
9 W& M# N- B* @6 m( S' P& n' d! c! _ - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;9 ^3 g/ c8 k) l% L) n# P" a2 Y* z
- GPIO_InitStruct.Pull = GPIO_NOPULL;
2 K; t; ^2 c' u3 s( A- W - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
* k' |1 D$ \, R - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);/ X f; J* t" I+ \, \
- . M7 b6 y B* v r
- }
复制代码
7 R1 o0 P1 W7 \7 o3 h非安全区域的GPIO初始化
( ~* t: i3 Y" f1 i! L- void MX_GPIO_Init(void)( Z Z7 J p4 d) x
- {
n; o( b/ z% X - 9 L. U {( F5 ~3 h4 s' V
- GPIO_InitTypeDef GPIO_InitStruct = {0};
2 k0 {9 m Q, l* o - 4 o: @+ g& h5 |' n5 J) n" v. p
- /* GPIO Ports Clock Enable */( Q7 ~# l; U+ P a w
- __HAL_RCC_GPIOH_CLK_ENABLE();
2 \& B1 m& p* J7 M% l! z. |$ }
; t+ m8 H) ~" M3 }- /*Configure GPIO pin Output Level */$ q, ]1 {/ E% E
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_RESET);
% V/ \% b. Z/ Z, W0 K2 G+ v$ @
+ j' ^+ a4 f3 s+ o6 o- /*Configure GPIO pin : PH6 */
! U# v6 O7 |" c4 b' D g - GPIO_InitStruct.Pin = GPIO_PIN_6;
8 j k9 A3 e& Z, T- T - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
W% w& Q# W" q0 M: `( ?, H - GPIO_InitStruct.Pull = GPIO_NOPULL;
/ @8 S4 K$ L8 H/ X( h8 o - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;1 [+ S$ `- `# h; W3 b/ T- V- U; c
- HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
y* b7 S+ E$ ?/ I - - q9 Q1 r$ O/ x: B5 {* O7 p
- }
复制代码 # n5 u5 I; Y# r1 i8 D
区分还是很明显的。
( P: \. ^7 f I. q# Y7 U; V2 `' B' h2 @- U" m+ {3 [6 ~
接下来写写代码看看; q9 O8 W2 ?7 T0 u# z, [% [. x
安全区域: C' D9 @; V, K! b8 {
- while (1)& i! \5 h+ W% J+ }; L4 X8 v
- {% N7 E/ k& f# T: h0 p# L
- HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_7);4 \7 b) L6 u, V- Z5 ], h" R
- HAL_Delay(1000);
! r5 E+ q. |8 w" }4 e- q! g - /* USER CODE END WHILE */: f% }- [# i9 z2 t6 U- C" \
: L' q. k$ F; K" @0 }* a0 L: s. b- /* USER CODE BEGIN 3 */5 e/ M' N0 E- q" c0 q+ P1 b' _
- }
复制代码 7 C6 w3 Z: R- K: `2 l2 g( k' e
非安全区域
) |2 o; y g5 w; W- while (1)8 m2 D+ _" Y: N) m$ j" p- ~
- {
) k7 \" S }* Z- y4 G0 z - HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_6);
/ _, b2 M3 d# n! A6 m3 c0 J* M7 m - HAL_Delay(1000);. D; i. [" Z7 Y |4 E2 @
- /* USER CODE END WHILE */$ t% Q, i6 K q+ p1 n
- / z) P6 f2 Z1 C! [% n
- /* USER CODE BEGIN 3 */
) H# C) t& r+ J' Y$ j8 ~ - }
复制代码 3 X% d7 G' _$ U3 t
写了两个闪灯的程序,各自是各自的。看看会发生什么。把两个代码都下载到芯片内部。
' R1 s# z: F S
& O; f: q, e' S结果是,非安全区的代码while(1)里面的代码正常执行,而安全区while(1)里面的代码没有正常执行。板卡红灯闪烁,而绿灯常亮(图片看不太出来)。
+ S7 q1 m! o9 |- n( Q9 V
! b# G) U* C3 e! u! ?
原因也很简单,安全区代码是上电之后优先执行的,然后运行到NonSecure_Init,把非安全区堆栈初始化好,然后调用非安全区的复位函数(具体调用方式与逻辑请关注后续文章)。然后代码就跳转到非安全区了。1 v/ K3 h$ W) {
; O4 M% z8 s) k" {) y
也就是说,两套代码,并不是真两个核,内部还是只有一个内核滴。4 i' D. n# J0 t6 ]- y
$ I) `" b/ e3 N( o- E# d |
你有测试过吗?M33只是为了安全在NVIC、MPU、SYSTICK等资源提供了双份,本身控制还在在切换安全区与非安全区运行实现的。核心资源只会提供一份的。
用过NXP的LPC55S69 里面有两个M33 ,理解错了
[md]嗯嗯,你说的这一颗芯片比较特殊,他虽然是双核M33,不过仅有第一个核是支持TrustZone的
3 H' J7 D1 }5 @3 k
; K; o. |; k* ^+ Q