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

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

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

8 O5 j6 U, U5 r" @' z一、CM33 TrustZone 架构下的异常模型  ^2 o7 j8 V! V% G$ E( [
在 STM32 TrustZone 开发调试技巧的第二篇中我们介绍过 CM33 带安全扩展的 S 和 NS 侧的中断以及中断向量表,这里不再赘述。表 1 总结了其中的 Fault 异常。' O% a1 s& n6 a! z0 R3 P1 ~5 F  V8 B
: x0 C$ _/ s' n$ N, n, ~
微信图片_20231130170530.png
/ d0 h- R+ z  |: v* }

. Y4 ~9 W, ?4 ], r1.1. Fault 异常类型(带安全扩展)! |1 i' I, V4 J' @, g
1.1.1. Hard Fault, H+ j& Q. w# Z& a) S: C/ m5 @
HardFault 是默认的 Fault 异常,总是使能。触发的原因可能是由于异常处理本身触发了错误,或者某个异常无法被其他机制处理而上升到 HardFault。它的优先级高于所有其他可配置优先级的异常。
9 @" m( ?# o0 G2 P3 i
. u7 V9 v  L6 i& F& E在 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 触发一般情形。
% c/ ^  G4 }. h8 N
" ?; E/ D0 b2 j/ B3 F4 x+ e
6 l: s* E2 F# ?3 s, P/ y
微信图片_20231130170527.png
" H5 C! d) s3 O. D  {  P6 R

2 U) i+ ~+ ~# G6 Q  A1 i6 d6 z需要注意的是,即使 AIRCR.BFHFNMINS=1,原本 target 到 S 侧并且上升为 HardFault 的异常,将依旧触发 S 侧的 HardFault,他们并不受到 AIRCR.BFHFNMINS 位的影响,例如当安全代码违反 MPU 保护规则,产生 MemManage 错误的时候,即使 AIRCR.BFHFNMINS=1,故障还是会进入 Secure HardFault Handler。而 NS 侧的 HardFault,只有当AIRCR.BFHFNMINS=1 时才有可能会被触发。
3 _8 `1 y3 }" y
( F  X9 Y9 m2 |9 u& D. L另外还要注意一点,AIRCR 寄存器不能直接修改,需要先写 Key 值才能更改寄存器内容。置位或清除 AIRCR.BFHFNMINS bit 的示例代码如下(只能在安全代码中使用):9 X& h: n7 v: n& h' F- k
  1. void SECURE_SetNMIHFBFTarget(int NS)# B9 h# g) |1 n/ f; O  m
  2. {
    9 x6 x% [' T- M1 t# d' P
  3. uint32_t reg_value;* O3 ]$ K( G2 b& s2 E* O( ~
  4. uint32_t target = (NS==1)?1:0;
    4 F! ]/ q4 T, Q
  5. /* read old register configuration */
    5 c$ m6 f" b& m8 t
  6. reg_value = SCB->AIRCR;( A6 ?" f, J$ l. [7 m
  7. /* clear bits to change */' n. p% @3 I3 r& `
  8. reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_BFHFNMINS_Msk));) F/ n( ?4 }: s2 _
  9. /* insert write key and target bit */
    " E7 b1 n) |6 A) m
  10. reg_value = (reg_value |% F" h9 `& ~6 C0 l) E( P( h$ y
  11. ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
    . t, x* E% o5 h! r1 {$ g4 s
  12. (target << SCB_AIRCR_BFHFNMINS_Pos) );
    : x6 Q  ~( t, g' r  P
  13. SCB->AIRCR = reg_value;+ T4 x, G8 [% Y+ J+ {) K. |, z* k
  14. }
复制代码
& z* Y/ `. s4 ?; r% @& t% {  I
注意:有的时候,软件可能需要设置 AIRCR.PRIS 位,来整体降低 NS 中断的优先级(例如在 TF-M 的实现中就使用这个机制)。这时候,如果同时设置 AIRCR.PRIS=1,AIRCR.BFHFNMINS=1,内核的行为将不可预测。因此如果需要设置 AIRCR.PRIS=1,则建议保持 AIRCR.BFHFNMINS=0。
8 ?9 g4 `8 W+ V* C9 x' H
5 o  O, m0 `, ?
* O7 m$ N- J8 D; p
1.1.2. Bus Fault* p; Y' j5 E3 R4 R7 l' A  i
Bus Fault 通常发生在指令或数据访问时候,可能由于检测到 memory 系统的总线错误而导致。Bus Fault 默认不使能,就是说总线故障默认将触发 HardFault Handler。如果需要单独使能 Bus Fault,可以将 SCB 的 SHCSR.BUSFAULTENA 位设 1。
5 g) o! s3 j4 V  k8 _( U

  S+ U( }( P. \6 v( w# W) v在 TrustZone 环境中,Bus Fault 也不是 Bank 的。触发 S 还是 NS 侧的 BusFault Handler与SCB 的AIRCR.BFHFNMINS 有关。如果 AIRCR.BFHFNMINS=0,BusFault 总是 target 到S 安全状态;反之如果 AIRCR.BFHFNMINS=1,则 target 到 NS 非安全状态。& \. |  O0 p  F

0 y. s  j6 P" |, c: u4 T! @产生 Bus 错误时,实际会触发哪个 Fault Handler,将取决于 AIRCR.BFHFNMINS 和SCB_S/NS 的 SHCSR.BUSFAULTENA 的设置。图 2 给出了 Bus 错误触发 Fault Handler 的一般情况(例如这里不考虑安全侧 Vector 错误依旧上升到 Secure HardFault 的情况)。; G3 w- u- J$ R9 f$ b) |
" C9 P6 P) U5 U& C. K+ B
微信图片_20231130170523.png

% y* k% z  J6 w1 T0 h  `8 C  ?" @+ a# r1 t; d" Z
通常情况下,SCB 的 CFSR/BFSR 和 BFAR 寄存器中会标记总线故障信息。在 TrustZone环境中,SCB 的某些寄存器以及寄存器的某些比特位是 Bank 的。从安全侧和非安全侧都能够看到各自的 SCB 寄存器,但是 CFSR 寄存器的 BFSR 域以及 BFAR 寄存器并不是 Bank 的。而 Bus 故障可能 target 到 S 安全侧也可能 target 到 NS 非安全侧,当发生总线错误的时候,如果分别从 SCB_S、SCB_NS 的相关寄存器中读取 Bus Fault 的信息,可以看到不同的结果。0 ~/ U& K* s$ v

; {2 a4 D4 |! D( i. b+ J! N如果 AIRCR.BFHFNMINS=0,只有安全侧可以看到 BFSR 和 BFAR 的真实数据,非安全侧读取 BFSR、BFAR,或者从安全侧读取 BFSR_NS,BFAR_NS 都只能读到全 0 的值。0 Y2 g! Q5 `9 t8 @3 U
5 u$ e- g& N: k  r4 ?6 n
如果 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 寄存器获取故障信息。
- E8 R, G( i8 w$ o6 B
4 Q2 G. i2 r  c; r
BusFault 默认没有单独使能,如果需要使能 BusFault,可以将 SHCSR 寄存器的BUSFAULTENA 位置位。使能或禁止 BusFault 的示例代码如下:
5 h' t0 L4 _& i5 ]* U1 z( D
  1. void EnableBusFault(int enable)
    2 y+ J! a# n  E' `, m
  2. {7 w; A# Z2 H* B: N2 X( {6 e
  3. if( enable == 1)2 n5 H( U7 L" u6 s+ c
  4. SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;1 V8 [+ W! e" J, r
  5. else
      _1 w" X- M9 |; Z' k5 ^+ D
  6. SCB->SHCSR &= (~SCB_SHCSR_BUSFAULTENA_Msk);
    % s5 _* `- U. B" {5 v; J7 O0 X7 w1 ~
  7. }
复制代码
: _$ D0 H; q9 H% H8 w
这段代码对安全和非安全侧都是一样的,但是要注意,由于 BusFault 不是 Bank 的,当AIRCR.BFHFNMINS=0 时,这段代码只能在安全侧使用,也就是修改的是 S 安全侧 SCB SHCSR 的 BusFault,此时写 SCB_NS 的 SHCSR.BUSFAULTENA 位无效。6 P- W# Z9 N8 n& c7 H! o+ M

2 T; k9 q$ Q1 b, H7 V8 t; ~0 r如果非安全侧应用使用这段代码使能 BusFault,那么前提是安全侧已经设置了AIRCR.BFHFNMINS=1。
* ?5 G# O& M2 W' M+ W, d9 V1 t6 `4 ^& b- ?. q5 q2 i
1.1.3. Usage Fault, _9 [- |, K7 v$ \- P
UsageFault 与指令执行时候的错误有关,包括未定义的指令、非对齐访问、执行指令时的无效状态、中断返回时的错误、除 0 等。
6 |! h3 w- E0 a7 f0 Z+ v% q1 k3 c4 w, Z" |; w+ {, U% |
在 TrustZone 环境中,UsageFault 是 Bank 的,因此在 S 和 NS 状态可能产生各自的UsageFault,并且可能触发各自的 S UsageFault Handler 和 NS UsageFault Handler。UsageFault 默认不使能,因而缺省会上升到 HardFault,是否触发 S 还是 NS 的 HardFault Handler 还要取决于 AIRCR.BFHFNMINS 的值是 0 还是 1。. B0 \* D2 d1 n+ p
: f5 z! B$ L  J
使能UsageFault 需要分别设置 SCB_S 和 SCB_NS 的 SHCSR.USGFAULTENA。SCB_S的 SHCSR.USGFAULTENA=1 用于使能 S 安全侧的 Usage Fault;SCB_NS 的SHCSR.USGFAULTENA=1 用于使能 NS 非安全侧的 Usage Fault。
1 w& p# U1 O% D9 J/ @$ l# K

5 V( W: d) ?8 e# Q$ Y. x8 _另外,通常除 0 操作不会触发 UsageFault,如果希望除 0 操作触发 UsageFault,需要将SCB_S/NS 对应的 CCR.DIV_0_TRP 比特置 1。
, Y! v% C" l" a, P4 W$ [: t3 `; S7 x6 L2 I
图 3 总结了 Usage 错误触发 Fault Handler 的一般情况。
0 t" v4 r( _% |  z8 G" y6 R. b& ^- L0 A  f& P
微信图片_20231130170520.png

2 e. q7 R5 ~  J- l9 @  c9 v
; ?2 o" g0 \/ W7 u只要 SHCSR.USGFAULTENA=1,UsageFault 总是触发软件对应安全状态的 UsageFault Handler,否则上升到 HardFault,安全侧的 UsageFault 总是上升到 Secure HardFault。对于非安全侧的 UsageFault,如果 AIRCR.BFHFNMINS=0,则上升到 Secure HardFault,否则上升到 Non-Secure HardFault。
; k* _, h9 q& B6 }2 y  y1 H1 t* U5 G4 A) U, T
使能或禁止 UsageFault 的示例代码如下:
) O: ?) R7 y7 d6 D& i
  1. void EnableUsageFault(int enable)' S7 {( d: q6 Z$ ^- g) L3 \: O
  2. {$ i8 T$ f- E5 W1 |8 H0 r
  3. if( enable == 1)
    - r/ u9 n6 @: C0 s! K+ f( l' q
  4. {
    ! K9 x! q5 Z0 o: ?4 b. G5 R3 I
  5. SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;3 x! t, ]6 F: E. `3 ^( ]/ [
  6. /* Enable divide by 0 trap to trigger usage fault (if necessary) */( A. V! S, G% m( }8 K5 \
  7. SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;9 [9 K) [' _2 W$ M8 o$ Q
  8. }8 D, X1 H0 J6 r6 }
  9. else
    : r- J5 K$ \1 P4 Z8 i! q
  10. SCB->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    / k3 y6 B; s) C. S3 \1 C3 `
  11. }
复制代码
: X, ]% k8 x( W2 ^* v
如果安全和非安全侧都需要使能 UsageFault,则 S、NS 代码可以分别调用这段代码使能各自的 UsageFault,或者 S 安全侧代码也可以直接控制 NS 非安全侧 UsageFault 的使能,例如可以在 S 安全侧增加下面这段代码来决定 NS 侧的 UsageFault 是否使能。
* H+ o/ C  s8 t# X: M
  1. void EnableNSUsageFault(int enable)
    4 G, u, F2 Q, x; D& Q
  2. {
    ! {8 m# \3 i  \0 L( a# r
  3. if( enable == 1)7 W  Q4 d4 F, o- S
  4. SCB_NS->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;, S- `! q  n# H& s4 ]
  5. else0 ~* c  c- V5 d6 m  \9 ]
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    2 {% I; s# v6 h- J) [6 i9 _) v
  7. }
复制代码

+ P8 O" d" P% }# y: l. \% h* |! F+ k: X1.1.4. MemManage Fault
  F1 k+ `& G( l) C" U, mMemManage Fault 是由于 Memory 保护产生的故障异常,例如在取指令或进行数据访问时违反了 MPU region 定义的访问规则,或者违反了默认地址保护规则。
8 a' `3 g# X- k: Q' f) o. h; q. |7 v3 E5 C. z3 ?
MemManageFault 与 UsageFault 类似,也是默认不使能,如果希望使能 S 或者 NS 侧的MemManageFault,需要相应将 SCB_S 或者 SCB_NS 的 SHCSR.MEMFAULTENA 比特置位。, G9 |! }3 N* X( {* r' {+ |

# Y$ k2 b7 h+ |# k+ O另外也与 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 处于非安全状态时候的访问,二者互不影响。
* \. a3 N6 E& f) [( N; \
/ T9 \, |& R4 |$ b+ a图 4 给出了 MemManage 故障触发 Fault Handler 的一般情况。如果 S 安全代码违反memory 访问规则,可能会触发安全侧的 MemManageFault,或者 Secure HardFault。非安全代码违反 memory 访问规则,可能会触发非安全侧的 MemManageFault,或者上升到HardFault,如果 AIRCR.BFHFNMINS=0 上升到 Secure HardFault,否则上升到 Non-Secure HardFault。) E! U- u. a' K3 x
微信图片_20231130170516.png

( ~( w0 d( ]/ z8 Q( o
微信图片_20231130170512.png
& B# ~7 `& L1 {

2 i  k9 m& M: r# L使能或禁止 MemManage Fault 的示例代码如下:
' E. s+ N# h; B9 s+ ^( w. N; H
  1. void EnableMemoryFault(int enable)
    ( F9 _8 F/ W( D& k2 r( b& A
  2. {
    : k1 ~9 H' `" M- v. ^
  3. if( enable == 1)+ t8 [! ~9 _5 P
  4. SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;$ e  @4 f  ]1 D  W; X; K
  5. else
    " \0 F5 D; t3 @' `
  6. SCB->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);
    + x, c  v$ y/ e' \& e' ^
  7. }
复制代码

- b# G1 ^1 q* F$ C+ k如果安全和非安全侧都需要使能 MemManage Fault,则 S、NS 应用可以分别调用这段代码使能各自的 MemManage Fault,或者 S 安全侧代码也可以直接使能 NS 非安全侧的MemManage Fault,例如可以在 S 安全侧增加下面这段代码来控制 NS 侧的 MemManageFault 使能。
) `8 D5 P; H3 X+ I2 Y7 a8 j
  1. void EnableNSMemoryFault (int enable)
    ; J- L$ N7 v8 V) \" D
  2. {
    % R. B: g7 N/ N0 t1 H) {* B
  3. if( enable == 1)6 f9 s: `$ [; C8 S& t, G
  4. SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
    1 j5 l' d4 l& X& P2 Q5 B" q
  5. else- Q( T! M: I1 m3 L  N6 q; ?4 q# \
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);
    3 @. B& ^  e/ w: Q1 H
  7. }
复制代码
- h/ h8 P' C% ]" Z: E/ T1 A
另外,如果代码使用 HAL API 使能 MPU,即调用 HAL_MPU_Enable(),那么MemManage Fault 在 MPU 使能的函数中会自动被使能,这时候无需额外调用前面提到的代码去单独使能 MemManage Fault。
: G% j6 L; N; y2 O
" m$ `5 Q) X* L0 n, l0 X: S! ^1.1.5. Secure Fault/ G* ]  \: F6 P& r% w
Secure Fault 只有在 TrustZone 使能的环境下才存在。SecureFault 可能由于内核中各种各样的安全检查而触发,例如从 NS 跳转至 S 代码时没有从 SG 入口指令进入,或者非安全代码试图访问 SAU/IDAU 规定的安全地址范围等。通常当出现 SecureFault 时,软件的处理可以是直接停止或者复位系统,这样做可以尽可能地避免引入安全漏洞。
" B( S; d8 M2 _( Y& g
  i! m$ V) ~/ _  RSecureFault 不是 Bank 的,总是 target 到 S 侧,因此只有安全代码能够处理SecureFault。SecureFault 缺省也没有使能,出现 Secure 错误时,默认触发 SecureHardFault。软件可以通过置位 SHCSR.SECUREFAULTENA 来单独使能 SecureFault,使能后Secure 错误将触发 SecureFault Handler。图 5 给出了 Secure 错误触发 Fault Handler 的一般情况。8 o  ]2 `9 i4 Q
0 X3 g$ A, b# }4 c6 H$ {! w( Z3 X5 D
微信图片_20231130170508.png

& v/ s9 _0 |1 D* @8 H4 R* V- I
微信图片_20231130170459.png

7 ?, A( x% ]$ W6 n% t" z; k' U( |
使能或禁止 SecureFault 的示例代码如下:
% E6 A) K! W) q8 ?
  1. void EnableSecureFault(int enable)
    - {, ^1 k0 Z2 Y
  2. {
    ! T, R6 s- b$ {! x7 C# H
  3. if( enable == 1)
    ( d+ W' e0 d6 n
  4. SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk;8 I9 b: v. R# Z0 `6 [
  5. else4 i5 |! h: g0 k2 S/ l
  6. SCB->SHCSR &= (~SCB_SHCSR_SECUREFAULTENA_Msk);7 y2 M0 [+ ?2 V& r1 X. |9 p
  7. }
复制代码
7 y1 U5 ~1 ?+ T' |# F
1.2. 故障升级与 HardFault
) {/ `9 B+ v$ o, h  Z0 X9 T0 M除了 HardFault 以外,其他故障类型都具有可配置的优先级。软件可以禁止某个可配优先级的故障异常,但是不能禁止 HardFault。故障异常的优先级和对应的 mask bit 决定了内核是否会进入某个故障的处理程序,以及某个故障是否可以抢占另一个故障。6 s. p7 K' W7 s

0 h# L0 N: ?5 W9 g6 f. e& n某些情况下,可配置优先级的故障可能会被当成 HardFault 处理,也就是故障升级或称中断上访,此时,这个具体的 Fault 会升级为 HardFault 故障。
6 b7 e2 _+ ^$ k  a0 r某个 Fault 升级成 HardFault 可能有多种原因,例如:0 C1 ]* P; N# i* }0 e/ Q) M1 T
该故障 Fault 没有使能;2 ]2 B8 Y& G2 n0 l' s: m/ `) o

" I8 h  P& ]$ x! i" a例如,代码由于执行未定义的指令产生了 UsageFault,但是 UsageFault 没有被使能.
& M: x2 `! M: L/ B0 N3 f: p- z+ C% g该故障的 FaultHandler 优先级不够高无法运行;7 m; ^) @% O& U( \7 @# `- O

9 Z# ~' A7 N* S' w9 F例如,系统配置并使能了 MPU,CPU 正在执行某个中断操作,该操作试图进行地址访问时违反了 MPU 定义的访问规则,进而触发了故障,但是当前执行的中断的优先级高于 MemManage 故障的优先级。! c, `( a: ~% ?( r( z
在故障的 FaultHandler 中产生了同样的故障;; J5 p' c; N4 h' c$ T1 o) ]% R
- S# _0 n* ?1 t* }2 Y8 z
例如,在处理 UsageFault 的 handler 中又发生了未定义指令的情况。
( W% Q; p) |' H; r9 M+ `如果在进入 BusFault Handler 的时候,压栈操作又导致了 BusFault,这种情况下 BusFault 不会升级到 HardFault。这意味着,如果损坏的堆栈导致故障,即使 Fault Handler 压栈失败,故障处理程序还是会执行,但堆栈内容已损坏。
  s& h; `0 [0 Y* i% E( r9 A$ i1 L' j只有 NMI 可以抢占 HardFault,HardFault 可以抢占任何除 Reset、NMI 或者另一个HardFault 以外的异常。当 BFHFNMINS=1 时,如果 NS 侧的 NMI Handler 产生了安全违规错误,那么它将触发 Secure HardFault,并被其抢占。
5 Z* k6 A2 ^; q" R8 ^5 t% M在获取异常向量的时候发生的 Bus 错误,总是升级到 HardFault,由 HardFault 处理,而非 BusFault。
+ ?1 L8 i0 d* Y9 L/ h1 e$ S3 C
. k- v' B: G/ e% ~- k3 W0 K+ T) t1.3. Fault 异常的安全状态
/ j$ h! w$ y% A& ^2 }& M3 F在 TrustZone 使能的环境中,故障异常可能 target 到 S 安全状态或 NS 非安全状态,这会导致 ARMv8-M 内核的行为与以往 ARMv6-M 及 ARMv7-M 内核有很大不同,TrustZone 环境软件开发中对 Fault 的处理要特别注意到这一点。& F$ E2 w, l& r# T5 B. x
关于 Fault 异常 target 到 S、NS 的情况在前文中介绍几个 Fault 类型的时候已经有提到,这里在表 2 中再稍加总结。/ h2 b% Y' T+ g( O9 }7 z

4 j% N6 Q4 u4 a" [( W( R6 y
微信图片_20231130170455.png
! n7 Q; Y2 W( `( c
+ }0 x1 V" L: P( V5 {1 \0 K% I; [
1.4. 异常的进入与返回( g# |: n/ [2 {" \/ K/ T; k9 v
1.4.1. 异常的进入与 stack frame0 X& Y. v& I5 F- P! s" ?
当处理器处于线程模式且系统存在具有足够优先级的 pending 异常时则会进入异常,或者新异常的优先级高于正在处理的异常,这时候新异常将抢占原始异常,即出现异常嵌套。  j: q! @; O- t. H& U7 y4 N! x  Y
当处理器发生异常时,除非该异常是尾链异常或延迟到达的异常,否则处理器会将上下文信息压入堆栈,压栈的数据结构即 stack frame。
$ d, W1 D" `3 |& n0 w. t通常 stack frame 的内容如图 6 (a) 所示,包含了 R0 到 R3、R12、LR、PC 和 xPSR 的内容。在 TrustZone 使能的环境中,如果 S 安全代码执行被 NS 非安全异常抢占,那么进入非安全异常前会有更多的信息压栈,如图 6 (b)所示,并且硬件会自动将压栈的寄存器清零,防止任何安全状态下的数据暴露给非安全代码。
2 j6 i: T1 o$ c- b如果使用了浮点功能,存在浮点上下文,那么内核也会自动将浮点相关的上下文内容压栈。由于浮点部分数据内容对我们通常的 Fault 调试没有太多帮助,这里不做赘述。
' t% N. p( x' _/ `! ^/ A% J9 E进入异常前的 stack frame 压栈操作使用 MSP 还是 PSP,取决于当时内核的运行状态及其使用的堆栈。如果当时 CPU 运行于 Handler 模式,则使用 MSP 压栈 stack frame;如果 CPU运行于 Thread 模式,由当时的 CPU CONTROL.SPSEL 位来标记使用的堆栈。0 f9 U. H3 R9 E5 T

8 O( j- l% [( }' W, L4 g% @% D0 v6 i
' V+ p9 {4 l( ]
转载自: STM32. E, w3 V! O5 n/ f- Y4 f
如有侵权请联系删除
! a. I; M, a  D0 U/ Q/ c, Y
  u: s3 X& o! |9 E7 O5 e6 x

* o# r6 V. N. w' l
! X5 h" ~. G" U2 S, o3 O7 R
收藏 评论0 发布时间:2023-11-30 17:05

举报

0个回答

所属标签

相似分享

官网相关资源

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