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

基于STM32 TrustZone 开发HardFault调试与处理

[复制链接]
STMCU小助手 发布时间:2023-11-30 17:05
引  言  F. a. }4 v4 B
在 STM32 TrustZone 开发调试技巧的前两篇中,我们介绍了内核的 SAU/IDAU,地址的安全属性配置,资源的安全属性配置,内核访问资源的安全规则,以及 TrustZone 环境下外设使用的常见问题等内容。TrustZone 环境开发中还可能经常遇到的一个问题就是软件触发的故障错误。ARM CM33内核 TrustZone 环境下的异常模型以及 Fault 的处理与不带安全扩展的情况有着很多变化,一旦出现 HardFault,经验不足的开发者可能往会找不到头绪,不知道从哪里着手寻找问题所在。因此,在这一篇的重点将围绕 CM33 TrustZone 环境下的异常模型以及 HardFault 的调试与处理展开,供开发者参考。2 G4 K( @  ~) h$ w, X" ?

/ _" [" H: P$ s- e- q# q; f一、CM33 TrustZone 架构下的异常模型
# _3 K( k+ C* S1 ?# ?6 t' ]( _% U在 STM32 TrustZone 开发调试技巧的第二篇中我们介绍过 CM33 带安全扩展的 S 和 NS 侧的中断以及中断向量表,这里不再赘述。表 1 总结了其中的 Fault 异常。; N3 }+ z$ i3 t2 X0 `4 I/ Q$ Y

9 Y) d0 S" z( \2 Y9 p
微信图片_20231130170530.png

4 c. v0 [$ `) W  h
; E, k, G8 E6 Z: t1.1. Fault 异常类型(带安全扩展)
) D4 M' S9 T6 t  \1 G4 G1.1.1. Hard Fault5 ?) L: [4 t- p. L0 U0 a
HardFault 是默认的 Fault 异常,总是使能。触发的原因可能是由于异常处理本身触发了错误,或者某个异常无法被其他机制处理而上升到 HardFault。它的优先级高于所有其他可配置优先级的异常。" o1 N) P* j' n# |0 U; c% J# w

$ `' J1 T. y" Q; q  _在 TrustZone 环境中,HardFault 不是 Bank 的。同一个异常,要么触发 S 侧的HardFault,要么触发 NS 侧的 HardFault。SCB 的 AIRCR.BFHFNMINS 决定了是否使能NS的BusFault,HardFault 和NMI。如果SCB 的 AIRCR.BFHFNMINS=0,HardFault 总是触发 S 侧的 HardFault Hanlder;如果 AIRCR.BFHFNMINS=1,则故障可能触发 NS 侧的 HardFaultHandler,也可能触发 S 侧的 HardFault Handler。图1 给出了在其他 Fault 未使能情况下,HardFault Handler 触发一般情形。7 y+ @1 `9 M  R% t7 n

, e! s: N; W4 k0 l1 |+ m6 `( r$ p8 |
( j% ^* g$ O1 l+ v: R8 {; Z" G
微信图片_20231130170527.png

7 g: U4 O7 J' ]* w/ C5 w8 X" {6 l
5 c5 ?, Z1 u1 j5 H4 e3 I5 X需要注意的是,即使 AIRCR.BFHFNMINS=1,原本 target 到 S 侧并且上升为 HardFault 的异常,将依旧触发 S 侧的 HardFault,他们并不受到 AIRCR.BFHFNMINS 位的影响,例如当安全代码违反 MPU 保护规则,产生 MemManage 错误的时候,即使 AIRCR.BFHFNMINS=1,故障还是会进入 Secure HardFault Handler。而 NS 侧的 HardFault,只有当AIRCR.BFHFNMINS=1 时才有可能会被触发。0 t; l" |0 f& R7 c

. s) \; e* z' w0 ]另外还要注意一点,AIRCR 寄存器不能直接修改,需要先写 Key 值才能更改寄存器内容。置位或清除 AIRCR.BFHFNMINS bit 的示例代码如下(只能在安全代码中使用):4 ]2 O4 ^* @* i2 g1 G1 P  F
  1. void SECURE_SetNMIHFBFTarget(int NS)
    3 K" W1 K1 G" y
  2. {
    & ]3 O. E* }% K, M" s: C
  3. uint32_t reg_value;
    4 V1 l  z+ z" C9 d' U# _
  4. uint32_t target = (NS==1)?1:0;0 O& D( _. N6 J
  5. /* read old register configuration */- M3 z# `0 m, R/ x& G) F
  6. reg_value = SCB->AIRCR;- K1 }# j; g0 ]: N
  7. /* clear bits to change */
    : Y' K% J% I& J1 h( s
  8. reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_BFHFNMINS_Msk));
    3 N/ [4 B$ s3 T5 O* n# k; r
  9. /* insert write key and target bit */  d  ?3 W% u# c: [! ^
  10. reg_value = (reg_value |
    ( ^; u+ Y8 t) U* Z( j
  11. ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
    4 ^9 \/ b. ]5 ~% Z, P
  12. (target << SCB_AIRCR_BFHFNMINS_Pos) );
    & e. x9 U  B0 Q$ S6 j: N. p
  13. SCB->AIRCR = reg_value;
    % ^, ]; j& x2 f7 v
  14. }
复制代码
* M* S; j# u3 I
注意:有的时候,软件可能需要设置 AIRCR.PRIS 位,来整体降低 NS 中断的优先级(例如在 TF-M 的实现中就使用这个机制)。这时候,如果同时设置 AIRCR.PRIS=1,AIRCR.BFHFNMINS=1,内核的行为将不可预测。因此如果需要设置 AIRCR.PRIS=1,则建议保持 AIRCR.BFHFNMINS=0。
. v6 C. }" j" d7 z3 g2 p" K$ @7 S7 k0 a1 m9 J9 E1 z
* N3 ?# Q- K2 ]- K6 z
1.1.2. Bus Fault
/ E* [7 Q4 D. MBus Fault 通常发生在指令或数据访问时候,可能由于检测到 memory 系统的总线错误而导致。Bus Fault 默认不使能,就是说总线故障默认将触发 HardFault Handler。如果需要单独使能 Bus Fault,可以将 SCB 的 SHCSR.BUSFAULTENA 位设 1。$ f1 h) a) Z! D+ [4 h, D; N& o
+ p, O" F2 z! z5 t( t
在 TrustZone 环境中,Bus Fault 也不是 Bank 的。触发 S 还是 NS 侧的 BusFault Handler与SCB 的AIRCR.BFHFNMINS 有关。如果 AIRCR.BFHFNMINS=0,BusFault 总是 target 到S 安全状态;反之如果 AIRCR.BFHFNMINS=1,则 target 到 NS 非安全状态。. C) x, A, }' w- ^7 r" U& m

' v  {8 V/ z4 y产生 Bus 错误时,实际会触发哪个 Fault Handler,将取决于 AIRCR.BFHFNMINS 和SCB_S/NS 的 SHCSR.BUSFAULTENA 的设置。图 2 给出了 Bus 错误触发 Fault Handler 的一般情况(例如这里不考虑安全侧 Vector 错误依旧上升到 Secure HardFault 的情况)。
, Z$ n' ~( r5 G! T/ f4 g- n$ ~& Y6 ~* e2 N  B& X) N7 I, |
微信图片_20231130170523.png

- V6 y: z0 V3 g4 T. j- s5 V" y
2 O1 p1 j  l( S1 p, ~* m通常情况下,SCB 的 CFSR/BFSR 和 BFAR 寄存器中会标记总线故障信息。在 TrustZone环境中,SCB 的某些寄存器以及寄存器的某些比特位是 Bank 的。从安全侧和非安全侧都能够看到各自的 SCB 寄存器,但是 CFSR 寄存器的 BFSR 域以及 BFAR 寄存器并不是 Bank 的。而 Bus 故障可能 target 到 S 安全侧也可能 target 到 NS 非安全侧,当发生总线错误的时候,如果分别从 SCB_S、SCB_NS 的相关寄存器中读取 Bus Fault 的信息,可以看到不同的结果。8 r) i2 u7 c+ s; Q1 _/ [7 D0 ~2 @
+ B. U( X: C9 K# v/ Q# i
如果 AIRCR.BFHFNMINS=0,只有安全侧可以看到 BFSR 和 BFAR 的真实数据,非安全侧读取 BFSR、BFAR,或者从安全侧读取 BFSR_NS,BFAR_NS 都只能读到全 0 的值。
9 F9 t+ b( I: V; b$ Z8 b
& W5 J+ k! S6 V1 ~5 q+ t
如果 AIRCR.BFHFNMINS=1,BFAR_NS 和 BFAR_S 的值一般会读取到相同的值。通常,代码需要处理 BusFault 时,如果使用默认配置,即保持 BusFault target 到 S 侧,AIRCR.BFHFNMINS=0,则 Fault Handler 可以从 SCB_S 的 CFSR.BFSR 和 BFAR 寄存器获取总线故障信息;而如果设置了 AIRCR.BFHFNMINS=1,那么发生 Bus error 的时候,非安全侧的 Fault Handler 可以直接从 SCB_NS 的 CFSR.BFSR 和 BFAR 寄存器获取故障信息。
5 K9 N1 C) Y- @* W8 I% Z9 m

% j' s. r5 ]" G  ZBusFault 默认没有单独使能,如果需要使能 BusFault,可以将 SHCSR 寄存器的BUSFAULTENA 位置位。使能或禁止 BusFault 的示例代码如下:! ?' z- v, d* d! H5 T/ n
  1. void EnableBusFault(int enable)
    $ B7 c0 ~% G7 a/ y
  2. {9 F0 l) _# N0 Y5 \5 i
  3. if( enable == 1)0 B: I5 \( u/ R7 i* G0 g
  4. SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
    3 {2 L, i  z7 Y; ~) A4 d/ k* ?
  5. else
    % |6 F5 I9 ~. o
  6. SCB->SHCSR &= (~SCB_SHCSR_BUSFAULTENA_Msk);: ^. ^0 i0 A1 f: ~/ S: B- Y
  7. }
复制代码
* z; O/ P  k2 j+ t5 z
这段代码对安全和非安全侧都是一样的,但是要注意,由于 BusFault 不是 Bank 的,当AIRCR.BFHFNMINS=0 时,这段代码只能在安全侧使用,也就是修改的是 S 安全侧 SCB SHCSR 的 BusFault,此时写 SCB_NS 的 SHCSR.BUSFAULTENA 位无效。1 Q2 c$ T% X& ]7 A0 c& R
/ L1 D, T- K) p
如果非安全侧应用使用这段代码使能 BusFault,那么前提是安全侧已经设置了AIRCR.BFHFNMINS=1。0 S4 c4 }( p) V
' Q9 g; n0 W* \: K  ]. X
1.1.3. Usage Fault. L+ H- ?0 H; _3 x% x+ n
UsageFault 与指令执行时候的错误有关,包括未定义的指令、非对齐访问、执行指令时的无效状态、中断返回时的错误、除 0 等。! T6 c, |% ~1 ?( f

" {/ K. J# }, d- x' }" b/ `在 TrustZone 环境中,UsageFault 是 Bank 的,因此在 S 和 NS 状态可能产生各自的UsageFault,并且可能触发各自的 S UsageFault Handler 和 NS UsageFault Handler。UsageFault 默认不使能,因而缺省会上升到 HardFault,是否触发 S 还是 NS 的 HardFault Handler 还要取决于 AIRCR.BFHFNMINS 的值是 0 还是 1。
7 Y% o$ Z/ |# T( J  Y6 }

( R1 i; z2 J6 U使能UsageFault 需要分别设置 SCB_S 和 SCB_NS 的 SHCSR.USGFAULTENA。SCB_S的 SHCSR.USGFAULTENA=1 用于使能 S 安全侧的 Usage Fault;SCB_NS 的SHCSR.USGFAULTENA=1 用于使能 NS 非安全侧的 Usage Fault。
" }) E& a- I- W7 }; L
# {; ~; k2 V0 P5 g
另外,通常除 0 操作不会触发 UsageFault,如果希望除 0 操作触发 UsageFault,需要将SCB_S/NS 对应的 CCR.DIV_0_TRP 比特置 1。
; j+ i# H+ i8 W4 g* J; c, O
2 Z5 n. M$ Q7 p# Z1 r( m图 3 总结了 Usage 错误触发 Fault Handler 的一般情况。
4 c* a1 W8 v. S6 Q7 y; d
9 ?/ A( A# W( |' `
微信图片_20231130170520.png
2 u, A% N+ ?* @" ?
/ g) _' i. }- j0 D* }3 ]. |
只要 SHCSR.USGFAULTENA=1,UsageFault 总是触发软件对应安全状态的 UsageFault Handler,否则上升到 HardFault,安全侧的 UsageFault 总是上升到 Secure HardFault。对于非安全侧的 UsageFault,如果 AIRCR.BFHFNMINS=0,则上升到 Secure HardFault,否则上升到 Non-Secure HardFault。/ X% p* q' M9 Y8 p! N
0 t- t% n. P9 b% w
使能或禁止 UsageFault 的示例代码如下:% x( T* U1 v5 L- w5 B
  1. void EnableUsageFault(int enable). l8 G- N* [) O' N
  2. {6 W, r5 n+ Q* B' G  l4 V+ `5 K
  3. if( enable == 1). |9 y; s* P* k8 M( p! I8 H
  4. {) [; E* ~2 c4 h1 I! G0 \% l) @
  5. SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;% O. a( @& h4 a0 x% k
  6. /* Enable divide by 0 trap to trigger usage fault (if necessary) */
    . @, c: b+ W% j5 R( E# o0 U; {
  7. SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;; w4 s6 N% s+ q8 B2 `' k
  8. }% J2 Y; h; n% c: e% X! [( Q
  9. else
    ! p3 }2 D2 G% X# h- o/ b
  10. SCB->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    , c& X" _& r6 D: a( D
  11. }
复制代码
; l. d: M' M- a! l9 j
如果安全和非安全侧都需要使能 UsageFault,则 S、NS 代码可以分别调用这段代码使能各自的 UsageFault,或者 S 安全侧代码也可以直接控制 NS 非安全侧 UsageFault 的使能,例如可以在 S 安全侧增加下面这段代码来决定 NS 侧的 UsageFault 是否使能。
0 j: y  n" S  s5 ?' ?. L
  1. void EnableNSUsageFault(int enable)* f% @: \" s" c( x1 h& |
  2. {
    5 ~% A- O  V6 V0 E# @  z
  3. if( enable == 1)
    ' Y8 J- p5 f8 l% R9 r5 M
  4. SCB_NS->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
    3 s9 p0 U% s# D2 Y& C1 C
  5. else
    % y1 b! a& r0 m9 V0 ?& y
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    ' m" z6 `! j" I& Y! F" Q
  7. }
复制代码

. C, g8 O( y9 A8 ]7 u5 N; m2 k1 I1.1.4. MemManage Fault/ q; l0 G* J1 }6 ]( ~* h2 t, z7 t' R
MemManage Fault 是由于 Memory 保护产生的故障异常,例如在取指令或进行数据访问时违反了 MPU region 定义的访问规则,或者违反了默认地址保护规则。
3 B' H* D+ s, S3 z7 O4 z, L
4 I& |3 i; q* s+ o3 oMemManageFault 与 UsageFault 类似,也是默认不使能,如果希望使能 S 或者 NS 侧的MemManageFault,需要相应将 SCB_S 或者 SCB_NS 的 SHCSR.MEMFAULTENA 比特置位。( e; t3 I6 u  Q' O# y
0 L; \  v0 V% h7 ~- m8 W( S* [+ }* h0 U
另外也与 UsageFault 类似,MemManageFault 在 S 和 NS 侧也是 Bank 的,也就是 S、NS 有各自的 MemManageFault。由于 MPU 单元本身是 Bank 的,系统中有两套 MPU 寄存器MPU_S 和 MPU_NS,因而代码在 S 和 NS 侧可以各自定义自己的 MPU region 并使用不同配置,也就是说即使对相同的地址,S/NS 两侧也可以通过各自的 MPU 单元定义不同的访问规则。MPU_S 配置的保护规则只应用于 S 安全侧代码,即控制 CPU 处于安全状态时候的访问,这与 CPU 访问的地址的在 SAU 中定义安全属性无关。而 MPU_NS 配置的保护规则只应用于NS 非安全侧代码,即 CPU 处于非安全状态时候的访问,二者互不影响。
7 L0 i4 H; d) e9 x4 \4 Q% d5 s9 q4 x' F
图 4 给出了 MemManage 故障触发 Fault Handler 的一般情况。如果 S 安全代码违反memory 访问规则,可能会触发安全侧的 MemManageFault,或者 Secure HardFault。非安全代码违反 memory 访问规则,可能会触发非安全侧的 MemManageFault,或者上升到HardFault,如果 AIRCR.BFHFNMINS=0 上升到 Secure HardFault,否则上升到 Non-Secure HardFault。2 }; E( X  o; e
微信图片_20231130170516.png

+ d0 m! ]' V1 `- h# O- h$ @+ Z) K
微信图片_20231130170512.png
. s% C, J: |. B: h/ _

& m7 I1 H# \; w$ ^( G6 Z: N+ ~使能或禁止 MemManage Fault 的示例代码如下:( o" n# N/ k* j& y% P
  1. void EnableMemoryFault(int enable); Z7 l1 P/ b  C+ l; ]
  2. {' m$ }. Z, ]( z% W
  3. if( enable == 1)
      d* U2 N0 U8 v2 W9 A; H2 P+ a
  4. SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;( j3 Z0 y" D) c; M- p& {6 ^
  5. else
    ( i9 V7 i  X; U3 N
  6. SCB->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);
    6 r! T: C& {3 Q9 X8 _, B
  7. }
复制代码

: l3 X8 `$ G" V2 J! ~如果安全和非安全侧都需要使能 MemManage Fault,则 S、NS 应用可以分别调用这段代码使能各自的 MemManage Fault,或者 S 安全侧代码也可以直接使能 NS 非安全侧的MemManage Fault,例如可以在 S 安全侧增加下面这段代码来控制 NS 侧的 MemManageFault 使能。/ a2 F2 i6 g! ~3 O
  1. void EnableNSMemoryFault (int enable)
    7 y; L" Z) M6 B9 ]8 {
  2. {/ d6 B1 C2 @) L: `2 O
  3. if( enable == 1)9 B! U3 P/ W$ _5 `# C
  4. SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;# F  _/ V' O7 f! X7 y' j, b
  5. else
    3 {, F7 w) x2 z* B; q/ y1 F7 I* E6 U% q
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);
    ) e4 B- t+ D' r) f& c5 s  N
  7. }
复制代码

$ |+ o& B* A3 r/ B) ~3 }另外,如果代码使用 HAL API 使能 MPU,即调用 HAL_MPU_Enable(),那么MemManage Fault 在 MPU 使能的函数中会自动被使能,这时候无需额外调用前面提到的代码去单独使能 MemManage Fault。
2 ^# u" p: i) t: U* f& q2 m1 c/ Y: `  Y6 U& w& w) ?# I
1.1.5. Secure Fault; o7 r+ n5 |8 Z
Secure Fault 只有在 TrustZone 使能的环境下才存在。SecureFault 可能由于内核中各种各样的安全检查而触发,例如从 NS 跳转至 S 代码时没有从 SG 入口指令进入,或者非安全代码试图访问 SAU/IDAU 规定的安全地址范围等。通常当出现 SecureFault 时,软件的处理可以是直接停止或者复位系统,这样做可以尽可能地避免引入安全漏洞。
1 O1 h7 k* u( c8 g8 ~+ W: `8 K( X" m- E+ w
SecureFault 不是 Bank 的,总是 target 到 S 侧,因此只有安全代码能够处理SecureFault。SecureFault 缺省也没有使能,出现 Secure 错误时,默认触发 SecureHardFault。软件可以通过置位 SHCSR.SECUREFAULTENA 来单独使能 SecureFault,使能后Secure 错误将触发 SecureFault Handler。图 5 给出了 Secure 错误触发 Fault Handler 的一般情况。
3 ^' l! b; e9 z% `" p0 l  V+ r9 U  g) ]. ~8 S9 ~, j! [$ F, K3 {
微信图片_20231130170508.png

/ u% A! f1 O3 U, Q6 x8 X
微信图片_20231130170459.png
1 b2 S: c9 h$ s; f* f
. }' z( ^. L! l
使能或禁止 SecureFault 的示例代码如下:
" _8 x) I' H( e0 W7 I
  1. void EnableSecureFault(int enable)
    1 c, O- _. ^9 v! F! r0 u
  2. {
    ' ~( {( Q! t9 P* J$ k7 o6 P
  3. if( enable == 1)
      I5 L- _3 q8 Y% }/ K( S
  4. SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk;7 c/ ?* b; x, e4 v
  5. else% y' F! Y% D. j3 L
  6. SCB->SHCSR &= (~SCB_SHCSR_SECUREFAULTENA_Msk);
    4 _# ~" W# B6 Y3 @% ]  \
  7. }
复制代码
: A0 @9 s0 O0 H* h" K- |+ E
1.2. 故障升级与 HardFault
6 s) l) G' C- X# E" Q( D除了 HardFault 以外,其他故障类型都具有可配置的优先级。软件可以禁止某个可配优先级的故障异常,但是不能禁止 HardFault。故障异常的优先级和对应的 mask bit 决定了内核是否会进入某个故障的处理程序,以及某个故障是否可以抢占另一个故障。' c6 {; q1 ~* ^
% W9 e; K/ L9 f: x( p8 Y6 s* g
某些情况下,可配置优先级的故障可能会被当成 HardFault 处理,也就是故障升级或称中断上访,此时,这个具体的 Fault 会升级为 HardFault 故障。
/ y; l# V* G3 @( i* I$ C某个 Fault 升级成 HardFault 可能有多种原因,例如:
- R! ^7 j# g( m该故障 Fault 没有使能;+ C  x, M: {5 `* E5 Z# F) `

% W9 R: C: S8 r; f/ V+ r- n7 B- I例如,代码由于执行未定义的指令产生了 UsageFault,但是 UsageFault 没有被使能.$ ~, \$ }+ P9 t9 [. v
该故障的 FaultHandler 优先级不够高无法运行;% p* J) e3 D. g- M, }5 y
0 ]! N7 f, N1 ?( D- Y
例如,系统配置并使能了 MPU,CPU 正在执行某个中断操作,该操作试图进行地址访问时违反了 MPU 定义的访问规则,进而触发了故障,但是当前执行的中断的优先级高于 MemManage 故障的优先级。) M5 k( z) D$ d  B# I  A; }8 l6 ]
在故障的 FaultHandler 中产生了同样的故障;
5 ^) `9 m' V2 ]  s
, {" G: |. @0 S) S, U例如,在处理 UsageFault 的 handler 中又发生了未定义指令的情况。" z7 J$ y& g, e" e! l
如果在进入 BusFault Handler 的时候,压栈操作又导致了 BusFault,这种情况下 BusFault 不会升级到 HardFault。这意味着,如果损坏的堆栈导致故障,即使 Fault Handler 压栈失败,故障处理程序还是会执行,但堆栈内容已损坏。. U4 H; J. p+ Z
只有 NMI 可以抢占 HardFault,HardFault 可以抢占任何除 Reset、NMI 或者另一个HardFault 以外的异常。当 BFHFNMINS=1 时,如果 NS 侧的 NMI Handler 产生了安全违规错误,那么它将触发 Secure HardFault,并被其抢占。
- X6 D1 T9 e! }0 j+ ~' b3 V在获取异常向量的时候发生的 Bus 错误,总是升级到 HardFault,由 HardFault 处理,而非 BusFault。
, V  l' W* ^* ]$ y
( P; T+ q, o) U) K5 A- F0 ^3 c1.3. Fault 异常的安全状态' _4 ~) f1 {  s) t8 _
在 TrustZone 使能的环境中,故障异常可能 target 到 S 安全状态或 NS 非安全状态,这会导致 ARMv8-M 内核的行为与以往 ARMv6-M 及 ARMv7-M 内核有很大不同,TrustZone 环境软件开发中对 Fault 的处理要特别注意到这一点。8 U2 J" M+ Y0 P6 l/ `4 l# N& e
关于 Fault 异常 target 到 S、NS 的情况在前文中介绍几个 Fault 类型的时候已经有提到,这里在表 2 中再稍加总结。- H& ?) A6 V, B3 v: f! \
% w/ U* V  n9 L( t5 G4 u
微信图片_20231130170455.png
, D/ T- ?. s* |

1 g" h- O2 u/ L0 u7 C  D0 c1.4. 异常的进入与返回8 k* {; I( L: [/ X' _
1.4.1. 异常的进入与 stack frame- t# @1 W3 g. q
当处理器处于线程模式且系统存在具有足够优先级的 pending 异常时则会进入异常,或者新异常的优先级高于正在处理的异常,这时候新异常将抢占原始异常,即出现异常嵌套。
8 s. \6 g' H! i" w# H2 T: D0 v( q当处理器发生异常时,除非该异常是尾链异常或延迟到达的异常,否则处理器会将上下文信息压入堆栈,压栈的数据结构即 stack frame。
# n# K# B2 L2 l7 ~% w- e通常 stack frame 的内容如图 6 (a) 所示,包含了 R0 到 R3、R12、LR、PC 和 xPSR 的内容。在 TrustZone 使能的环境中,如果 S 安全代码执行被 NS 非安全异常抢占,那么进入非安全异常前会有更多的信息压栈,如图 6 (b)所示,并且硬件会自动将压栈的寄存器清零,防止任何安全状态下的数据暴露给非安全代码。
9 y0 [1 m$ C# N5 V如果使用了浮点功能,存在浮点上下文,那么内核也会自动将浮点相关的上下文内容压栈。由于浮点部分数据内容对我们通常的 Fault 调试没有太多帮助,这里不做赘述。
, H3 g, F7 r' N. @0 M/ V6 L( `进入异常前的 stack frame 压栈操作使用 MSP 还是 PSP,取决于当时内核的运行状态及其使用的堆栈。如果当时 CPU 运行于 Handler 模式,则使用 MSP 压栈 stack frame;如果 CPU运行于 Thread 模式,由当时的 CPU CONTROL.SPSEL 位来标记使用的堆栈。" |: m1 g9 D* ^: g3 w

1 i$ [# @  W+ @0 x

+ a9 O  u) j8 _5 B4 b转载自: STM32
; H* Z  ~8 m  ?" t, `4 p- D如有侵权请联系删除
: _/ q7 M- f5 D; {! k. {' s* \: A; T7 T0 C0 D( X1 {, i6 S

- a7 y$ q0 o  }- T- d7 t- w* v/ ^5 U, |" U# h
赞 收藏 评论0 发布时间:2023-11-30 17:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版