请选择 进入手机版 | 继续访问电脑版

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

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

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

, W- Q0 h$ Z9 n/ U1 Y4 N一、CM33 TrustZone 架构下的异常模型
( u; R* \$ Y! v* m: ?: w4 p  y在 STM32 TrustZone 开发调试技巧的第二篇中我们介绍过 CM33 带安全扩展的 S 和 NS 侧的中断以及中断向量表,这里不再赘述。表 1 总结了其中的 Fault 异常。( C: l; B5 l& I1 g  K+ `

; Y$ `( \4 h- M/ u# N7 P( Y
微信图片_20231130170530.png

5 R& r" t, n- h6 q
: @" }. ~" k* G- \, A+ M1.1. Fault 异常类型(带安全扩展)7 T# P3 e0 d; q! w% t) b; b
1.1.1. Hard Fault
6 W& H' Y# s6 O. Y4 vHardFault 是默认的 Fault 异常,总是使能。触发的原因可能是由于异常处理本身触发了错误,或者某个异常无法被其他机制处理而上升到 HardFault。它的优先级高于所有其他可配置优先级的异常。* G2 y- E  j# n2 ]' V
2 x$ _7 @7 H( b" j7 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 触发一般情形。' X7 T9 C4 {' w$ C7 k
- I+ t) D1 i4 J! Q$ A+ ?7 J  m
5 t1 l! [. d# c
微信图片_20231130170527.png

, D- a# D* S/ ^& F# D0 q+ O7 x8 h( K0 F3 Y: ~
需要注意的是,即使 AIRCR.BFHFNMINS=1,原本 target 到 S 侧并且上升为 HardFault 的异常,将依旧触发 S 侧的 HardFault,他们并不受到 AIRCR.BFHFNMINS 位的影响,例如当安全代码违反 MPU 保护规则,产生 MemManage 错误的时候,即使 AIRCR.BFHFNMINS=1,故障还是会进入 Secure HardFault Handler。而 NS 侧的 HardFault,只有当AIRCR.BFHFNMINS=1 时才有可能会被触发。
. K, x1 U0 i% C" U+ D" v. r; i# c% ~) b, w& c
另外还要注意一点,AIRCR 寄存器不能直接修改,需要先写 Key 值才能更改寄存器内容。置位或清除 AIRCR.BFHFNMINS bit 的示例代码如下(只能在安全代码中使用):
2 L: j( t/ n6 w
  1. void SECURE_SetNMIHFBFTarget(int NS)
    ( V5 `4 s$ Q6 a
  2. {
    ; R2 D$ g! V0 d* b( F! ~$ o
  3. uint32_t reg_value;& f8 W" Z3 W$ U% a! ?
  4. uint32_t target = (NS==1)?1:0;
    7 f# D3 }: |# F6 U. J8 b5 M
  5. /* read old register configuration */8 @2 j) N! D4 T, s4 U$ J
  6. reg_value = SCB->AIRCR;
    & B$ G+ k/ o8 i& p- _
  7. /* clear bits to change */6 @* o: z, H5 f) r/ h
  8. reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_BFHFNMINS_Msk));
    0 K  E$ f. e* b" A' O  w8 n, \; }
  9. /* insert write key and target bit */
    8 V( J# p/ s" a+ @$ Z2 G. K% {3 S
  10. reg_value = (reg_value |, }& |0 ?" A* [' c3 X$ x
  11. ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
    # L# j$ h- Z9 {9 L
  12. (target << SCB_AIRCR_BFHFNMINS_Pos) );1 S; Z3 M; N- N% g5 ]
  13. SCB->AIRCR = reg_value;5 x. ~" @( g: m$ d: s1 v' M5 k
  14. }
复制代码

' z+ H* @# {/ N! y5 ]9 A* q: q注意:有的时候,软件可能需要设置 AIRCR.PRIS 位,来整体降低 NS 中断的优先级(例如在 TF-M 的实现中就使用这个机制)。这时候,如果同时设置 AIRCR.PRIS=1,AIRCR.BFHFNMINS=1,内核的行为将不可预测。因此如果需要设置 AIRCR.PRIS=1,则建议保持 AIRCR.BFHFNMINS=0。" t" G3 [0 w' P: r& w5 r
8 z: J' T7 g$ ]1 C3 ]  F

) [& k; s0 I7 F$ g! o2 f, F1.1.2. Bus Fault0 o1 I4 P2 }4 |' @: M
Bus Fault 通常发生在指令或数据访问时候,可能由于检测到 memory 系统的总线错误而导致。Bus Fault 默认不使能,就是说总线故障默认将触发 HardFault Handler。如果需要单独使能 Bus Fault,可以将 SCB 的 SHCSR.BUSFAULTENA 位设 1。
5 a" [# H; v# _" b  m! ~2 D1 u

; e, [6 ^- a5 d. x1 j( a  ^在 TrustZone 环境中,Bus Fault 也不是 Bank 的。触发 S 还是 NS 侧的 BusFault Handler与SCB 的AIRCR.BFHFNMINS 有关。如果 AIRCR.BFHFNMINS=0,BusFault 总是 target 到S 安全状态;反之如果 AIRCR.BFHFNMINS=1,则 target 到 NS 非安全状态。) f7 I# W) T" C& R& d. c

/ h5 @+ J0 [. Q' h0 N产生 Bus 错误时,实际会触发哪个 Fault Handler,将取决于 AIRCR.BFHFNMINS 和SCB_S/NS 的 SHCSR.BUSFAULTENA 的设置。图 2 给出了 Bus 错误触发 Fault Handler 的一般情况(例如这里不考虑安全侧 Vector 错误依旧上升到 Secure HardFault 的情况)。+ ~5 _) Z. B# X$ ], c
! [0 a5 f7 V$ S8 s( Q
微信图片_20231130170523.png

: @# F1 ]+ v( \6 ]7 h% N7 u4 @0 w! i% O1 [, L  _" y) s
通常情况下,SCB 的 CFSR/BFSR 和 BFAR 寄存器中会标记总线故障信息。在 TrustZone环境中,SCB 的某些寄存器以及寄存器的某些比特位是 Bank 的。从安全侧和非安全侧都能够看到各自的 SCB 寄存器,但是 CFSR 寄存器的 BFSR 域以及 BFAR 寄存器并不是 Bank 的。而 Bus 故障可能 target 到 S 安全侧也可能 target 到 NS 非安全侧,当发生总线错误的时候,如果分别从 SCB_S、SCB_NS 的相关寄存器中读取 Bus Fault 的信息,可以看到不同的结果。
" n! Y5 z! a+ ~8 G( ]3 E; ^1 N9 r, ~# j' o' A
如果 AIRCR.BFHFNMINS=0,只有安全侧可以看到 BFSR 和 BFAR 的真实数据,非安全侧读取 BFSR、BFAR,或者从安全侧读取 BFSR_NS,BFAR_NS 都只能读到全 0 的值。) ]0 {4 ?, E( F- _0 K8 m# h* J+ i
  L( U5 B2 ?/ I; O( f% w1 G1 b0 C; Z7 j
如果 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 寄存器获取故障信息。
( e& n7 L$ ?6 V/ x) }

4 \7 X! U0 n( x6 B9 c7 z( wBusFault 默认没有单独使能,如果需要使能 BusFault,可以将 SHCSR 寄存器的BUSFAULTENA 位置位。使能或禁止 BusFault 的示例代码如下:
. U! N* u9 a/ x& H& L
  1. void EnableBusFault(int enable)
    + u3 }, J7 p5 C
  2. {
    ! E/ _0 j8 o! ~* m
  3. if( enable == 1)$ q/ F' }3 p2 q" B- @
  4. SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
    + i+ e" i0 Z' g1 i' C
  5. else
    : x; B/ V  Z* F" Y( t3 n0 W
  6. SCB->SHCSR &= (~SCB_SHCSR_BUSFAULTENA_Msk);% l! d2 A2 G0 \  Z
  7. }
复制代码

0 r" v, L+ W" S这段代码对安全和非安全侧都是一样的,但是要注意,由于 BusFault 不是 Bank 的,当AIRCR.BFHFNMINS=0 时,这段代码只能在安全侧使用,也就是修改的是 S 安全侧 SCB SHCSR 的 BusFault,此时写 SCB_NS 的 SHCSR.BUSFAULTENA 位无效。
% m% F, B. Q7 i
. K( i4 G  _! m4 O. h. @7 V) v" H3 S如果非安全侧应用使用这段代码使能 BusFault,那么前提是安全侧已经设置了AIRCR.BFHFNMINS=1。. S  {9 O. {. ~7 r% `8 w
$ o/ y$ v8 V* Q  s( I9 ?
1.1.3. Usage Fault
. \* i" r# U" K- [; l' k9 GUsageFault 与指令执行时候的错误有关,包括未定义的指令、非对齐访问、执行指令时的无效状态、中断返回时的错误、除 0 等。5 D! C( U9 M3 M" |& C

& p! ]" o% h  d( t在 TrustZone 环境中,UsageFault 是 Bank 的,因此在 S 和 NS 状态可能产生各自的UsageFault,并且可能触发各自的 S UsageFault Handler 和 NS UsageFault Handler。UsageFault 默认不使能,因而缺省会上升到 HardFault,是否触发 S 还是 NS 的 HardFault Handler 还要取决于 AIRCR.BFHFNMINS 的值是 0 还是 1。
; \% X2 f3 {" X' w0 P

3 E1 A& U% K# ^4 ^( e使能UsageFault 需要分别设置 SCB_S 和 SCB_NS 的 SHCSR.USGFAULTENA。SCB_S的 SHCSR.USGFAULTENA=1 用于使能 S 安全侧的 Usage Fault;SCB_NS 的SHCSR.USGFAULTENA=1 用于使能 NS 非安全侧的 Usage Fault。. S- G, B9 w# U$ n, e

- H2 k4 V& a7 x  k( Y$ k另外,通常除 0 操作不会触发 UsageFault,如果希望除 0 操作触发 UsageFault,需要将SCB_S/NS 对应的 CCR.DIV_0_TRP 比特置 1。0 T: B/ s8 P4 w' \

- A- M6 y5 `8 f) O# m6 i图 3 总结了 Usage 错误触发 Fault Handler 的一般情况。8 ?2 {/ A, ^+ a* J9 I3 S* r

/ m4 a2 u- v. T6 _
微信图片_20231130170520.png
- A- T7 L/ a! `; d4 Y) v8 ~$ P5 C$ j

3 X/ _! ^) l0 X% S0 J1 l# Q/ k只要 SHCSR.USGFAULTENA=1,UsageFault 总是触发软件对应安全状态的 UsageFault Handler,否则上升到 HardFault,安全侧的 UsageFault 总是上升到 Secure HardFault。对于非安全侧的 UsageFault,如果 AIRCR.BFHFNMINS=0,则上升到 Secure HardFault,否则上升到 Non-Secure HardFault。
' @9 b9 D/ t+ E! m3 e$ p6 |8 V/ w% p" b% t' t; Q
使能或禁止 UsageFault 的示例代码如下:
; I6 V6 ^, S# h  s5 b
  1. void EnableUsageFault(int enable)
    $ M, N  ]! W' E2 o, N* C
  2. {  ^. G% b1 |# s$ I. i' y# k
  3. if( enable == 1)
    " k9 e9 G4 `2 ^" w, q& N
  4. {5 v9 m7 u8 R" e9 \- K6 R
  5. SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
    $ r3 z9 F* C$ }( r$ l, h) m9 g6 f; q3 G
  6. /* Enable divide by 0 trap to trigger usage fault (if necessary) */# n9 E: x4 t1 Y
  7. SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;" l) a3 ?+ z( E3 L
  8. }) H5 r7 S+ k% A) q$ ?& T
  9. else
    - g1 a" O6 S, V6 U
  10. SCB->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    & d3 I- Q% t" A5 p8 {
  11. }
复制代码
9 V+ T$ {. ^: e+ s  E: A5 p
如果安全和非安全侧都需要使能 UsageFault,则 S、NS 代码可以分别调用这段代码使能各自的 UsageFault,或者 S 安全侧代码也可以直接控制 NS 非安全侧 UsageFault 的使能,例如可以在 S 安全侧增加下面这段代码来决定 NS 侧的 UsageFault 是否使能。9 c+ Y$ `$ @6 _, w3 R/ u$ e
  1. void EnableNSUsageFault(int enable)
    3 d' h/ z9 ~, z
  2. {
    " n1 a4 k  O6 l4 I
  3. if( enable == 1)8 U3 H! [# }) |4 l1 a
  4. SCB_NS->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
    - n+ v+ P5 M; o. ~# ?$ U& w; A+ _
  5. else
    5 k7 }3 H  A# j, M) d8 j
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);( G* r+ {$ G* d% T6 }$ `) p
  7. }
复制代码

9 V3 F% _. O# `/ d) w' v, \1.1.4. MemManage Fault
' L5 |; e# B$ `0 hMemManage Fault 是由于 Memory 保护产生的故障异常,例如在取指令或进行数据访问时违反了 MPU region 定义的访问规则,或者违反了默认地址保护规则。
8 e6 N$ B' B' v% Q9 e
& q0 G, u/ `& [  ^: ]4 ~MemManageFault 与 UsageFault 类似,也是默认不使能,如果希望使能 S 或者 NS 侧的MemManageFault,需要相应将 SCB_S 或者 SCB_NS 的 SHCSR.MEMFAULTENA 比特置位。
% y" A% v4 a+ ~* P

8 t  s9 |3 H3 I% @( K另外也与 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 处于非安全状态时候的访问,二者互不影响。
4 k; ?+ p) d* e7 u. W4 p0 w! M- [! s7 G& D
图 4 给出了 MemManage 故障触发 Fault Handler 的一般情况。如果 S 安全代码违反memory 访问规则,可能会触发安全侧的 MemManageFault,或者 Secure HardFault。非安全代码违反 memory 访问规则,可能会触发非安全侧的 MemManageFault,或者上升到HardFault,如果 AIRCR.BFHFNMINS=0 上升到 Secure HardFault,否则上升到 Non-Secure HardFault。
( t- K* I3 m/ O4 {1 U! g1 @
微信图片_20231130170516.png
. f, |1 W2 ?$ {
微信图片_20231130170512.png

8 |$ I& o3 l; L0 o. G0 R  A% Z  p% a' v/ c* y* h4 P
使能或禁止 MemManage Fault 的示例代码如下:
9 v5 b) ~! A& |
  1. void EnableMemoryFault(int enable)7 H9 P) V0 T$ F7 m/ e7 L5 }- Y0 u
  2. {2 V/ t: [) f5 ~  i
  3. if( enable == 1)
    - j8 X# j9 d/ }% `6 v
  4. SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
    , y. j) f0 _. l0 T3 l' t
  5. else
    & p. C5 a( {5 J2 M9 D
  6. SCB->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);6 b! K4 N1 W- x" B
  7. }
复制代码
& S* x+ R9 Z1 d4 v
如果安全和非安全侧都需要使能 MemManage Fault,则 S、NS 应用可以分别调用这段代码使能各自的 MemManage Fault,或者 S 安全侧代码也可以直接使能 NS 非安全侧的MemManage Fault,例如可以在 S 安全侧增加下面这段代码来控制 NS 侧的 MemManageFault 使能。
& [! |& r9 y% X/ {) Q% |
  1. void EnableNSMemoryFault (int enable)
    0 o6 V: B# c6 k; V& S8 m% {8 e
  2. {! |7 l8 p9 S! h& \3 u6 U
  3. if( enable == 1)
    - |; |* Y; M+ j( L" R& R$ r
  4. SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
    7 G, T5 D5 U, U: a2 g% b$ B1 q
  5. else
    0 `0 D" R9 g3 [
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);; [) ?  _% R5 k
  7. }
复制代码

* Z, V! y' }3 j2 H% Z; n; ?5 |另外,如果代码使用 HAL API 使能 MPU,即调用 HAL_MPU_Enable(),那么MemManage Fault 在 MPU 使能的函数中会自动被使能,这时候无需额外调用前面提到的代码去单独使能 MemManage Fault。/ p9 k  V( I3 Q) H
' |; c- N9 n6 w+ t
1.1.5. Secure Fault
* p& y& f; Y6 Y" n$ y5 X" nSecure Fault 只有在 TrustZone 使能的环境下才存在。SecureFault 可能由于内核中各种各样的安全检查而触发,例如从 NS 跳转至 S 代码时没有从 SG 入口指令进入,或者非安全代码试图访问 SAU/IDAU 规定的安全地址范围等。通常当出现 SecureFault 时,软件的处理可以是直接停止或者复位系统,这样做可以尽可能地避免引入安全漏洞。
( R: ~# I; p# X& D4 i$ N5 d0 l% Z
9 T$ y( \& F3 dSecureFault 不是 Bank 的,总是 target 到 S 侧,因此只有安全代码能够处理SecureFault。SecureFault 缺省也没有使能,出现 Secure 错误时,默认触发 SecureHardFault。软件可以通过置位 SHCSR.SECUREFAULTENA 来单独使能 SecureFault,使能后Secure 错误将触发 SecureFault Handler。图 5 给出了 Secure 错误触发 Fault Handler 的一般情况。* [# ^  h) M& N: Z9 w+ g0 @1 {" s
0 C# ]7 f/ }* U( T3 W
微信图片_20231130170508.png

1 m+ w- ?- _2 T% W2 v
微信图片_20231130170459.png
- |0 P/ Y0 n( v. w

9 L$ u$ G. c! b  L+ s6 h4 c0 w使能或禁止 SecureFault 的示例代码如下:" j2 g7 C, v* a( {* A( k
  1. void EnableSecureFault(int enable)
    3 Z% ^6 z! d$ S7 T8 p8 T
  2. {' y7 Q$ V; w& [" O4 g, b8 S5 `
  3. if( enable == 1)
    9 L, s. ^/ j. b/ S. G" S
  4. SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk;
    ; d. m7 C. S' v* |
  5. else/ i/ B: w% A. }7 Z" U- t9 {, ?
  6. SCB->SHCSR &= (~SCB_SHCSR_SECUREFAULTENA_Msk);
    " w: W) a) ?/ Y" p7 A& }/ w
  7. }
复制代码

4 Q$ C8 {8 J. T: F- S1.2. 故障升级与 HardFault/ W; M0 u) s$ @
除了 HardFault 以外,其他故障类型都具有可配置的优先级。软件可以禁止某个可配优先级的故障异常,但是不能禁止 HardFault。故障异常的优先级和对应的 mask bit 决定了内核是否会进入某个故障的处理程序,以及某个故障是否可以抢占另一个故障。8 a3 r- t! y. l- f% A" h$ I
. V0 m# i- G8 f  B3 P
某些情况下,可配置优先级的故障可能会被当成 HardFault 处理,也就是故障升级或称中断上访,此时,这个具体的 Fault 会升级为 HardFault 故障。& U8 z% |! |' b  Q- P) e
某个 Fault 升级成 HardFault 可能有多种原因,例如:& t. Q* k; V7 m3 ~2 y8 j( b! j
该故障 Fault 没有使能;5 d' B( F$ Q7 d( I1 s( ], Q

4 C0 f! F7 O9 _+ ]0 F% P& f, |例如,代码由于执行未定义的指令产生了 UsageFault,但是 UsageFault 没有被使能.
+ ]( C3 W+ E7 q; H& u7 m8 ]/ ?5 R3 h该故障的 FaultHandler 优先级不够高无法运行;
; F, Z( |( Z& _* l% {

2 {" V1 I! x. d4 Y: f6 _9 C5 P例如,系统配置并使能了 MPU,CPU 正在执行某个中断操作,该操作试图进行地址访问时违反了 MPU 定义的访问规则,进而触发了故障,但是当前执行的中断的优先级高于 MemManage 故障的优先级。5 K6 f7 p) L2 u
在故障的 FaultHandler 中产生了同样的故障;
1 @( t* [" g; w9 V/ g; ^
9 u" g5 G) {- Y5 i例如,在处理 UsageFault 的 handler 中又发生了未定义指令的情况。
' b+ _# B  Q6 u* P/ ^; Z如果在进入 BusFault Handler 的时候,压栈操作又导致了 BusFault,这种情况下 BusFault 不会升级到 HardFault。这意味着,如果损坏的堆栈导致故障,即使 Fault Handler 压栈失败,故障处理程序还是会执行,但堆栈内容已损坏。
7 v7 @6 \+ ^3 {+ |+ F只有 NMI 可以抢占 HardFault,HardFault 可以抢占任何除 Reset、NMI 或者另一个HardFault 以外的异常。当 BFHFNMINS=1 时,如果 NS 侧的 NMI Handler 产生了安全违规错误,那么它将触发 Secure HardFault,并被其抢占。+ O) p& E4 r( a! L0 c
在获取异常向量的时候发生的 Bus 错误,总是升级到 HardFault,由 HardFault 处理,而非 BusFault。
" l- O2 [" T  i$ w4 k- j) K: m9 v8 ~+ f- W" @* ?1 D
1.3. Fault 异常的安全状态
; i6 _1 C) e  ?7 @, r5 X0 P; i在 TrustZone 使能的环境中,故障异常可能 target 到 S 安全状态或 NS 非安全状态,这会导致 ARMv8-M 内核的行为与以往 ARMv6-M 及 ARMv7-M 内核有很大不同,TrustZone 环境软件开发中对 Fault 的处理要特别注意到这一点。
/ A6 `# R* ?2 d+ {5 W关于 Fault 异常 target 到 S、NS 的情况在前文中介绍几个 Fault 类型的时候已经有提到,这里在表 2 中再稍加总结。
+ b5 \% M; h/ C" U) l# k/ \: V# Z' Z6 q; N
微信图片_20231130170455.png

" M7 n' P3 ^! l
/ b* U, e0 R; X( I" h1.4. 异常的进入与返回' V0 o/ b+ S1 \1 b0 S- q: _
1.4.1. 异常的进入与 stack frame+ L  g' S/ [" Y7 N' H, z7 g
当处理器处于线程模式且系统存在具有足够优先级的 pending 异常时则会进入异常,或者新异常的优先级高于正在处理的异常,这时候新异常将抢占原始异常,即出现异常嵌套。
6 S* J9 {- b7 X' n+ q6 E4 q当处理器发生异常时,除非该异常是尾链异常或延迟到达的异常,否则处理器会将上下文信息压入堆栈,压栈的数据结构即 stack frame。
) Q, O3 \5 W9 M9 u3 ~3 y8 d通常 stack frame 的内容如图 6 (a) 所示,包含了 R0 到 R3、R12、LR、PC 和 xPSR 的内容。在 TrustZone 使能的环境中,如果 S 安全代码执行被 NS 非安全异常抢占,那么进入非安全异常前会有更多的信息压栈,如图 6 (b)所示,并且硬件会自动将压栈的寄存器清零,防止任何安全状态下的数据暴露给非安全代码。
! C, ?' G5 D$ t* s' j4 x如果使用了浮点功能,存在浮点上下文,那么内核也会自动将浮点相关的上下文内容压栈。由于浮点部分数据内容对我们通常的 Fault 调试没有太多帮助,这里不做赘述。
& O+ D9 ^/ e& j+ z进入异常前的 stack frame 压栈操作使用 MSP 还是 PSP,取决于当时内核的运行状态及其使用的堆栈。如果当时 CPU 运行于 Handler 模式,则使用 MSP 压栈 stack frame;如果 CPU运行于 Thread 模式,由当时的 CPU CONTROL.SPSEL 位来标记使用的堆栈。, J# r$ @+ f$ q, j7 p* J
" |; R- K, F# `& q( Z

8 x' j, i9 K) @+ y6 A转载自: STM320 y8 o# S/ u6 @( E1 w
如有侵权请联系删除1 {/ ]* t% h0 G$ D# |) T: a
3 N& z& J) N5 I/ i# r

3 M8 {  n* e. w
. H$ o* {4 B) q0 w
收藏 评论0 发布时间:2023-11-30 17:05

举报

0个回答

所属标签

相似分享

官网相关资源

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