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

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

[复制链接]
STMCU小助手 发布时间:2023-11-30 17:05
引  言! J5 m. f$ }$ d; g# K, |
在 STM32 TrustZone 开发调试技巧的前两篇中,我们介绍了内核的 SAU/IDAU,地址的安全属性配置,资源的安全属性配置,内核访问资源的安全规则,以及 TrustZone 环境下外设使用的常见问题等内容。TrustZone 环境开发中还可能经常遇到的一个问题就是软件触发的故障错误。ARM CM33内核 TrustZone 环境下的异常模型以及 Fault 的处理与不带安全扩展的情况有着很多变化,一旦出现 HardFault,经验不足的开发者可能往会找不到头绪,不知道从哪里着手寻找问题所在。因此,在这一篇的重点将围绕 CM33 TrustZone 环境下的异常模型以及 HardFault 的调试与处理展开,供开发者参考。  Y8 {. e9 n5 f! {
6 |5 e  O) ^' I* u2 E% v
一、CM33 TrustZone 架构下的异常模型/ n1 N8 ]5 ?- E1 r/ o* C8 Q0 |  ]
在 STM32 TrustZone 开发调试技巧的第二篇中我们介绍过 CM33 带安全扩展的 S 和 NS 侧的中断以及中断向量表,这里不再赘述。表 1 总结了其中的 Fault 异常。
. H2 P& k+ g! H- _/ ^+ Z$ ?, \
! O4 s4 z# H. x; T% n: n; I
微信图片_20231130170530.png

/ B+ K: U2 z" z9 i8 ]/ ?* H( u1 F& J
1.1. Fault 异常类型(带安全扩展)
# y( p$ u) E2 Y; p+ v) H1.1.1. Hard Fault
8 d/ V/ R+ [+ O3 u5 |HardFault 是默认的 Fault 异常,总是使能。触发的原因可能是由于异常处理本身触发了错误,或者某个异常无法被其他机制处理而上升到 HardFault。它的优先级高于所有其他可配置优先级的异常。
, a% g, b$ _* o5 k0 u0 J1 l3 C3 T! Y" l
- ?; p4 u7 G0 b+ I  P4 `1 l' f在 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 触发一般情形。6 g) z$ V% I4 @$ f2 f1 t
/ F* V9 _( J) m4 V5 X
" y' g; m) a# x5 i+ Z
微信图片_20231130170527.png
2 r( w3 s8 K+ O1 l
4 r) d+ ~6 \- u; @* f
需要注意的是,即使 AIRCR.BFHFNMINS=1,原本 target 到 S 侧并且上升为 HardFault 的异常,将依旧触发 S 侧的 HardFault,他们并不受到 AIRCR.BFHFNMINS 位的影响,例如当安全代码违反 MPU 保护规则,产生 MemManage 错误的时候,即使 AIRCR.BFHFNMINS=1,故障还是会进入 Secure HardFault Handler。而 NS 侧的 HardFault,只有当AIRCR.BFHFNMINS=1 时才有可能会被触发。
$ w' T5 B( O- o) i; m2 k' f0 }9 h% @. I
另外还要注意一点,AIRCR 寄存器不能直接修改,需要先写 Key 值才能更改寄存器内容。置位或清除 AIRCR.BFHFNMINS bit 的示例代码如下(只能在安全代码中使用):
: B5 F& K: y" i" b4 p* }1 Q  R( @
  1. void SECURE_SetNMIHFBFTarget(int NS)
    ( G8 u$ i* P6 N6 ?- z
  2. {
    $ f0 s3 r( |0 ]* g
  3. uint32_t reg_value;
    0 n4 \% K' f5 s! ?) w
  4. uint32_t target = (NS==1)?1:0;
    % s: [6 a5 r  M) S
  5. /* read old register configuration */. X6 l- X) z9 q+ I/ m
  6. reg_value = SCB->AIRCR;' f" Y% |% [, }$ O* v6 I. W
  7. /* clear bits to change */! v' o: h& B1 G$ A: o% {
  8. reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_BFHFNMINS_Msk));
    4 @  ?5 C4 k1 @4 u. V) l% d, o+ w
  9. /* insert write key and target bit */( X1 q7 q3 I% x2 W
  10. reg_value = (reg_value |/ w0 w( y& o- ]( A
  11. ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
    3 ?( ^7 X, z+ H* L4 [: u
  12. (target << SCB_AIRCR_BFHFNMINS_Pos) );
    ) P; ~& `2 N, P0 y( l& G1 f
  13. SCB->AIRCR = reg_value;
    ' B* `. I. l7 v! R
  14. }
复制代码

; I& D  p8 n. Q2 d3 o. q+ J注意:有的时候,软件可能需要设置 AIRCR.PRIS 位,来整体降低 NS 中断的优先级(例如在 TF-M 的实现中就使用这个机制)。这时候,如果同时设置 AIRCR.PRIS=1,AIRCR.BFHFNMINS=1,内核的行为将不可预测。因此如果需要设置 AIRCR.PRIS=1,则建议保持 AIRCR.BFHFNMINS=0。, ^3 r' i* T/ \$ J2 I& ]9 R* T9 ^7 V

6 J" @) G% J* A, I) i
: C2 U2 ]2 Z' N- e2 |
1.1.2. Bus Fault8 y& U9 B$ j& t. d
Bus Fault 通常发生在指令或数据访问时候,可能由于检测到 memory 系统的总线错误而导致。Bus Fault 默认不使能,就是说总线故障默认将触发 HardFault Handler。如果需要单独使能 Bus Fault,可以将 SCB 的 SHCSR.BUSFAULTENA 位设 1。
' r- ?8 W8 w5 j) W7 w1 r
. {' |/ n  s8 ^
在 TrustZone 环境中,Bus Fault 也不是 Bank 的。触发 S 还是 NS 侧的 BusFault Handler与SCB 的AIRCR.BFHFNMINS 有关。如果 AIRCR.BFHFNMINS=0,BusFault 总是 target 到S 安全状态;反之如果 AIRCR.BFHFNMINS=1,则 target 到 NS 非安全状态。9 z% `; c; ^& |! p$ @9 D8 |
0 q" R/ l2 E3 L+ {5 D: B
产生 Bus 错误时,实际会触发哪个 Fault Handler,将取决于 AIRCR.BFHFNMINS 和SCB_S/NS 的 SHCSR.BUSFAULTENA 的设置。图 2 给出了 Bus 错误触发 Fault Handler 的一般情况(例如这里不考虑安全侧 Vector 错误依旧上升到 Secure HardFault 的情况)。- |5 H. x+ Q- N2 P( u$ y7 J
: l8 J! d7 d) {- w- c
微信图片_20231130170523.png

4 T) Z7 ~7 v1 S! c* o4 }1 Y! Q
# @; m! T+ [$ @8 K  I7 r0 ~通常情况下,SCB 的 CFSR/BFSR 和 BFAR 寄存器中会标记总线故障信息。在 TrustZone环境中,SCB 的某些寄存器以及寄存器的某些比特位是 Bank 的。从安全侧和非安全侧都能够看到各自的 SCB 寄存器,但是 CFSR 寄存器的 BFSR 域以及 BFAR 寄存器并不是 Bank 的。而 Bus 故障可能 target 到 S 安全侧也可能 target 到 NS 非安全侧,当发生总线错误的时候,如果分别从 SCB_S、SCB_NS 的相关寄存器中读取 Bus Fault 的信息,可以看到不同的结果。
+ v' _' C4 h; J
& ]) Q' y0 v" L; n! Z! G如果 AIRCR.BFHFNMINS=0,只有安全侧可以看到 BFSR 和 BFAR 的真实数据,非安全侧读取 BFSR、BFAR,或者从安全侧读取 BFSR_NS,BFAR_NS 都只能读到全 0 的值。3 `1 a) _0 t4 e) o& v

/ v% L& v1 M& N/ w6 A如果 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 寄存器获取故障信息。
0 c$ Y/ M7 N% t& j( Z0 _- E7 s1 @
& K- v) |8 h% G- H6 U' P# {
BusFault 默认没有单独使能,如果需要使能 BusFault,可以将 SHCSR 寄存器的BUSFAULTENA 位置位。使能或禁止 BusFault 的示例代码如下:& O7 ~7 T+ n/ n$ |
  1. void EnableBusFault(int enable)" c  z6 s5 L6 ^8 Z/ }
  2. {
    : g/ [9 C/ W6 \
  3. if( enable == 1)
    # L) @/ \3 _3 Z7 P+ n5 ^" x
  4. SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
    4 {* W+ q2 ]6 m' F# Q5 `
  5. else
    3 H" ]' c: s- j: P9 a5 D
  6. SCB->SHCSR &= (~SCB_SHCSR_BUSFAULTENA_Msk);9 _5 u# O$ V- ?  ?, p+ k
  7. }
复制代码

# }' h, o7 ~* ?/ _( R- t这段代码对安全和非安全侧都是一样的,但是要注意,由于 BusFault 不是 Bank 的,当AIRCR.BFHFNMINS=0 时,这段代码只能在安全侧使用,也就是修改的是 S 安全侧 SCB SHCSR 的 BusFault,此时写 SCB_NS 的 SHCSR.BUSFAULTENA 位无效。* o! Z1 D0 }, u1 r' b

' B& g0 t' s: w: R7 l  ^0 O& s如果非安全侧应用使用这段代码使能 BusFault,那么前提是安全侧已经设置了AIRCR.BFHFNMINS=1。
: v6 W% I$ D" V
9 l+ K* r6 S* V2 N1.1.3. Usage Fault1 d# a. G0 v7 l% j6 ~5 i
UsageFault 与指令执行时候的错误有关,包括未定义的指令、非对齐访问、执行指令时的无效状态、中断返回时的错误、除 0 等。2 f( h! g3 Y% F0 ^0 a

  M. F. Z- W, \; v; l在 TrustZone 环境中,UsageFault 是 Bank 的,因此在 S 和 NS 状态可能产生各自的UsageFault,并且可能触发各自的 S UsageFault Handler 和 NS UsageFault Handler。UsageFault 默认不使能,因而缺省会上升到 HardFault,是否触发 S 还是 NS 的 HardFault Handler 还要取决于 AIRCR.BFHFNMINS 的值是 0 还是 1。
: n/ ?3 h4 M$ k, E3 a& \2 C. O; r! V

  Z# a4 z1 ?8 `. q9 W使能UsageFault 需要分别设置 SCB_S 和 SCB_NS 的 SHCSR.USGFAULTENA。SCB_S的 SHCSR.USGFAULTENA=1 用于使能 S 安全侧的 Usage Fault;SCB_NS 的SHCSR.USGFAULTENA=1 用于使能 NS 非安全侧的 Usage Fault。# K" |- i' u9 G! K/ B
- [$ b5 Q7 ]: u8 W* z
另外,通常除 0 操作不会触发 UsageFault,如果希望除 0 操作触发 UsageFault,需要将SCB_S/NS 对应的 CCR.DIV_0_TRP 比特置 1。
! D& b$ J$ {/ l# V  J& C1 T
- z6 _2 h4 w1 d- W图 3 总结了 Usage 错误触发 Fault Handler 的一般情况。
  K9 q+ q% y, Y4 y3 s
8 ~7 p) I0 B; B. e; [
微信图片_20231130170520.png

; D8 W) I+ a2 Q! x- `1 e
! v1 w' c- ?8 ]+ u, P- q只要 SHCSR.USGFAULTENA=1,UsageFault 总是触发软件对应安全状态的 UsageFault Handler,否则上升到 HardFault,安全侧的 UsageFault 总是上升到 Secure HardFault。对于非安全侧的 UsageFault,如果 AIRCR.BFHFNMINS=0,则上升到 Secure HardFault,否则上升到 Non-Secure HardFault。
+ q$ ]0 a  O0 r
6 E" B4 H! L$ T7 l( f. \使能或禁止 UsageFault 的示例代码如下:
% S. q% C, `  Z: F6 c" U1 H
  1. void EnableUsageFault(int enable)
    ; _3 M" ]. O0 N+ U3 k
  2. {
    0 ?9 Q; Y$ u- y2 {
  3. if( enable == 1)
    ' m  [+ P. }, F) H, ]) I
  4. {
    3 R% l3 U  ^. B* I
  5. SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
    ' x3 q! p4 \+ d0 h: U" F
  6. /* Enable divide by 0 trap to trigger usage fault (if necessary) */* E1 i) T" _, G' z
  7. SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;1 j$ K; @' L0 m% i
  8. }" \" d7 T# J7 t5 x2 v. ]) j
  9. else
    : E% k% i( O- X) H& A6 q0 E$ D# E7 D
  10. SCB->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    7 b; ?# z/ U" u! o0 Q. r
  11. }
复制代码

; x" s3 Y( a+ f  A# f& v2 R+ L如果安全和非安全侧都需要使能 UsageFault,则 S、NS 代码可以分别调用这段代码使能各自的 UsageFault,或者 S 安全侧代码也可以直接控制 NS 非安全侧 UsageFault 的使能,例如可以在 S 安全侧增加下面这段代码来决定 NS 侧的 UsageFault 是否使能。* y% W, G# K6 A4 Y3 F2 u; T
  1. void EnableNSUsageFault(int enable)) b" K- p7 F9 R) i0 E' i
  2. {
    - ]' L- ?) P! J" b1 b( ^  O% F
  3. if( enable == 1)
    " L, @1 {2 i1 F7 G+ {4 B
  4. SCB_NS->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
    2 |' L% N3 j- d  l5 c
  5. else/ Z: N) @; r: M9 w) Q0 d5 j$ j3 l/ G
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_USGFAULTENA_Msk);
    & j$ \5 |( B( z" j
  7. }
复制代码

6 s7 f# ]1 O* F! `1.1.4. MemManage Fault
5 A& |4 a6 `% b0 A- mMemManage Fault 是由于 Memory 保护产生的故障异常,例如在取指令或进行数据访问时违反了 MPU region 定义的访问规则,或者违反了默认地址保护规则。% c, h9 \2 }# f9 E5 X; c( t/ N& e$ P, \
# E2 Q/ B  O# K* Y. m3 S/ `2 u' [: |
MemManageFault 与 UsageFault 类似,也是默认不使能,如果希望使能 S 或者 NS 侧的MemManageFault,需要相应将 SCB_S 或者 SCB_NS 的 SHCSR.MEMFAULTENA 比特置位。
" i. t" F6 O1 P# r

# c/ P" P9 N. g- a2 O0 Y1 |! 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 处于非安全状态时候的访问,二者互不影响。* V) z" _9 h( t- t* {# y8 N4 B6 n

/ a  ]( `* W- t图 4 给出了 MemManage 故障触发 Fault Handler 的一般情况。如果 S 安全代码违反memory 访问规则,可能会触发安全侧的 MemManageFault,或者 Secure HardFault。非安全代码违反 memory 访问规则,可能会触发非安全侧的 MemManageFault,或者上升到HardFault,如果 AIRCR.BFHFNMINS=0 上升到 Secure HardFault,否则上升到 Non-Secure HardFault。) {0 T! k! p! m# F3 x0 |
微信图片_20231130170516.png
# H3 H; H' P) h
微信图片_20231130170512.png
& y' S8 d: @0 ~$ x& H+ R$ p' k

; C  H: q7 w$ L) L4 {, \, _使能或禁止 MemManage Fault 的示例代码如下:: _+ a. [$ u! S# o9 j0 Y5 u+ ~
  1. void EnableMemoryFault(int enable). G5 w' h: J1 Y( ?+ C- R+ v. G
  2. {0 O3 x$ I9 J  O. y4 c/ i; ~
  3. if( enable == 1): Y& [4 T  U: R
  4. SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;: g2 a8 ?% ^* K
  5. else5 m& \; S1 Y( l0 E
  6. SCB->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);4 v+ @. P- ^, }/ q% R1 s# X4 U
  7. }
复制代码
7 ~) @7 y1 d+ f0 `$ Y( M1 |
如果安全和非安全侧都需要使能 MemManage Fault,则 S、NS 应用可以分别调用这段代码使能各自的 MemManage Fault,或者 S 安全侧代码也可以直接使能 NS 非安全侧的MemManage Fault,例如可以在 S 安全侧增加下面这段代码来控制 NS 侧的 MemManageFault 使能。+ {. ^9 U$ R7 a* K/ }
  1. void EnableNSMemoryFault (int enable)- w$ x# g$ o, p7 t
  2. {
    3 M% I0 s: F4 U8 C0 J# A
  3. if( enable == 1)$ j/ S1 I- t. p5 D8 Q( L
  4. SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;: g) H$ p9 O) T2 O( F7 ~8 Y
  5. else/ E+ {1 G4 X0 i6 q# J
  6. SCB_NS->SHCSR &= (~SCB_SHCSR_MEMFAULTENA_Msk);
    8 a8 I. c; W# R% K3 {  j
  7. }
复制代码
3 z; [; `6 C  P' w' V( ~) {
另外,如果代码使用 HAL API 使能 MPU,即调用 HAL_MPU_Enable(),那么MemManage Fault 在 MPU 使能的函数中会自动被使能,这时候无需额外调用前面提到的代码去单独使能 MemManage Fault。
9 b; b, y3 S( e% ?2 n4 }. X0 I2 v  F# e. f7 I
1.1.5. Secure Fault. w8 d4 q0 p* w7 T/ h% X
Secure Fault 只有在 TrustZone 使能的环境下才存在。SecureFault 可能由于内核中各种各样的安全检查而触发,例如从 NS 跳转至 S 代码时没有从 SG 入口指令进入,或者非安全代码试图访问 SAU/IDAU 规定的安全地址范围等。通常当出现 SecureFault 时,软件的处理可以是直接停止或者复位系统,这样做可以尽可能地避免引入安全漏洞。
7 j) m. C& g$ s0 `0 n8 x# N
' I! E% k1 G8 [3 C. _& W$ i% ?, fSecureFault 不是 Bank 的,总是 target 到 S 侧,因此只有安全代码能够处理SecureFault。SecureFault 缺省也没有使能,出现 Secure 错误时,默认触发 SecureHardFault。软件可以通过置位 SHCSR.SECUREFAULTENA 来单独使能 SecureFault,使能后Secure 错误将触发 SecureFault Handler。图 5 给出了 Secure 错误触发 Fault Handler 的一般情况。
4 _- C! I& J+ N) V- ^% v' x! E7 s" v& X. q2 p4 b4 [9 f" w  m
微信图片_20231130170508.png
2 z6 b8 }6 e* N& q: s! @
微信图片_20231130170459.png

8 S  ?4 y( R8 J  ~6 y) k) n# U$ m; J- d: T
使能或禁止 SecureFault 的示例代码如下:
, V4 d: }0 y! b
  1. void EnableSecureFault(int enable)
    ) l: N; I; M9 m( I6 s7 T
  2. {0 U$ b0 c/ s3 W* P( b" S# g1 Q
  3. if( enable == 1)5 r1 _9 @$ {( t& q$ s
  4. SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk;& W4 U1 c4 f1 C4 U. `4 N* Q2 d7 [0 f
  5. else
    4 U" Y( M/ ?0 w6 R$ U# b& M( x7 e
  6. SCB->SHCSR &= (~SCB_SHCSR_SECUREFAULTENA_Msk);7 g2 ?# }3 x, C7 X# w0 Q
  7. }
复制代码

  c; I9 |* @# d+ T2 s( ], t( ]9 H1.2. 故障升级与 HardFault
6 R3 n1 I6 Q" p5 v/ n除了 HardFault 以外,其他故障类型都具有可配置的优先级。软件可以禁止某个可配优先级的故障异常,但是不能禁止 HardFault。故障异常的优先级和对应的 mask bit 决定了内核是否会进入某个故障的处理程序,以及某个故障是否可以抢占另一个故障。
; Y! ^+ e- [3 [; g) T. U3 U! Q! i
' Y4 p9 O# l4 u/ \3 v+ P7 ?/ K
某些情况下,可配置优先级的故障可能会被当成 HardFault 处理,也就是故障升级或称中断上访,此时,这个具体的 Fault 会升级为 HardFault 故障。, S: i, b' g% c: v- G
某个 Fault 升级成 HardFault 可能有多种原因,例如:% ?* t# s6 M; v8 s' }& a  Z9 l  r
该故障 Fault 没有使能;' F6 {6 _4 R" W: ~% L! u

1 y) k( U' K9 A3 T, K, f) J  r" S例如,代码由于执行未定义的指令产生了 UsageFault,但是 UsageFault 没有被使能.( V& ?! e* n! r2 |2 F6 N
该故障的 FaultHandler 优先级不够高无法运行;/ p  ~. A# p; X8 p

) F0 L: j# o! z8 G例如,系统配置并使能了 MPU,CPU 正在执行某个中断操作,该操作试图进行地址访问时违反了 MPU 定义的访问规则,进而触发了故障,但是当前执行的中断的优先级高于 MemManage 故障的优先级。
& f) n5 R# z$ P& m( a2 D在故障的 FaultHandler 中产生了同样的故障;+ J3 C. _+ v; s& |

: l; J! U- f+ H' U9 h6 ]例如,在处理 UsageFault 的 handler 中又发生了未定义指令的情况。* r1 c, |. \: N: K1 ~2 ^# i; b
如果在进入 BusFault Handler 的时候,压栈操作又导致了 BusFault,这种情况下 BusFault 不会升级到 HardFault。这意味着,如果损坏的堆栈导致故障,即使 Fault Handler 压栈失败,故障处理程序还是会执行,但堆栈内容已损坏。2 ]) c3 q3 m: f" z; A0 }& d3 Q
只有 NMI 可以抢占 HardFault,HardFault 可以抢占任何除 Reset、NMI 或者另一个HardFault 以外的异常。当 BFHFNMINS=1 时,如果 NS 侧的 NMI Handler 产生了安全违规错误,那么它将触发 Secure HardFault,并被其抢占。
( J0 T1 Y  T7 E# y" G% p& f在获取异常向量的时候发生的 Bus 错误,总是升级到 HardFault,由 HardFault 处理,而非 BusFault。
/ U/ q/ W% l8 r2 w* g3 R& v
/ w4 @) S8 ^0 |7 }) g1.3. Fault 异常的安全状态6 V' O) r2 I: N* O
在 TrustZone 使能的环境中,故障异常可能 target 到 S 安全状态或 NS 非安全状态,这会导致 ARMv8-M 内核的行为与以往 ARMv6-M 及 ARMv7-M 内核有很大不同,TrustZone 环境软件开发中对 Fault 的处理要特别注意到这一点。: M0 X8 S: x7 C5 @0 V
关于 Fault 异常 target 到 S、NS 的情况在前文中介绍几个 Fault 类型的时候已经有提到,这里在表 2 中再稍加总结。
' c( g7 e4 G1 d4 W6 k* Z$ f* W' L, I* f( n1 j6 N& L) w4 Q
微信图片_20231130170455.png
7 a$ G7 @) y! {+ W# s6 ~% |
5 F- V. V6 ?( h4 o
1.4. 异常的进入与返回
3 O5 K& c4 o' Y6 d1 ]5 T& ~1.4.1. 异常的进入与 stack frame
1 N' V, p+ I+ _5 N; @( h) P当处理器处于线程模式且系统存在具有足够优先级的 pending 异常时则会进入异常,或者新异常的优先级高于正在处理的异常,这时候新异常将抢占原始异常,即出现异常嵌套。7 q9 n7 x  @* u+ Y. |
当处理器发生异常时,除非该异常是尾链异常或延迟到达的异常,否则处理器会将上下文信息压入堆栈,压栈的数据结构即 stack frame。
  u9 P8 q# M3 K6 Q通常 stack frame 的内容如图 6 (a) 所示,包含了 R0 到 R3、R12、LR、PC 和 xPSR 的内容。在 TrustZone 使能的环境中,如果 S 安全代码执行被 NS 非安全异常抢占,那么进入非安全异常前会有更多的信息压栈,如图 6 (b)所示,并且硬件会自动将压栈的寄存器清零,防止任何安全状态下的数据暴露给非安全代码。, w5 q5 t2 S+ o2 s8 U
如果使用了浮点功能,存在浮点上下文,那么内核也会自动将浮点相关的上下文内容压栈。由于浮点部分数据内容对我们通常的 Fault 调试没有太多帮助,这里不做赘述。
. s& @8 y+ d1 ?) B# A$ E4 t6 {1 F进入异常前的 stack frame 压栈操作使用 MSP 还是 PSP,取决于当时内核的运行状态及其使用的堆栈。如果当时 CPU 运行于 Handler 模式,则使用 MSP 压栈 stack frame;如果 CPU运行于 Thread 模式,由当时的 CPU CONTROL.SPSEL 位来标记使用的堆栈。; _0 X( \0 G- A: _

! i  y3 p& v/ p0 L1 w; M7 D
: y7 L) `* A* a
转载自: STM325 ~; ?" A1 J" T' @! L! @9 A
如有侵权请联系删除
: \8 X8 G+ `" B5 C
$ N* I" K) X. s) o% J3 p

. f9 n- t% q& T4 w7 }, P9 W$ I+ X2 u
赞 收藏 评论0 发布时间:2023-11-30 17:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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