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

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

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

% ~6 o0 H* \4 T1 }" s一、CM33 TrustZone 架构下的异常模型
5 C+ s6 }/ m% _2 o) a) v: v+ N在 STM32 TrustZone 开发调试技巧的第二篇中我们介绍过 CM33 带安全扩展的 S 和 NS 侧的中断以及中断向量表,这里不再赘述。表 1 总结了其中的 Fault 异常。: K% g7 W( W0 h5 P( v& {6 o6 X

/ G4 v3 ~  V) P9 B7 l0 s) Z
微信图片_20231130170530.png
- Z% t# |8 r6 A  F- v
# l4 Q5 E9 E3 ?) b. G! x0 ^' i
1.1. Fault 异常类型(带安全扩展)
0 ]$ K! F/ g0 f7 L! Y  I1.1.1. Hard Fault
) z6 j/ |$ H* nHardFault 是默认的 Fault 异常,总是使能。触发的原因可能是由于异常处理本身触发了错误,或者某个异常无法被其他机制处理而上升到 HardFault。它的优先级高于所有其他可配置优先级的异常。
2 n! A1 c' w3 P* ?* |+ s" ]/ w) W" r: M8 g+ W  ^, _
在 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 触发一般情形。
) e( m4 M# K- `, G& _. M  r
7 u( o+ L( y. z6 v, U+ w7 ~4 D( g1 d2 e& |+ U+ T; P
微信图片_20231130170527.png
# k3 U$ [' }6 t3 W2 n: h

$ [: S' ^( a) h% T! n( G$ S需要注意的是,即使 AIRCR.BFHFNMINS=1,原本 target 到 S 侧并且上升为 HardFault 的异常,将依旧触发 S 侧的 HardFault,他们并不受到 AIRCR.BFHFNMINS 位的影响,例如当安全代码违反 MPU 保护规则,产生 MemManage 错误的时候,即使 AIRCR.BFHFNMINS=1,故障还是会进入 Secure HardFault Handler。而 NS 侧的 HardFault,只有当AIRCR.BFHFNMINS=1 时才有可能会被触发。
- W, \# [- G5 e- }9 @* j* e
* J; O% Z! B) N+ _, m/ D另外还要注意一点,AIRCR 寄存器不能直接修改,需要先写 Key 值才能更改寄存器内容。置位或清除 AIRCR.BFHFNMINS bit 的示例代码如下(只能在安全代码中使用):: y5 ]  X4 i! w+ y9 R9 V+ w* a4 Q
  1. void SECURE_SetNMIHFBFTarget(int NS)
    " U9 R# X( k8 ~
  2. {4 j" O3 L( h3 o; }
  3. uint32_t reg_value;
    - }8 r& i: e8 R$ G: P* l) }
  4. uint32_t target = (NS==1)?1:0;
    3 e/ A$ B( f! W( Z, ~/ [
  5. /* read old register configuration */
    , }% {7 H  R# g( v) A
  6. reg_value = SCB->AIRCR;
    & A4 X4 ^" H4 X4 A& ?: P
  7. /* clear bits to change */8 m- K4 v0 {7 _
  8. reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_BFHFNMINS_Msk));& \7 C5 L: L3 G, m' N5 Z
  9. /* insert write key and target bit */
    ; D5 D- p; J+ Q' e0 g9 T& j
  10. reg_value = (reg_value |
    + Q3 N: ?% K% |+ ?: E& |% C5 b2 b
  11. ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
    * D6 g( v6 {7 K3 ^
  12. (target << SCB_AIRCR_BFHFNMINS_Pos) );
    8 Q7 K! v# B- `9 B/ S4 |
  13. SCB->AIRCR = reg_value;
    4 Y6 c6 }# g5 t. ^6 @2 j' L( w
  14. }
复制代码
7 ^! O5 L6 J: v! d% j6 {
注意:有的时候,软件可能需要设置 AIRCR.PRIS 位,来整体降低 NS 中断的优先级(例如在 TF-M 的实现中就使用这个机制)。这时候,如果同时设置 AIRCR.PRIS=1,AIRCR.BFHFNMINS=1,内核的行为将不可预测。因此如果需要设置 AIRCR.PRIS=1,则建议保持 AIRCR.BFHFNMINS=0。
# _) J- B( l) y5 D5 a; U: _( m
0 `1 \% t- f7 i/ M1 Q' {: t4 D
2 u. I) }. |0 W
1.1.2. Bus Fault3 f$ V3 y0 I- i
Bus Fault 通常发生在指令或数据访问时候,可能由于检测到 memory 系统的总线错误而导致。Bus Fault 默认不使能,就是说总线故障默认将触发 HardFault Handler。如果需要单独使能 Bus Fault,可以将 SCB 的 SHCSR.BUSFAULTENA 位设 1。
: S4 X1 Y1 G9 K# \

6 E% [' Q1 l' ~" c9 e在 TrustZone 环境中,Bus Fault 也不是 Bank 的。触发 S 还是 NS 侧的 BusFault Handler与SCB 的AIRCR.BFHFNMINS 有关。如果 AIRCR.BFHFNMINS=0,BusFault 总是 target 到S 安全状态;反之如果 AIRCR.BFHFNMINS=1,则 target 到 NS 非安全状态。! Y0 Y9 b( f# }  q; T/ G  u: j
. B# |/ s2 _- F; Z) E
产生 Bus 错误时,实际会触发哪个 Fault Handler,将取决于 AIRCR.BFHFNMINS 和SCB_S/NS 的 SHCSR.BUSFAULTENA 的设置。图 2 给出了 Bus 错误触发 Fault Handler 的一般情况(例如这里不考虑安全侧 Vector 错误依旧上升到 Secure HardFault 的情况)。
/ ?) ]% y7 B0 l8 s, u$ L5 [9 w6 ]  [4 D
微信图片_20231130170523.png
& G; y4 [+ t% P, O
: N( x! W0 [/ Z2 H" O! `
通常情况下,SCB 的 CFSR/BFSR 和 BFAR 寄存器中会标记总线故障信息。在 TrustZone环境中,SCB 的某些寄存器以及寄存器的某些比特位是 Bank 的。从安全侧和非安全侧都能够看到各自的 SCB 寄存器,但是 CFSR 寄存器的 BFSR 域以及 BFAR 寄存器并不是 Bank 的。而 Bus 故障可能 target 到 S 安全侧也可能 target 到 NS 非安全侧,当发生总线错误的时候,如果分别从 SCB_S、SCB_NS 的相关寄存器中读取 Bus Fault 的信息,可以看到不同的结果。
1 j0 ~# y# V0 e9 g: c. Q: z) Y* y! D) @
如果 AIRCR.BFHFNMINS=0,只有安全侧可以看到 BFSR 和 BFAR 的真实数据,非安全侧读取 BFSR、BFAR,或者从安全侧读取 BFSR_NS,BFAR_NS 都只能读到全 0 的值。
" c! x! e$ t& g  H6 F
  A+ e) b) |  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 寄存器获取故障信息。6 z$ `; p+ x. {: j- f! S" _$ R

1 I$ w, J" `/ SBusFault 默认没有单独使能,如果需要使能 BusFault,可以将 SHCSR 寄存器的BUSFAULTENA 位置位。使能或禁止 BusFault 的示例代码如下:
6 _. e$ O  C( X2 d
  1. void EnableBusFault(int enable). ^% ^6 o4 d/ V! I
  2. {
    4 H# E$ L' h) h/ H- d
  3. if( enable == 1)
    - H0 r* t5 L9 x; F
  4. SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
    2 h! C% |% N, t9 F- ]
  5. else4 A& i0 T! W, Y; n: X
  6. SCB->SHCSR &= (~SCB_SHCSR_BUSFAULTENA_Msk);
    - t7 U* G" y( I2 _3 T; V; {
  7. }
复制代码
5 R- u, W! _  w- I: o' }: G) p# w
这段代码对安全和非安全侧都是一样的,但是要注意,由于 BusFault 不是 Bank 的,当AIRCR.BFHFNMINS=0 时,这段代码只能在安全侧使用,也就是修改的是 S 安全侧 SCB SHCSR 的 BusFault,此时写 SCB_NS 的 SHCSR.BUSFAULTENA 位无效。
! ?) |9 L/ q4 [3 {4 t
$ f5 K3 m/ H/ B$ I# M0 @9 j5 ?如果非安全侧应用使用这段代码使能 BusFault,那么前提是安全侧已经设置了AIRCR.BFHFNMINS=1。* ^9 e! Z& h! ]* y; Z/ S0 V# N+ T( W

# i( [" w5 U( j& b! n1.1.3. Usage Fault
) B7 s5 J4 @, G5 |* y: l/ A3 y* Z3 eUsageFault 与指令执行时候的错误有关,包括未定义的指令、非对齐访问、执行指令时的无效状态、中断返回时的错误、除 0 等。1 f- k* b$ ^6 Z- a) E5 K! ^
6 q9 i, J" P# H) ?3 k- v0 X6 ^
在 TrustZone 环境中,UsageFault 是 Bank 的,因此在 S 和 NS 状态可能产生各自的UsageFault,并且可能触发各自的 S UsageFault Handler 和 NS UsageFault Handler。UsageFault 默认不使能,因而缺省会上升到 HardFault,是否触发 S 还是 NS 的 HardFault Handler 还要取决于 AIRCR.BFHFNMINS 的值是 0 还是 1。1 b2 }& K7 D  ]3 ?" L

' O( j- g: t3 H; W* ~+ @使能UsageFault 需要分别设置 SCB_S 和 SCB_NS 的 SHCSR.USGFAULTENA。SCB_S的 SHCSR.USGFAULTENA=1 用于使能 S 安全侧的 Usage Fault;SCB_NS 的SHCSR.USGFAULTENA=1 用于使能 NS 非安全侧的 Usage Fault。: s7 N1 z/ P3 N
( d' A7 ~: o9 b/ G+ w
另外,通常除 0 操作不会触发 UsageFault,如果希望除 0 操作触发 UsageFault,需要将SCB_S/NS 对应的 CCR.DIV_0_TRP 比特置 1。
) V9 M& ~/ \/ t$ w. {
8 A# j( c1 L, X5 {. ^1 _图 3 总结了 Usage 错误触发 Fault Handler 的一般情况。5 X( X$ k$ F+ A- o6 ~
7 p+ ~+ R( }5 a4 A$ j! R$ t
微信图片_20231130170520.png
# G7 ]' X! f* C

% s4 U8 R4 d6 h; P# g% S. c只要 SHCSR.USGFAULTENA=1,UsageFault 总是触发软件对应安全状态的 UsageFault Handler,否则上升到 HardFault,安全侧的 UsageFault 总是上升到 Secure HardFault。对于非安全侧的 UsageFault,如果 AIRCR.BFHFNMINS=0,则上升到 Secure HardFault,否则上升到 Non-Secure HardFault。7 Y' V- K, ~4 P3 e; f+ a  Z

9 p# J0 V# D8 V3 I- N" Y( y: r使能或禁止 UsageFault 的示例代码如下:' I7 i+ T! Z2 |  `1 A1 D
  1. void EnableUsageFault(int enable)
    ) N8 H0 p$ n9 l/ p" n0 |7 g. f
  2. {
      C7 d; u+ p! ?' }- {& I5 @
  3. if( enable == 1)1 I4 \$ t/ ^( {( P
  4. {- }' l1 ~8 B; ^- N; R
  5. SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
    1 y" b+ ^' o. M" S$ n: u; [
  6. /* Enable divide by 0 trap to trigger usage fault (if necessary) */
    / a9 e  f5 `3 G! I5 s: k
  7. SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
    3 i2 N, R" U5 R) f$ U/ k
  8. }: T1 ]2 q4 }& \$ R+ q! [9 J
  9. else
    " R1 T! T% h- ?+ x
  10. SCB->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    4 ~+ R) j* X  T3 e) p8 T$ V
  11. }
复制代码
& e$ r5 Y. Y; B$ B
如果安全和非安全侧都需要使能 UsageFault,则 S、NS 代码可以分别调用这段代码使能各自的 UsageFault,或者 S 安全侧代码也可以直接控制 NS 非安全侧 UsageFault 的使能,例如可以在 S 安全侧增加下面这段代码来决定 NS 侧的 UsageFault 是否使能。
/ Z& z: s8 J, y( }" L, V
  1. void EnableNSUsageFault(int enable)* Z3 G. B2 o! j) p9 `! I2 R
  2. {
    , v% Y! r5 S0 p& s- s8 D6 w5 p4 A
  3. if( enable == 1)
    ! p/ D! k9 R+ T- r1 b
  4. SCB_NS->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
    7 h+ `" l; h2 O: W! P
  5. else
    ! n! n$ I7 B9 `; n& N
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    3 H6 l+ t, F7 k" `
  7. }
复制代码
5 H% V% ]* I8 ]5 N  P
1.1.4. MemManage Fault
, J9 ]6 o0 J1 }) [9 t; G; V9 w. DMemManage Fault 是由于 Memory 保护产生的故障异常,例如在取指令或进行数据访问时违反了 MPU region 定义的访问规则,或者违反了默认地址保护规则。( R# i8 W0 F7 t/ b) \9 }

6 y& o* d" v3 F( e- jMemManageFault 与 UsageFault 类似,也是默认不使能,如果希望使能 S 或者 NS 侧的MemManageFault,需要相应将 SCB_S 或者 SCB_NS 的 SHCSR.MEMFAULTENA 比特置位。7 h9 @2 B. c" c2 |. g, ]# f( [
5 k% k! m8 A, P
另外也与 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 c0 ]1 \2 t, b* u/ y2 `
* k0 W! N. u) w
图 4 给出了 MemManage 故障触发 Fault Handler 的一般情况。如果 S 安全代码违反memory 访问规则,可能会触发安全侧的 MemManageFault,或者 Secure HardFault。非安全代码违反 memory 访问规则,可能会触发非安全侧的 MemManageFault,或者上升到HardFault,如果 AIRCR.BFHFNMINS=0 上升到 Secure HardFault,否则上升到 Non-Secure HardFault。
8 Y% o: }; U, _$ {( \% g! X5 _
微信图片_20231130170516.png

% Q& G, z# X) }9 ?
微信图片_20231130170512.png
  @) f- w, J' H3 `* T/ S- D6 ~

; c, {, `8 J2 _$ }( G# |使能或禁止 MemManage Fault 的示例代码如下:9 Q, a" k; ]3 e$ p2 T
  1. void EnableMemoryFault(int enable)
    $ j" M) @; v/ B! _
  2. {+ H/ L0 t. \+ X- g
  3. if( enable == 1)/ t" L) C2 v& q7 H
  4. SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
    ( H8 c: M! a* K- i. y
  5. else
    ) }4 {5 z/ y1 a- s2 H) v
  6. SCB->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);, d8 S) B/ `+ e9 n# ]
  7. }
复制代码
" N8 a# H, T! u8 n( x0 }
如果安全和非安全侧都需要使能 MemManage Fault,则 S、NS 应用可以分别调用这段代码使能各自的 MemManage Fault,或者 S 安全侧代码也可以直接使能 NS 非安全侧的MemManage Fault,例如可以在 S 安全侧增加下面这段代码来控制 NS 侧的 MemManageFault 使能。
3 R  z* C6 Z4 a' i8 }
  1. void EnableNSMemoryFault (int enable)) K% E# D7 }; U* l( \( m
  2. {* R. C# D% q5 \5 A
  3. if( enable == 1)
    % W7 _8 [2 D+ b% j
  4. SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
    ) Y  L9 k( k; K" A) r2 L: d
  5. else
    6 U  H( ~  c4 H; o
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);/ m9 n2 N' a) P9 A! X, t
  7. }
复制代码

( \( D4 O4 I3 Y1 s9 q另外,如果代码使用 HAL API 使能 MPU,即调用 HAL_MPU_Enable(),那么MemManage Fault 在 MPU 使能的函数中会自动被使能,这时候无需额外调用前面提到的代码去单独使能 MemManage Fault。7 t7 u3 K/ h2 d5 u
1 I4 w/ a4 q& I& \8 x5 R
1.1.5. Secure Fault6 H7 a+ C* p: o6 X/ a" I
Secure Fault 只有在 TrustZone 使能的环境下才存在。SecureFault 可能由于内核中各种各样的安全检查而触发,例如从 NS 跳转至 S 代码时没有从 SG 入口指令进入,或者非安全代码试图访问 SAU/IDAU 规定的安全地址范围等。通常当出现 SecureFault 时,软件的处理可以是直接停止或者复位系统,这样做可以尽可能地避免引入安全漏洞。
" G+ ?& }9 E1 a: o
8 r1 k6 K- p5 e; XSecureFault 不是 Bank 的,总是 target 到 S 侧,因此只有安全代码能够处理SecureFault。SecureFault 缺省也没有使能,出现 Secure 错误时,默认触发 SecureHardFault。软件可以通过置位 SHCSR.SECUREFAULTENA 来单独使能 SecureFault,使能后Secure 错误将触发 SecureFault Handler。图 5 给出了 Secure 错误触发 Fault Handler 的一般情况。
4 f, `0 G' A% r5 E3 T
- ]- K! z7 \* i6 I: r7 _# T
微信图片_20231130170508.png
( m5 j. _+ u+ {; w* d9 z9 t
微信图片_20231130170459.png
( b. `" F9 U9 P: m) V' Z  p' [/ [

* R; Y, f' a$ h使能或禁止 SecureFault 的示例代码如下:
/ J* J" ~5 |9 B) z3 [
  1. void EnableSecureFault(int enable)
    5 _' y% L0 q7 j" e
  2. {; d( ^1 F$ w: P$ X2 P- v
  3. if( enable == 1)
    / U# |4 c' I" S9 S; L
  4. SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk;
    % g8 A* k) B+ Y6 n( ^9 r
  5. else
    : Y, |9 n2 h* t
  6. SCB->SHCSR &= (~SCB_SHCSR_SECUREFAULTENA_Msk);3 U/ I8 Z5 C3 }7 z; x0 j6 A, z, \
  7. }
复制代码
0 n6 M4 e- o+ b3 O- r
1.2. 故障升级与 HardFault, W/ r; w0 ~+ T) \5 y7 U
除了 HardFault 以外,其他故障类型都具有可配置的优先级。软件可以禁止某个可配优先级的故障异常,但是不能禁止 HardFault。故障异常的优先级和对应的 mask bit 决定了内核是否会进入某个故障的处理程序,以及某个故障是否可以抢占另一个故障。
/ z( C2 Z: ~4 f! s# o. j

, I) G6 b* p2 F2 Y某些情况下,可配置优先级的故障可能会被当成 HardFault 处理,也就是故障升级或称中断上访,此时,这个具体的 Fault 会升级为 HardFault 故障。+ W$ V/ Y& k1 R( p' |. S: \
某个 Fault 升级成 HardFault 可能有多种原因,例如:
9 {8 ^7 C. `' K1 y该故障 Fault 没有使能;2 `& r& b0 k: V2 ?9 f' ~, R
. S+ [3 r3 c* i9 e4 g! b
例如,代码由于执行未定义的指令产生了 UsageFault,但是 UsageFault 没有被使能.2 F; Y, E" _3 A! I$ h4 k
该故障的 FaultHandler 优先级不够高无法运行;  @! i5 P; E9 X+ z& v8 ~% c

9 L& D" V) Z4 b) b1 W* }例如,系统配置并使能了 MPU,CPU 正在执行某个中断操作,该操作试图进行地址访问时违反了 MPU 定义的访问规则,进而触发了故障,但是当前执行的中断的优先级高于 MemManage 故障的优先级。
4 |8 M* d$ E( |/ a在故障的 FaultHandler 中产生了同样的故障;1 u- h2 D+ O. `* ~8 z' p

4 {" E6 H5 [" V) q例如,在处理 UsageFault 的 handler 中又发生了未定义指令的情况。0 s' H5 Q6 W4 D2 T  x# V
如果在进入 BusFault Handler 的时候,压栈操作又导致了 BusFault,这种情况下 BusFault 不会升级到 HardFault。这意味着,如果损坏的堆栈导致故障,即使 Fault Handler 压栈失败,故障处理程序还是会执行,但堆栈内容已损坏。3 F+ v6 a+ _: X+ d
只有 NMI 可以抢占 HardFault,HardFault 可以抢占任何除 Reset、NMI 或者另一个HardFault 以外的异常。当 BFHFNMINS=1 时,如果 NS 侧的 NMI Handler 产生了安全违规错误,那么它将触发 Secure HardFault,并被其抢占。. A/ B$ V5 X' P+ r7 i8 _$ [- a
在获取异常向量的时候发生的 Bus 错误,总是升级到 HardFault,由 HardFault 处理,而非 BusFault。: H8 @5 A2 w$ P* t- k
4 k. |8 @, @0 ?# e1 a2 q
1.3. Fault 异常的安全状态
. p( b8 R! P& a在 TrustZone 使能的环境中,故障异常可能 target 到 S 安全状态或 NS 非安全状态,这会导致 ARMv8-M 内核的行为与以往 ARMv6-M 及 ARMv7-M 内核有很大不同,TrustZone 环境软件开发中对 Fault 的处理要特别注意到这一点。
" X" l# ]" _, b1 n0 z$ _关于 Fault 异常 target 到 S、NS 的情况在前文中介绍几个 Fault 类型的时候已经有提到,这里在表 2 中再稍加总结。  K2 d( y" H( t
$ g8 N6 i4 O& T) L) \+ O
微信图片_20231130170455.png
' \4 K) v1 Q" v$ v0 r
6 @4 y1 U+ C  g. X
1.4. 异常的进入与返回; T3 U- q5 a4 k) |
1.4.1. 异常的进入与 stack frame, {* c$ E* Z. J" n) y' F
当处理器处于线程模式且系统存在具有足够优先级的 pending 异常时则会进入异常,或者新异常的优先级高于正在处理的异常,这时候新异常将抢占原始异常,即出现异常嵌套。% A' X) ^* ?- x7 K7 D& [
当处理器发生异常时,除非该异常是尾链异常或延迟到达的异常,否则处理器会将上下文信息压入堆栈,压栈的数据结构即 stack frame。
2 T* F& }5 P/ S0 \通常 stack frame 的内容如图 6 (a) 所示,包含了 R0 到 R3、R12、LR、PC 和 xPSR 的内容。在 TrustZone 使能的环境中,如果 S 安全代码执行被 NS 非安全异常抢占,那么进入非安全异常前会有更多的信息压栈,如图 6 (b)所示,并且硬件会自动将压栈的寄存器清零,防止任何安全状态下的数据暴露给非安全代码。. {" j3 ^/ {% b- |' ~
如果使用了浮点功能,存在浮点上下文,那么内核也会自动将浮点相关的上下文内容压栈。由于浮点部分数据内容对我们通常的 Fault 调试没有太多帮助,这里不做赘述。
: n- k; e0 |' b+ K/ L+ X进入异常前的 stack frame 压栈操作使用 MSP 还是 PSP,取决于当时内核的运行状态及其使用的堆栈。如果当时 CPU 运行于 Handler 模式,则使用 MSP 压栈 stack frame;如果 CPU运行于 Thread 模式,由当时的 CPU CONTROL.SPSEL 位来标记使用的堆栈。) J% l' P# M: b) H% O

2 P5 c) ^& e( w
5 }9 P5 o+ \. }9 p
转载自: STM32
$ U6 w9 o* T8 p/ [5 z& i4 y/ g: ^如有侵权请联系删除
$ w7 ~4 E9 g1 m5 c  I) x
! x$ N1 G( E4 t, g. J) i0 M

$ r. t4 G1 W& Q5 ?4 m! Y) w5 M7 m4 \0 ^5 p5 w
收藏 评论0 发布时间:2023-11-30 17:05

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版