你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

实战经验 | TrustZone应用中串口通信的DMA传输失败问题

[复制链接]
STMCU-管管 发布时间:2025-4-25 09:44
012 ~5 C0 {( z1 ^% h- D
问题描述2 m5 l7 h( v% B3 H. [
客户要在STM32U5 SBSFU的基础上开发自己的项目,SBSFU由三个工程组成,Boot,APP,Loader。其中的Boot工程由开源项目MCU boot移植而来,它负责整个系统的安全启动以及升级部分。客户想在此基础上新增一个串口通信,不使用DMA模式的情况下,串口能够正常工作,但切换到DMA模式的时候就不正常了,PC端连接串口发送引脚,显示接收的数据全为0。如下图所示:
9 s& n7 I  x  r% G$ l
14.png
▲ 图1 SBSFU Boot运行的置log信息及串口收到的数据全为0
02$ |, e% n% g, x: `  i9 K  m) g
问题分析及定位
7 k0 M- _8 O- `# \( i. k! d  `此问题看起来应该是DMA哪里配置出了问题。为了快速找到问题,不如先从STM32CubeMx重新生成一个基于trustzone的USART且带DMA的测试工程,等到测试工程测试通过后,直接移植到boot工程内不就完了?
; @6 P, [6 a$ p于是我直接使用STM32CubeMx新建一个工程,使用LPUART1外设PA2,PA3引脚。并分配其为M33 Secure。配置115200 bps。1+8+1数据格式。
! x  D# h0 G) t" U. w
15.png
▲ 图2 串口基本配置
5 A( m8 o) R! N& Z0 j) r1 l4 X

* a5 B$ A, i# M4 }4 K在其DMA配置页面下,点Go to GPDMA1,切换到GPDMA1配置:在上面Mode页面下激活通道0和通道1,并将通道0分配给LPUSART1_TX:
% c2 L2 ?% H: O( h2 W5 d+ x9 N
16.png
▲ 图3 通道0分配给串口发送
4 P8 j& {/ u5 ?6 Y8 f- e% ]# m

( u! E: C& _" w. ~4 B0 V
17.png
▲ 图4 通道1分配给串口接收
在security页面下配置通道,目标和源均为“secure”:# _8 Q3 V' M% t( f/ x
18.png
▲ 图5 DMA通道的安全属性配置
. g9 |1 U  {' i" u7 @& S

- ^) R' H6 J5 m' u. C  h然后就是配置内存了。在ld文件中配置使用的内存是SRAM1:7 z* C$ J9 W# Y8 S4 T: C3 I! Y/ l, ?
  1. /* Memories definition */$ \; M' A. X% j- ?# ?/ l+ s
  2. MEMORY
    9 @4 t( B3 ]. R- U. U
  3. {# z& {, b8 y8 Z8 n, B6 e
  4. RAM (xrw)  : ORIGIN = 0x30000000, LENGTH = 192K     2 U9 v4 _/ Y  t" x
  5. /* Memory is divided. Actual start is 0x30000000 and actual length is 768K */; U/ p" t' W- L/ v$ M" w1 B9 U7 O3 ^* K
  6. SRAM4 (xrw)    : ORIGIN = 0x38000000, LENGTH = 16K; T' q, U2 M6 T" e& k7 K, x
  7. FLASH (rx)   : ORIGIN = 0x0C006000, LENGTH = 500K   0 B5 L' q9 k/ @- T* s3 ?: z
  8. /* Memory is divided.) c4 w  F9 V* j) t
  9. Actual start is 0x0C000000 and actual length is 2048K */
    % M3 C2 F% g( E& y( u
  10. FLASH_NSC (rx) : ORIGIN = 0x0C0FE000, LENGTH = 8K$ t" O& X0 X- A) h
  11. /* Non-Secure Call-able region*/3 i7 [% S! e4 t, h0 V
  12. }
复制代码

/ Q0 ~; G- L# u  X. B+ \然后在GTZC中配置MPCBB1:6 M* J0 u- ]' v

7 Q& ~3 O4 Y3 Y# p. k0 n9 S

8 U- H2 [: `' c. y' q
19.png
▲ 图 6 GTZC下MPCBB1配置
+ c8 e5 T* H' _8 k

) S; w7 t4 i4 u在MPCBB1中将192KB的SRAM1配置为全部安全。
/ ^% C8 d8 h. ?  k* J! c7 M然后生成测试工程。0 Y9 H% J: W- e! x4 h/ H
为了让测试代码跟boot工程保护一致,我们也让测试工程从0x0C006000,见之前ld文件中FLASH的定义范围。9 p/ m- L% \4 I# k; \( ~
还需要在修改向量偏移位置到0x6000处:
5 z; y7 e9 F: G( _4 C#define VECT_TAB_OFFSET  0x00006000UL2 b& f9 Q5 s/ T& u4 ^; S
然后在main函数处增加测试代码:
2 C! f* w9 z2 s! g
  1. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
    $ Z) O6 O8 A4 [% K) b$ ?
  2. {  i4 X  t! k. x3 Z- y
  3. txPendingFlag =0;
    2 }$ \4 C  m8 J4 q# g
  4. }4 Y: p" g1 k- |7 v
  5. int main(void)% j) Q! m( n; M* f* I/ d
  6. {
    6 S* |9 k' N% z( ?  v* L# y& G
  7. //…( V1 e/ }1 L% Q: \& v6 G8 F
  8. while (1)
    % W" }) t, d& C" J6 a2 p
  9. {  
    8 {$ _) E. D9 i% ]8 ]+ W$ }
  10. if(txPendingFlag==0), K: ]: A, p& J3 h7 U
  11.    {/ g# Z6 @& V5 T- d7 \
  12.     txPendingFlag =1;
    9 Q' L7 m' ?/ u& u3 x3 r+ U  `
  13. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)aTxBuffer, sizeof(aTxBuffer));
    , q$ o8 N7 Z' b# y1 V8 o+ x, d
  14.    }   $ H5 ]) Y* j3 f8 a, u& X' X
  15.   HAL_Delay(100);
    ' C# N  w9 ~7 T# t, J1 z; ^
  16. }' v0 o' H* b6 Y) ~' @
  17. //…+ C6 m) H. Y6 X7 \
  18. }
复制代码
让主函数周期性地从串口发送数据。为了让程序正常运行,需要使用STM32CubeProgrammer修改MCU从0x0C00 6000地址启动(主要为了与SBSFU_Boot保持一致):" P4 R8 X* s* @3 y
20.png
▲ 图7 让MCU从0x0C00 6000地址启动
- ^0 [6 e2 ~8 @. ^/ R

4 K! g/ x. ]$ m( e. Z1 }, H3 r& C编译并烧录程序,并让程序运行起来后,使用示波器测量PA2引脚的波形,结果一切正常。
$ O2 N2 b2 K* `于是接下来移植到SBSFU_Boot工程。
6 \6 k0 T) a- [& M由于在测试工程中已经测试OK,按理说,移植到boot工程后,带DMA的串口也应该发送正常。但实际测试却是跟客户所描述一样,发送内容全为0!
$ \+ _% C3 ~- e; v4 c6 Z- S' E问题出在哪里?5 ^1 m1 ?  C! B( v/ p7 |
仔细对比两者的差别,发现测试工程是有配置GTZC。MPCBB1的,对应SRAM1,但是Boot工程,它使用的是SRAM2,代码并没有配置MPCBB2,其初始化函数:* s: F& w- N' x6 ?1 G$ f5 E+ T
  1. static void  gtzc_init_cfg(void)+ t$ y. [2 D3 Y# }4 h. w1 |
  2. {
    , I0 y4 Q$ L5 G" ~
  3. __HAL_RCC_GTZC1_CLK_ENABLE();) ?7 [0 t0 X- m, K/ o
  4. #ifdef TFM_ERROR_HANDLER_NON_SECURE
    ) ~% S  K+ z* @% f# D2 P+ P
  5. /*  unsecure only one block in SRAM1 */7 S  c8 q" ^* ?. }+ U
  6. GTZC_MPCBB1_S->SECCFGR[0] = 0xfffffffe;7 Q' z& l- C. ]
  7. #endif
    4 K: D: G/ b; n+ P' v% R. H6 k
  8. /*  TFM_ERROR_HANDLER_NON_SECURE *// g1 {+ _8 v* N5 S7 _8 Z
  9. }
复制代码
6 U7 p, J1 p8 |* r
在宏TFM_ERROR_HANDLE_NON_SECURE打开的情况下也只会配置MPCBB1,并没有配置MPCBB2。因此,SRAM的安全及特权属性应该是保留为默认属性,那么其默认属性是怎么定义的呢?
3 a2 Y/ _  ~$ r在参考手册RM0456 Rev 4第5.4.6节中,我们找到如下内容:; q8 h. Y7 j# ~8 F& N% V- ]
21.png
▲ 图 8 SRAM的默认属性定义
( ]* p) z# k# j8 b; J5 y8 S4 O
  S) O9 o# l" f& n, @
这说明,在默认情况下(TZEN),SRAM2的默认属性是Secure+Privieged的。之前在测试代码对应的STM32CubeMx配置中,我们配置了通道,目标及源为安全属性,但并没有配置其特权属性。在CubeMx中其默认为非特权,见之前的图5所示。也就是说,我们需要将通道也配置成特权属性,于是直接修改代码:  l- |9 R3 U$ p3 S* F
  1. //…
    ( `0 u$ \" i6 n. ~
  2. __HAL_LINKDMA(huart, hdmarx, handle_GPDMA1_Channel1);
    * \) u" M2 z: G0 q' X# A
  3. if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel1,) ]$ \# l8 J6 @5 x. v
  4. DMA_CHANNEL_PRIV|DMA_CHANNEL_SEC|DMA_CHANNEL_SRC_SEC|DMA_CHANNEL_DEST_S
    6 z$ `1 `, z1 O; Z( X6 I$ a
  5. EC) != HAL_OK)
    " V4 {: o1 F0 e3 G0 ~5 p
  6. {
    : }; \; M# p- L# E
  7. Error_Handler();( Z7 y0 z- a6 D( z2 n* S: E+ U! u
  8. }
    $ O+ [4 S8 x6 u# W
  9. //…
    ' `* f! j$ e2 ]% r9 T
  10. __HAL_LINKDMA(huart, hdmatx, handle_GPDMA1_Channel0);% _0 x& t  a& W
  11. if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0,- k* e" F- P4 J8 F7 ~
  12. DMA_CHANNEL_PRIV|DMA_CHANNEL_SEC|DMA_CHANNEL_SRC_SEC|DMA_CHANNEL_DEST_S1 d2 @  K# J, z2 r& ~( h9 N! j4 |
  13. EC) != HAL_OK); G! k/ R/ U9 I1 Q3 i
  14. {
    ; ~" R$ v4 a& Z# `
  15. Error_Handler();; r4 i- c# ]) g- f5 j4 j0 q% v
  16. }! j4 k' o" ~- u; l
  17. //…
复制代码
) x9 B8 Z$ S. b" G( f, W
如上代码所示,在代码中配置DMA通道处(红色标记处),将其改为配置特权属性。然后编译后再次测试,这次则能正常发送数据了:/ j. W9 J! v; O7 {+ p2 ^
22.png
▲ 图 9 串口正常发送数据
6 Y+ ^5 y% c. R3 U
( n6 R4 w1 B8 Z3 a: B; g
03
1 e2 l! d5 Z/ v. f- H7 w小结
' g9 @0 k4 b# j1 L7 m6 w在trustzone使能的情况下,MCU内的资源,若代码中没有显式设置的情况下,要注意其默认状态,内部flash,SRAM,片外存储映射区域以及GPIO引脚均为安全的,且特权,Securable外设基本都是非安全的,在STM32U5安全培训的一页PPT中有做总结,如下图所示:; |( M0 |, m' ~* U6 M$ ?# K
23.png
本文所描述的问题,正是由于MPCBB2(Boot工程对应的RAM)没有配置,其默认为Secure+Prileged属性,但DMA默认属性为NonSecre+NonPrileged。代码中只配置DMA通道为Secure属性,并没有配置其为Prileged,因此导致其访问SRAM2时失败,这也就是为什么发送内容全为0的原因了。这也提醒我们,在开发trustzone相关的项目时,对各个资源的安全属性配置一定要小心。8 a/ S2 \+ y; ?

, b  y2 ^7 g8 Z' ?
收藏 评论0 发布时间:2025-4-25 09:44

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版