首先需要使用STM32CubeProgrammer软件对芯片的模式进行配置。
3 c5 v, w1 w- g& z# N
0 F. X# g4 I( b0 u
连接上芯片后,选择OB选型卡,找到User Configuration
4 U& j" b2 `* q. W+ B8 i: J
4 ^) V& L! H' ~将其中的TZEN选项打上对号,使用Apply写入到芯片。
: J* D5 m" t2 r$ ]
9 y# E' W0 {& K+ n/ m5 k
1 d0 s9 q) o P/ V7 ?/ j3 p }5 d如图所示配置Secure Area 1与Secure Area 2选项,使用Apply写入到芯片。
0 P; b# U) z! S) S
; [. I& v6 Y0 p6 I, H$ `
2 M5 m% O* I3 m" f+ p3 g B4 N, W打开STM32CubeMX,找到STM32U585AI,这一次就要选择第二项开启TrustZone了。
E" `3 d2 X, K. s) d
3 l7 t- a2 b2 r% J4 K. |& ^
8 p& M+ J5 t* g; C2 ^ z看看新的外设界面,嗯,与之前大大不同啊。
0 Q) r8 S, r1 ? g0 f K* J
( y: y8 m5 ^$ ?5 t; U
# S" ^1 M% L8 B简单配一下时钟。
& T- x, v' Q7 V. J- j+ E% ~
2 M9 ~% R9 j. f7 P3 L/ M# S
. G: G- w. G2 o配一下SWD,这里就让他使用安全区域那边的初始化。
( v5 v# X3 q; i& b5 P
4 K# T" f9 h9 l: X$ ~& f
9 {' X+ B6 c5 b" ^8 E! l, [配一下IO,就是板子上的两个小灯,一个配置到安全区域、一个配置到非安全区域。
4 ?- G( p5 ]" i& P0 Y
9 n" Y, q/ W& o- `/ M; \" R% X N- k, [
生成代码,打开keil,嚯,两个工程啊(工程之间的区别以后再聊)。
* A5 K! s7 r3 P% X8 q
# c: w( I9 v' |; w3 g O. }, \+ L
$ M5 R* ]0 t7 ^" n4 T6 z右键可以切换选中工程。# y# u& b% r* a, x6 ]* c6 s, d
6 R) L" Z% M: N1 b" E
6 f$ A# X5 M. n' z看看代码" R! O* `7 C5 r. Q; S
安全区域的GPIO初始化8 m, T0 V- ~( D& K( r" H# }
- void MX_GPIO_Init(void)9 E! D1 X! x$ D! K, B' Q
- {
0 v( `1 d) `+ F5 g' c8 M - ! B# R; c5 c5 O' t8 f) l
- GPIO_InitTypeDef GPIO_InitStruct = {0};
! v0 s; U- L) S7 | - : E& [3 T8 V6 ]2 W6 `
- /* GPIO Ports Clock Enable */
6 a! Q, o& ?& S$ g - __HAL_RCC_GPIOA_CLK_ENABLE();
8 U: v, h; n% ]/ j - __HAL_RCC_GPIOH_CLK_ENABLE();
Z- L0 {: v- |( Q6 v - t. D6 T$ ~9 g" F1 _# `
- /*Configure GPIO pin Output Level */' w$ D* T# B2 B/ O2 `; c- P
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET);
+ x T' ?" ] @ w+ I6 Z
0 t. }6 r) |" F0 M; p- @6 }; o- /*IO attributes management functions */7 A. x- y# F- N0 `
- HAL_GPIO_ConfigPinAttributes(GPIOH, GPIO_PIN_6, GPIO_PIN_NSEC);
. s( r- O8 y3 V6 A4 H
( M. u% }; }6 i, {+ c$ w' M- /*Configure GPIO pin : PH7 */
# I0 H V$ Y* P# R+ T5 ~ - GPIO_InitStruct.Pin = GPIO_PIN_7;$ g' m _3 G: G* @1 c- N
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
D8 _* `' l" I# [+ v - GPIO_InitStruct.Pull = GPIO_NOPULL;* m2 Y: L4 D& T" i. T+ C* H3 u
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
' g) O# m4 n/ ?' ~; J' J A+ I/ e - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
+ r4 X9 }4 T7 U* E' j) Z" L
( B" o0 X' q! i: [- }
复制代码 6 U7 T" R; l% _
非安全区域的GPIO初始化9 ^7 g" i4 e; g% q" O. P6 ^3 e
- void MX_GPIO_Init(void)
o. x7 Z# [8 G3 n, ?6 s - {3 {3 L# O; k% O, v9 Q
* r9 j" b7 S6 c0 G! T- GPIO_InitTypeDef GPIO_InitStruct = {0};# o$ n2 U) u7 z6 h
- " C* \3 M# N, J" p8 r- B' Z
- /* GPIO Ports Clock Enable */! O# y! i) r# E# b9 o5 s
- __HAL_RCC_GPIOH_CLK_ENABLE();
4 j2 ~; o9 ^ y- a' q3 n. p
1 |0 r4 O: g! z# }- /*Configure GPIO pin Output Level */2 t0 ^* q; o! L2 }( s- p. I- \ ?
- HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_RESET);
. H/ b) C h: n% y - 3 c! u! u2 O( _6 z% f$ W
- /*Configure GPIO pin : PH6 */
) {+ w7 O7 e5 o6 t: b5 `2 F - GPIO_InitStruct.Pin = GPIO_PIN_6;' d5 m4 c' j, D, r% i
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;* `( r' z0 J1 ? v9 |
- GPIO_InitStruct.Pull = GPIO_NOPULL;
# y( W" j, r8 {5 h- ]$ X - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- c5 x. X. T7 V3 L( Y - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);8 N( @$ t6 E1 F- Y R) R7 F; c
- # j+ G+ ~9 ?6 r# B5 u
- }
复制代码 ! D9 ~1 N. k' Y, E+ N) e
区分还是很明显的。
6 i2 N& u2 N" H f1 A
. X8 [5 m7 q7 A接下来写写代码看看
$ A/ c9 y4 u! V! Y4 k5 x安全区域
2 c, }, K( W7 Z2 g- while (1)7 _3 W% y* s% N+ t3 B
- {3 |! ?/ n, w# W! u9 d0 F( L& w6 h
- HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_7);6 ?0 ~. N. R2 M; n
- HAL_Delay(1000);" M& @1 g# c% j$ ]' v
- /* USER CODE END WHILE */
. _2 g2 B( X% q2 A# S* K
- T& q/ y: G7 I% c9 W* m* P- /* USER CODE BEGIN 3 */
) h y# Y& V# z - }
复制代码
' ~7 A _6 R8 e% C& J+ d% w+ @4 Z8 T非安全区域
- l) U0 T' o- i- while (1)" I- X- v: t9 z+ `' u4 _3 i: C
- {
$ m# K9 Y6 E9 r# W1 Y3 r$ z - HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_6);
/ j6 ], P$ t8 A2 v: | - HAL_Delay(1000);
+ K! @2 a3 e0 y0 E9 G+ X! _ - /* USER CODE END WHILE */
3 S" b) ]) c; A6 J. S8 ~ - * C: f' v7 a3 q( M. k( X4 n
- /* USER CODE BEGIN 3 */% |% A6 }# `, V) ?8 J+ m
- }
复制代码
& |% ~& _3 q2 i6 H$ p; r写了两个闪灯的程序,各自是各自的。看看会发生什么。把两个代码都下载到芯片内部。. U( a' E$ F# K$ C
0 t3 r& Q. X2 m. b结果是,非安全区的代码while(1)里面的代码正常执行,而安全区while(1)里面的代码没有正常执行。板卡红灯闪烁,而绿灯常亮(图片看不太出来)。5 j+ n) s# `1 l! W/ @% z
) Y) T3 ~( j8 \6 x* A, f A
原因也很简单,安全区代码是上电之后优先执行的,然后运行到NonSecure_Init,把非安全区堆栈初始化好,然后调用非安全区的复位函数(具体调用方式与逻辑请关注后续文章)。然后代码就跳转到非安全区了。
. b3 e3 G! L$ }: A7 Q0 U1 P9 B
% {' t$ _; Z7 k1 x$ l也就是说,两套代码,并不是真两个核,内部还是只有一个内核滴。& }) C7 L A: o/ p; p2 |0 [- w, ?# _
4 C8 |1 {: m- P
|
你有测试过吗?M33只是为了安全在NVIC、MPU、SYSTICK等资源提供了双份,本身控制还在在切换安全区与非安全区运行实现的。核心资源只会提供一份的。8 e m8 j# b9 @8 f# i+ ~+ v4 R% [
用过NXP的LPC55S69 里面有两个M33 ,理解错了
<br /> <br />
嗯嗯,你说的这一颗芯片比较特殊,他虽然是双核M33,不过仅有第一个核是支持TrustZone的
/ d( z- ?3 V7 ^1 h& R0 C: g/ h. i