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

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

[复制链接]
STMCU小助手 发布时间:2023-11-30 17:05
引  言) V" |1 }5 Y* Q1 T! \3 q
在 STM32 TrustZone 开发调试技巧的前两篇中,我们介绍了内核的 SAU/IDAU,地址的安全属性配置,资源的安全属性配置,内核访问资源的安全规则,以及 TrustZone 环境下外设使用的常见问题等内容。TrustZone 环境开发中还可能经常遇到的一个问题就是软件触发的故障错误。ARM CM33内核 TrustZone 环境下的异常模型以及 Fault 的处理与不带安全扩展的情况有着很多变化,一旦出现 HardFault,经验不足的开发者可能往会找不到头绪,不知道从哪里着手寻找问题所在。因此,在这一篇的重点将围绕 CM33 TrustZone 环境下的异常模型以及 HardFault 的调试与处理展开,供开发者参考。
$ f& m- B0 R, f* {, k! W  `; d) S% D9 h# H
一、CM33 TrustZone 架构下的异常模型, H5 A' z3 a6 @. t( X
在 STM32 TrustZone 开发调试技巧的第二篇中我们介绍过 CM33 带安全扩展的 S 和 NS 侧的中断以及中断向量表,这里不再赘述。表 1 总结了其中的 Fault 异常。
) C2 _4 U1 }; P- B% l3 l9 C2 t& t) b# y3 z9 k; m9 s) b, G
微信图片_20231130170530.png

/ ]; I( l; }' {  S( R( l# w9 `$ Z$ E% w/ D, k# F$ j
1.1. Fault 异常类型(带安全扩展); S' O) i$ I( K+ c5 t# F' K* S
1.1.1. Hard Fault
; `- ?" P, V8 H# ~% QHardFault 是默认的 Fault 异常,总是使能。触发的原因可能是由于异常处理本身触发了错误,或者某个异常无法被其他机制处理而上升到 HardFault。它的优先级高于所有其他可配置优先级的异常。3 Z' R8 f' r; H9 U0 J! a& o8 ~

1 a* K& Q2 }) H7 g: k' m在 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 触发一般情形。
* U% A7 e; U$ M9 q1 i$ M0 \6 S0 e5 F$ C, f4 A
7 t2 e- j: H$ F% r9 c
微信图片_20231130170527.png

# U4 l% ~; Q: Y. e
6 o* w; Y5 h1 k# {需要注意的是,即使 AIRCR.BFHFNMINS=1,原本 target 到 S 侧并且上升为 HardFault 的异常,将依旧触发 S 侧的 HardFault,他们并不受到 AIRCR.BFHFNMINS 位的影响,例如当安全代码违反 MPU 保护规则,产生 MemManage 错误的时候,即使 AIRCR.BFHFNMINS=1,故障还是会进入 Secure HardFault Handler。而 NS 侧的 HardFault,只有当AIRCR.BFHFNMINS=1 时才有可能会被触发。9 [4 R3 O: U4 @: K! T
4 }3 _2 s: k& u4 \/ e9 x- M
另外还要注意一点,AIRCR 寄存器不能直接修改,需要先写 Key 值才能更改寄存器内容。置位或清除 AIRCR.BFHFNMINS bit 的示例代码如下(只能在安全代码中使用):2 D5 \/ n9 s& e! {4 v7 m
  1. void SECURE_SetNMIHFBFTarget(int NS)
    , S' G5 n: y8 L1 l3 H" G7 H
  2. {9 r2 K! |* ?  g
  3. uint32_t reg_value;
    : R7 N5 A$ L1 Z$ o3 f( O7 _) s( X
  4. uint32_t target = (NS==1)?1:0;
    4 s8 g1 o$ \; v3 ~1 P5 h
  5. /* read old register configuration */
    4 [( Y- I8 e5 }8 `( M/ t
  6. reg_value = SCB->AIRCR;% J0 ~/ X! c; O; q, G/ ?
  7. /* clear bits to change */% ]0 u- _+ }, D3 @
  8. reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_BFHFNMINS_Msk));7 r+ J, M) M3 i: K  O
  9. /* insert write key and target bit */
    7 i+ _$ }3 }; N+ h; `2 i+ Q/ R
  10. reg_value = (reg_value |
    2 a' c' I/ ~3 ^! I8 t% t$ B+ O. Y
  11. ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |; t2 W& p, @3 K* i+ a
  12. (target << SCB_AIRCR_BFHFNMINS_Pos) );8 ~$ \( R5 \+ `+ T. {
  13. SCB->AIRCR = reg_value;
    ; [$ r% [* m( j, q4 T3 P9 |8 T9 H% O
  14. }
复制代码
0 r- e/ \8 b+ m# B$ O% h
注意:有的时候,软件可能需要设置 AIRCR.PRIS 位,来整体降低 NS 中断的优先级(例如在 TF-M 的实现中就使用这个机制)。这时候,如果同时设置 AIRCR.PRIS=1,AIRCR.BFHFNMINS=1,内核的行为将不可预测。因此如果需要设置 AIRCR.PRIS=1,则建议保持 AIRCR.BFHFNMINS=0。2 @+ A1 F6 a$ U, o: L/ F& S( H* F
) \7 _' Z2 g; M  [" f

7 W& E( `  u  i& G3 u- ]1.1.2. Bus Fault9 t& C: u& {3 K8 A" \: c
Bus Fault 通常发生在指令或数据访问时候,可能由于检测到 memory 系统的总线错误而导致。Bus Fault 默认不使能,就是说总线故障默认将触发 HardFault Handler。如果需要单独使能 Bus Fault,可以将 SCB 的 SHCSR.BUSFAULTENA 位设 1。7 x' Q7 y  U" H) M- V, t5 n
4 j7 J( f! k( ~' ]# Y% O
在 TrustZone 环境中,Bus Fault 也不是 Bank 的。触发 S 还是 NS 侧的 BusFault Handler与SCB 的AIRCR.BFHFNMINS 有关。如果 AIRCR.BFHFNMINS=0,BusFault 总是 target 到S 安全状态;反之如果 AIRCR.BFHFNMINS=1,则 target 到 NS 非安全状态。! T  O4 X" Q$ q
0 _7 f8 G2 b+ i1 I
产生 Bus 错误时,实际会触发哪个 Fault Handler,将取决于 AIRCR.BFHFNMINS 和SCB_S/NS 的 SHCSR.BUSFAULTENA 的设置。图 2 给出了 Bus 错误触发 Fault Handler 的一般情况(例如这里不考虑安全侧 Vector 错误依旧上升到 Secure HardFault 的情况)。& R- ?* B- P9 g' K. V% U
  I% R- ?6 ~/ u; z# V: \' v9 B
微信图片_20231130170523.png

8 D% z, a8 G; I& [/ B/ a' r  ]/ a
3 w/ O. @1 X1 H/ o7 k" n4 ^通常情况下,SCB 的 CFSR/BFSR 和 BFAR 寄存器中会标记总线故障信息。在 TrustZone环境中,SCB 的某些寄存器以及寄存器的某些比特位是 Bank 的。从安全侧和非安全侧都能够看到各自的 SCB 寄存器,但是 CFSR 寄存器的 BFSR 域以及 BFAR 寄存器并不是 Bank 的。而 Bus 故障可能 target 到 S 安全侧也可能 target 到 NS 非安全侧,当发生总线错误的时候,如果分别从 SCB_S、SCB_NS 的相关寄存器中读取 Bus Fault 的信息,可以看到不同的结果。8 K; X) y) t- N5 Y
; E8 H2 C- x0 z  Y. b9 A' e+ K* |
如果 AIRCR.BFHFNMINS=0,只有安全侧可以看到 BFSR 和 BFAR 的真实数据,非安全侧读取 BFSR、BFAR,或者从安全侧读取 BFSR_NS,BFAR_NS 都只能读到全 0 的值。
/ A! L( x3 _* H* [7 \  m( O
3 d0 s6 @) z" h. Z; B
如果 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 寄存器获取故障信息。
- G& @5 O5 u, Z) O* O

1 d; w/ X/ I5 hBusFault 默认没有单独使能,如果需要使能 BusFault,可以将 SHCSR 寄存器的BUSFAULTENA 位置位。使能或禁止 BusFault 的示例代码如下:
/ ]+ X$ l; Y9 @8 n
  1. void EnableBusFault(int enable)
    2 l- L+ E4 ~  t- Z
  2. {  d- _) w; J3 f0 e3 {6 }5 _
  3. if( enable == 1)
    + d; k5 h5 N' ^7 t" k
  4. SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;) a0 P% i# D1 X( q8 [6 ~
  5. else
    + H. B1 y, J3 U; j1 f$ R9 C+ Y
  6. SCB->SHCSR &= (~SCB_SHCSR_BUSFAULTENA_Msk);3 ~' _2 `% q" e/ r" Y5 b7 k  r
  7. }
复制代码
5 ]% Y1 o- n5 n  D+ N
这段代码对安全和非安全侧都是一样的,但是要注意,由于 BusFault 不是 Bank 的,当AIRCR.BFHFNMINS=0 时,这段代码只能在安全侧使用,也就是修改的是 S 安全侧 SCB SHCSR 的 BusFault,此时写 SCB_NS 的 SHCSR.BUSFAULTENA 位无效。/ e) \* J% C# t% j& R8 [. E$ v
2 Z+ a+ H+ D  S6 [, V
如果非安全侧应用使用这段代码使能 BusFault,那么前提是安全侧已经设置了AIRCR.BFHFNMINS=1。
, O( w- R: K; |; T6 K) ~4 }  t, k4 Q9 J
1.1.3. Usage Fault
# A. v9 j& E8 H! dUsageFault 与指令执行时候的错误有关,包括未定义的指令、非对齐访问、执行指令时的无效状态、中断返回时的错误、除 0 等。
8 `# z3 I" O2 `8 O( V3 ~" F
* m  u: @  Y5 A5 u# [在 TrustZone 环境中,UsageFault 是 Bank 的,因此在 S 和 NS 状态可能产生各自的UsageFault,并且可能触发各自的 S UsageFault Handler 和 NS UsageFault Handler。UsageFault 默认不使能,因而缺省会上升到 HardFault,是否触发 S 还是 NS 的 HardFault Handler 还要取决于 AIRCR.BFHFNMINS 的值是 0 还是 1。
: c, _' E( Q% F' t. y' e

2 p7 [1 @" O% Q使能UsageFault 需要分别设置 SCB_S 和 SCB_NS 的 SHCSR.USGFAULTENA。SCB_S的 SHCSR.USGFAULTENA=1 用于使能 S 安全侧的 Usage Fault;SCB_NS 的SHCSR.USGFAULTENA=1 用于使能 NS 非安全侧的 Usage Fault。
  K. N+ ]1 l, z
1 @' z$ O( L; Q) |4 H, V8 F2 a2 U" F
另外,通常除 0 操作不会触发 UsageFault,如果希望除 0 操作触发 UsageFault,需要将SCB_S/NS 对应的 CCR.DIV_0_TRP 比特置 1。( z* u$ I& |" @$ {7 u. D+ Z" A

" N# }7 H" |  u5 j6 K7 w图 3 总结了 Usage 错误触发 Fault Handler 的一般情况。7 O% W9 I" C1 p% H: Z

: M5 M- u' _: V, [; j4 `
微信图片_20231130170520.png
1 g- _5 ~  e/ n& K; L

/ c4 z& A" S4 [0 K只要 SHCSR.USGFAULTENA=1,UsageFault 总是触发软件对应安全状态的 UsageFault Handler,否则上升到 HardFault,安全侧的 UsageFault 总是上升到 Secure HardFault。对于非安全侧的 UsageFault,如果 AIRCR.BFHFNMINS=0,则上升到 Secure HardFault,否则上升到 Non-Secure HardFault。
  X. k. a$ n2 [/ M" J, g2 E4 u$ e1 }  |8 N8 _$ N. T+ H' r
使能或禁止 UsageFault 的示例代码如下:
4 s3 l% C( X2 x: u" Z; K! K
  1. void EnableUsageFault(int enable)
    ; D3 H- x$ H5 D& Y" P' C
  2. {1 r9 y" v, _4 g5 H# X
  3. if( enable == 1)
    1 \* n1 N- f$ ?9 o
  4. {( i. c! N& u+ D  x
  5. SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
    8 l* u" K- V* o
  6. /* Enable divide by 0 trap to trigger usage fault (if necessary) */$ X$ T' y) J0 f6 ^& F
  7. SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;+ _$ X9 }6 W6 k/ _1 I  C
  8. }
    7 ~% X$ b# C* \- B. T5 ~  B
  9. else2 t* Q6 T3 B, l& |
  10. SCB->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    ) [! ]5 N8 J! v5 _/ s. {5 P
  11. }
复制代码
- B# }7 D' a" q) A2 ]7 X# U3 A
如果安全和非安全侧都需要使能 UsageFault,则 S、NS 代码可以分别调用这段代码使能各自的 UsageFault,或者 S 安全侧代码也可以直接控制 NS 非安全侧 UsageFault 的使能,例如可以在 S 安全侧增加下面这段代码来决定 NS 侧的 UsageFault 是否使能。
4 `: W) n4 o0 {  X6 j% j
  1. void EnableNSUsageFault(int enable)
    : @: [, J2 g5 o, \
  2. {3 d% \9 k6 V/ Q% r  X* R6 {
  3. if( enable == 1)
    - J+ f5 K* o% d, f# f$ H6 [
  4. SCB_NS->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;# {+ @- s7 l0 o" l4 j
  5. else$ n! \' V) Z7 L4 y7 _
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    6 i* ]) g: q" h) k4 v( m
  7. }
复制代码
5 y1 e0 n: C$ m! m/ X" o
1.1.4. MemManage Fault
; ]5 \2 K$ f3 y) J9 y2 [( E0 RMemManage Fault 是由于 Memory 保护产生的故障异常,例如在取指令或进行数据访问时违反了 MPU region 定义的访问规则,或者违反了默认地址保护规则。
! s# y6 s& \# O7 ~. g+ K' o8 d* _; o% ]# j
MemManageFault 与 UsageFault 类似,也是默认不使能,如果希望使能 S 或者 NS 侧的MemManageFault,需要相应将 SCB_S 或者 SCB_NS 的 SHCSR.MEMFAULTENA 比特置位。! i: C7 U' q$ v/ |3 q' W

, e- ]. F: T; [5 n6 l* }另外也与 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 处于非安全状态时候的访问,二者互不影响。& q& W6 L0 o; A; Y( {- \

2 A& s4 B5 i* c- M- s8 l0 w图 4 给出了 MemManage 故障触发 Fault Handler 的一般情况。如果 S 安全代码违反memory 访问规则,可能会触发安全侧的 MemManageFault,或者 Secure HardFault。非安全代码违反 memory 访问规则,可能会触发非安全侧的 MemManageFault,或者上升到HardFault,如果 AIRCR.BFHFNMINS=0 上升到 Secure HardFault,否则上升到 Non-Secure HardFault。
8 k! Z4 D8 a% ]' ?" d! M/ |
微信图片_20231130170516.png
! \6 k' n8 r' Y$ R; e; j$ `; X
微信图片_20231130170512.png
3 n) b9 Z+ o- |4 i9 q$ r
) w5 d+ M+ l& Y, Y6 G8 C* B5 Q3 V
使能或禁止 MemManage Fault 的示例代码如下:
/ e* U- g: g) H8 A& F; b
  1. void EnableMemoryFault(int enable)
    . L6 C0 {( w" Z: Z: I# L: G* f
  2. {
    7 g& x4 `* y: m, z- p
  3. if( enable == 1)
    ' R  Q' O& u2 x" c0 [# J' {' ?
  4. SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
    9 L, y; r! \+ {1 r: _8 X3 o
  5. else
    " V) J. X+ Z' {2 O  ]- r
  6. SCB->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);3 S3 ^7 D) V: ]
  7. }
复制代码

* \5 ^4 i! ]& O2 G, S: g1 D如果安全和非安全侧都需要使能 MemManage Fault,则 S、NS 应用可以分别调用这段代码使能各自的 MemManage Fault,或者 S 安全侧代码也可以直接使能 NS 非安全侧的MemManage Fault,例如可以在 S 安全侧增加下面这段代码来控制 NS 侧的 MemManageFault 使能。
; u; k0 f- n4 X3 f4 G3 D" \1 |8 v
  1. void EnableNSMemoryFault (int enable)% Y! `2 ?3 J$ ?7 U, @4 X7 @
  2. {
    8 @* R' t1 n7 T! ^; T4 [* X8 i+ P" y( p
  3. if( enable == 1)
    # A4 g5 j3 b$ I! y
  4. SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;0 q4 B! }/ p, u; n( _
  5. else
    " G, E' R# @/ H( G. N' Z1 m/ Q
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);/ _1 B6 z; m* j& \+ J, t4 ?
  7. }
复制代码
; V! q" W6 e6 r9 W2 r
另外,如果代码使用 HAL API 使能 MPU,即调用 HAL_MPU_Enable(),那么MemManage Fault 在 MPU 使能的函数中会自动被使能,这时候无需额外调用前面提到的代码去单独使能 MemManage Fault。' z) V  M9 c5 N! F  m8 K5 m" K

2 t# n% R' K4 a1.1.5. Secure Fault
7 v* X. L6 v# GSecure Fault 只有在 TrustZone 使能的环境下才存在。SecureFault 可能由于内核中各种各样的安全检查而触发,例如从 NS 跳转至 S 代码时没有从 SG 入口指令进入,或者非安全代码试图访问 SAU/IDAU 规定的安全地址范围等。通常当出现 SecureFault 时,软件的处理可以是直接停止或者复位系统,这样做可以尽可能地避免引入安全漏洞。
! v: u, f  O' d" \
+ h+ g. K( d& z6 WSecureFault 不是 Bank 的,总是 target 到 S 侧,因此只有安全代码能够处理SecureFault。SecureFault 缺省也没有使能,出现 Secure 错误时,默认触发 SecureHardFault。软件可以通过置位 SHCSR.SECUREFAULTENA 来单独使能 SecureFault,使能后Secure 错误将触发 SecureFault Handler。图 5 给出了 Secure 错误触发 Fault Handler 的一般情况。' J8 f7 j( [. h5 H3 D% Q2 @
7 q+ X' f  u! `5 v' I$ ~8 w
微信图片_20231130170508.png
1 l3 M) ~1 _$ M% \6 Y- w6 [
微信图片_20231130170459.png

% `2 ]/ {" j5 r# m" n0 b5 {, {& Y2 ?, x9 i% `) G0 H, o2 W
使能或禁止 SecureFault 的示例代码如下:5 g( D6 p* ]8 o) e4 l
  1. void EnableSecureFault(int enable)
    - i) r# D) Z. K  G, c* K# \0 @* v+ l
  2. {/ L6 Z) E; }! m5 O; Q1 d& J4 _" c
  3. if( enable == 1)" P. O9 Y% M' O5 d
  4. SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk;
    5 N% i$ s  v" }- L
  5. else# G6 M/ o6 _: T2 Z
  6. SCB->SHCSR &= (~SCB_SHCSR_SECUREFAULTENA_Msk);3 o! N  k7 E' B$ @
  7. }
复制代码

$ c8 {5 s+ O& n# ?1.2. 故障升级与 HardFault5 L) ?" u6 l! v5 J6 ~7 ^3 _  j: m
除了 HardFault 以外,其他故障类型都具有可配置的优先级。软件可以禁止某个可配优先级的故障异常,但是不能禁止 HardFault。故障异常的优先级和对应的 mask bit 决定了内核是否会进入某个故障的处理程序,以及某个故障是否可以抢占另一个故障。
/ X% F, a6 v+ i' I; q

, I" Z5 Q0 C; ^8 @+ E- y! C某些情况下,可配置优先级的故障可能会被当成 HardFault 处理,也就是故障升级或称中断上访,此时,这个具体的 Fault 会升级为 HardFault 故障。$ C# Q& C, D' s  [/ V
某个 Fault 升级成 HardFault 可能有多种原因,例如:
- r4 J/ ^, d& }: v; E) c该故障 Fault 没有使能;
& E* p  I( F* E/ R: K  M- \+ h# _
例如,代码由于执行未定义的指令产生了 UsageFault,但是 UsageFault 没有被使能.+ Q' K+ F3 r0 s
该故障的 FaultHandler 优先级不够高无法运行;  [/ R; ?; \, t" Z8 E! P" `

  |. Y9 E  o. s$ h$ f例如,系统配置并使能了 MPU,CPU 正在执行某个中断操作,该操作试图进行地址访问时违反了 MPU 定义的访问规则,进而触发了故障,但是当前执行的中断的优先级高于 MemManage 故障的优先级。% R0 j+ @7 V5 z; L
在故障的 FaultHandler 中产生了同样的故障;( X( _# K: j" N. a! q4 ?+ s
2 P" @' Q4 O" i2 Y
例如,在处理 UsageFault 的 handler 中又发生了未定义指令的情况。/ r9 ^; ?4 |/ W9 {: X! I" _
如果在进入 BusFault Handler 的时候,压栈操作又导致了 BusFault,这种情况下 BusFault 不会升级到 HardFault。这意味着,如果损坏的堆栈导致故障,即使 Fault Handler 压栈失败,故障处理程序还是会执行,但堆栈内容已损坏。
1 _- m: r! q! r# w  Y, p只有 NMI 可以抢占 HardFault,HardFault 可以抢占任何除 Reset、NMI 或者另一个HardFault 以外的异常。当 BFHFNMINS=1 时,如果 NS 侧的 NMI Handler 产生了安全违规错误,那么它将触发 Secure HardFault,并被其抢占。& R! _. R+ j# Z& u3 W8 j$ S# C# x
在获取异常向量的时候发生的 Bus 错误,总是升级到 HardFault,由 HardFault 处理,而非 BusFault。
# P! X. i0 R* v4 N$ f
1 c+ H* S1 m- Y3 h# h1.3. Fault 异常的安全状态7 c5 X. V+ t; ^4 ^/ G- F
在 TrustZone 使能的环境中,故障异常可能 target 到 S 安全状态或 NS 非安全状态,这会导致 ARMv8-M 内核的行为与以往 ARMv6-M 及 ARMv7-M 内核有很大不同,TrustZone 环境软件开发中对 Fault 的处理要特别注意到这一点。+ @# I+ f8 V8 W: {8 `! c
关于 Fault 异常 target 到 S、NS 的情况在前文中介绍几个 Fault 类型的时候已经有提到,这里在表 2 中再稍加总结。
" C1 {, U  j" t8 v/ m% A' d8 B* X1 k( w" a
微信图片_20231130170455.png

& ^* Y# M1 @+ r3 h3 W
4 L) L7 C3 H* L! E) c$ |1 e1.4. 异常的进入与返回
6 v- _- `1 `+ b. }1.4.1. 异常的进入与 stack frame
, l3 A. p8 M/ L5 H' |8 x当处理器处于线程模式且系统存在具有足够优先级的 pending 异常时则会进入异常,或者新异常的优先级高于正在处理的异常,这时候新异常将抢占原始异常,即出现异常嵌套。
2 R( E( o: ^# K1 t当处理器发生异常时,除非该异常是尾链异常或延迟到达的异常,否则处理器会将上下文信息压入堆栈,压栈的数据结构即 stack frame。( v' ^, h. Z: h8 T1 ]: f
通常 stack frame 的内容如图 6 (a) 所示,包含了 R0 到 R3、R12、LR、PC 和 xPSR 的内容。在 TrustZone 使能的环境中,如果 S 安全代码执行被 NS 非安全异常抢占,那么进入非安全异常前会有更多的信息压栈,如图 6 (b)所示,并且硬件会自动将压栈的寄存器清零,防止任何安全状态下的数据暴露给非安全代码。- W3 P& l! P4 v: \' P" v; N
如果使用了浮点功能,存在浮点上下文,那么内核也会自动将浮点相关的上下文内容压栈。由于浮点部分数据内容对我们通常的 Fault 调试没有太多帮助,这里不做赘述。0 f  a2 E  M3 z
进入异常前的 stack frame 压栈操作使用 MSP 还是 PSP,取决于当时内核的运行状态及其使用的堆栈。如果当时 CPU 运行于 Handler 模式,则使用 MSP 压栈 stack frame;如果 CPU运行于 Thread 模式,由当时的 CPU CONTROL.SPSEL 位来标记使用的堆栈。
6 k  `7 Z, X2 Q( m6 k. X- A  _* ~; Y) B. ^, c
9 O" j8 Y8 V. B, l
转载自: STM32
$ b& H3 Q2 L% A, m7 F$ T; L" R如有侵权请联系删除
* r/ S. {2 o( \* K  t; H; J5 \4 e: @. P8 V
0 Z9 K- Z; T  a1 P4 w4 a

8 ^+ ?+ _7 Z+ K* w- T9 W
收藏 评论0 发布时间:2023-11-30 17:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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