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

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

[复制链接]
STMCU-管管 发布时间:2025-4-25 09:44
010 K, p) @# \5 [3 O
问题描述# m1 V+ b. o) s; O  p8 i
客户要在STM32U5 SBSFU的基础上开发自己的项目,SBSFU由三个工程组成,Boot,APP,Loader。其中的Boot工程由开源项目MCU boot移植而来,它负责整个系统的安全启动以及升级部分。客户想在此基础上新增一个串口通信,不使用DMA模式的情况下,串口能够正常工作,但切换到DMA模式的时候就不正常了,PC端连接串口发送引脚,显示接收的数据全为0。如下图所示:
, A5 Z  j4 G4 s: U, B( G- ~$ l
14.png
▲ 图1 SBSFU Boot运行的置log信息及串口收到的数据全为0
026 m8 K0 Y! y- n% L$ Q4 G
问题分析及定位4 @, f' m& b( S- m4 W. p" `
此问题看起来应该是DMA哪里配置出了问题。为了快速找到问题,不如先从STM32CubeMx重新生成一个基于trustzone的USART且带DMA的测试工程,等到测试工程测试通过后,直接移植到boot工程内不就完了?
. p- n2 ?; n2 P6 g) y7 H于是我直接使用STM32CubeMx新建一个工程,使用LPUART1外设PA2,PA3引脚。并分配其为M33 Secure。配置115200 bps。1+8+1数据格式。
0 L' A0 f; }- ]4 ~& r5 E
15.png
▲ 图2 串口基本配置

  h/ g6 ^/ [% B6 b, x. D/ R
, n  D/ L3 I  `1 H
在其DMA配置页面下,点Go to GPDMA1,切换到GPDMA1配置:在上面Mode页面下激活通道0和通道1,并将通道0分配给LPUSART1_TX:( d6 P+ M+ c' f
16.png
▲ 图3 通道0分配给串口发送
- M) s9 e3 K2 F# H5 L; w5 u( |( Z

& F' G2 {; J( R, u3 f
17.png
▲ 图4 通道1分配给串口接收
在security页面下配置通道,目标和源均为“secure”:
* M) l- s! T/ l
18.png
▲ 图5 DMA通道的安全属性配置
& I' e* w2 i9 H* d2 c3 U
  l/ v5 d0 K6 S7 P8 q
然后就是配置内存了。在ld文件中配置使用的内存是SRAM1:
2 q% k# e0 P) D/ f! Q* R6 t! z
  1. /* Memories definition */
    & o0 l- m3 k7 o) f4 w. h3 ^
  2. MEMORY- N* u5 I) l& u. t
  3. {' y# l' {( h( h: e, _4 b, h6 f# R! B
  4. RAM (xrw)  : ORIGIN = 0x30000000, LENGTH = 192K     . i, H8 v( o: f* }/ e( v! p
  5. /* Memory is divided. Actual start is 0x30000000 and actual length is 768K */  P) D; O+ K; V* _3 i2 J0 Q
  6. SRAM4 (xrw)    : ORIGIN = 0x38000000, LENGTH = 16K
    % v( a7 O6 A2 X/ J) G) C
  7. FLASH (rx)   : ORIGIN = 0x0C006000, LENGTH = 500K   
    " R+ ~1 a5 y4 |" ?: @6 `
  8. /* Memory is divided.
    1 Q# M. \: M! h: G9 }% j
  9. Actual start is 0x0C000000 and actual length is 2048K */
    $ @0 f1 p$ ?* b0 g5 }: ^
  10. FLASH_NSC (rx) : ORIGIN = 0x0C0FE000, LENGTH = 8K
    ' E0 d5 h7 `+ v2 C0 J
  11. /* Non-Secure Call-able region*/
    ) f1 J( e+ r/ s' z
  12. }
复制代码

) W' p8 H. l- {! I' h6 |* P. ]然后在GTZC中配置MPCBB1:. W9 ?0 I* I$ r! x% @
- \, l; H- T6 A
1 `  T3 J! a% v
19.png
▲ 图 6 GTZC下MPCBB1配置
% M' t% _& h6 Z1 Q  U7 W

, C  f/ R& n& ?0 _在MPCBB1中将192KB的SRAM1配置为全部安全。
; H: C' ^1 ]: N1 o1 @然后生成测试工程。
  @, J! V: ^8 `; W, P为了让测试代码跟boot工程保护一致,我们也让测试工程从0x0C006000,见之前ld文件中FLASH的定义范围。
4 u' c8 |0 c* r6 ?5 H, Y还需要在修改向量偏移位置到0x6000处:
8 K- ^+ x0 w4 x$ W# ?2 U8 Z& T#define VECT_TAB_OFFSET  0x00006000UL
9 s% |) [+ X7 c7 A然后在main函数处增加测试代码:+ W6 X& z: ]4 _" z  o) t0 w
  1. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
    2 `/ V% d. t# g5 a5 B9 \
  2. {! y+ k) R: X4 B8 |6 R
  3. txPendingFlag =0;, {- f( [# F% F3 s0 ], _2 x5 B
  4. }
    + h- f% U3 a8 m5 O
  5. int main(void)
    5 k* L+ \, |  O$ b1 ]$ P8 {
  6. {
    + V: |) U! j* C$ y' y, r: n2 d
  7. //…  P  h+ c0 a' ]4 {) E
  8. while (1), X7 D4 D: s& ?( r; W/ d! |
  9. {  
    , o7 ?# j4 H! S% F+ k
  10. if(txPendingFlag==0)
    ; F& e$ M* u5 Z* T; \
  11.    {) D% w) f8 H* G! `/ x( I
  12.     txPendingFlag =1;  [  [6 Q# H9 ]" D: a8 `
  13. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)aTxBuffer, sizeof(aTxBuffer));
    ! E- c  k) |/ [5 `( t4 O% S/ k
  14.    }   & T" O* G( G/ w
  15.   HAL_Delay(100);) c2 H# G! o  o
  16. }
    / ^* v$ Q% F9 I$ J5 P0 f
  17. //…" [, C. M9 C) R' A8 ?+ i3 I
  18. }
复制代码
让主函数周期性地从串口发送数据。为了让程序正常运行,需要使用STM32CubeProgrammer修改MCU从0x0C00 6000地址启动(主要为了与SBSFU_Boot保持一致):
! ]$ C) S8 [- Z: h0 M6 v1 s
20.png
▲ 图7 让MCU从0x0C00 6000地址启动

1 q! L) z- p2 ?9 ^

) G% W* Q) U5 U$ ?' R: Z! O编译并烧录程序,并让程序运行起来后,使用示波器测量PA2引脚的波形,结果一切正常。
8 q  X! {8 |0 `5 H  U3 d于是接下来移植到SBSFU_Boot工程。
4 f4 F1 T% v# E0 s% O由于在测试工程中已经测试OK,按理说,移植到boot工程后,带DMA的串口也应该发送正常。但实际测试却是跟客户所描述一样,发送内容全为0!
4 k4 X7 [6 w6 E: o# q, o$ s问题出在哪里?
# B" R- B0 `/ Z% T仔细对比两者的差别,发现测试工程是有配置GTZC。MPCBB1的,对应SRAM1,但是Boot工程,它使用的是SRAM2,代码并没有配置MPCBB2,其初始化函数:
8 z0 Z8 h5 F0 ]* S0 p
  1. static void  gtzc_init_cfg(void)9 i0 w) z0 H1 C
  2. {9 \% F5 v; s" p% g" A
  3. __HAL_RCC_GTZC1_CLK_ENABLE();
    1 x" K5 a4 r- J
  4. #ifdef TFM_ERROR_HANDLER_NON_SECURE/ u4 Y7 d* Z, i6 a
  5. /*  unsecure only one block in SRAM1 */
    4 @& ~% j9 `) g( G: J" g7 t/ y
  6. GTZC_MPCBB1_S->SECCFGR[0] = 0xfffffffe;+ L1 o, p/ O1 R& e
  7. #endif4 Q0 W! X# w! H" L, ?# e- ~' S
  8. /*  TFM_ERROR_HANDLER_NON_SECURE */4 S% l1 o5 x  b& b+ k: }; P
  9. }
复制代码

! H' W2 P! V5 \; x; n" l- H" k6 f; P在宏TFM_ERROR_HANDLE_NON_SECURE打开的情况下也只会配置MPCBB1,并没有配置MPCBB2。因此,SRAM的安全及特权属性应该是保留为默认属性,那么其默认属性是怎么定义的呢?5 X3 B! `  Z* g* `5 m
在参考手册RM0456 Rev 4第5.4.6节中,我们找到如下内容:
2 \( H& Y9 F: q7 x
21.png
▲ 图 8 SRAM的默认属性定义

/ }" \: m% j  x5 b
1 `7 e) J. i( {" a9 v
这说明,在默认情况下(TZEN),SRAM2的默认属性是Secure+Privieged的。之前在测试代码对应的STM32CubeMx配置中,我们配置了通道,目标及源为安全属性,但并没有配置其特权属性。在CubeMx中其默认为非特权,见之前的图5所示。也就是说,我们需要将通道也配置成特权属性,于是直接修改代码:/ r( C) o. |" o8 F9 [3 a
  1. //…( S, s. v8 g5 N
  2. __HAL_LINKDMA(huart, hdmarx, handle_GPDMA1_Channel1);8 J0 a; U: z' A2 e
  3. if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel1,- ^" @( w* o" T; O: j/ _2 j
  4. DMA_CHANNEL_PRIV|DMA_CHANNEL_SEC|DMA_CHANNEL_SRC_SEC|DMA_CHANNEL_DEST_S
    0 J3 Q) f; I% U4 c* L
  5. EC) != HAL_OK)
    / u6 s1 l" Z6 Q
  6. {
    8 a* H0 E( X5 y6 t. U
  7. Error_Handler();
    & e2 Y# a1 {& ^3 g# k
  8. }! `$ P* N! s7 e; v' g! g/ D
  9. //…  F3 H0 `/ x7 @  s! W5 \
  10. __HAL_LINKDMA(huart, hdmatx, handle_GPDMA1_Channel0);
    ) Z$ x, d& Y2 o) H/ C  j
  11. if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0,& A2 z' Y( Z! b! E# q
  12. DMA_CHANNEL_PRIV|DMA_CHANNEL_SEC|DMA_CHANNEL_SRC_SEC|DMA_CHANNEL_DEST_S
    2 w) H1 o2 F8 s' o, ]
  13. EC) != HAL_OK)' z. r/ Y: |+ t% ~2 s
  14. {  E: b; z2 i: X" t. W
  15. Error_Handler();
    $ ~' [, W4 D! U& M8 b
  16. }" M/ p& J  f8 e; _* X3 Y1 _0 v
  17. //…
复制代码
) j- C# J+ g# t. r$ B% }, X
如上代码所示,在代码中配置DMA通道处(红色标记处),将其改为配置特权属性。然后编译后再次测试,这次则能正常发送数据了:, _, M. R" ]( y  U# a1 f
22.png
▲ 图 9 串口正常发送数据

2 v$ h" _# a& H. Q, ?, m( p: A
8 t) [3 u( I$ W
03
) R+ F; [8 O+ `" f" v* G4 m小结# u" m4 d, l$ [9 x) J
在trustzone使能的情况下,MCU内的资源,若代码中没有显式设置的情况下,要注意其默认状态,内部flash,SRAM,片外存储映射区域以及GPIO引脚均为安全的,且特权,Securable外设基本都是非安全的,在STM32U5安全培训的一页PPT中有做总结,如下图所示:
' H/ m6 {0 j/ N1 `8 k
23.png
本文所描述的问题,正是由于MPCBB2(Boot工程对应的RAM)没有配置,其默认为Secure+Prileged属性,但DMA默认属性为NonSecre+NonPrileged。代码中只配置DMA通道为Secure属性,并没有配置其为Prileged,因此导致其访问SRAM2时失败,这也就是为什么发送内容全为0的原因了。这也提醒我们,在开发trustzone相关的项目时,对各个资源的安全属性配置一定要小心。
. a( T6 U% j+ N0 m
: T, E' o% M$ z
收藏 评论0 发布时间:2025-4-25 09:44

举报

0个回答

所属标签

相似技术帖

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