电子产业一站式赋能平台

PCB联盟网

搜索
查看: 189|回复: 0
收起左侧

RTOS应用跳转至Bootloader后串口发送数据引发HardFault

[复制链接]

1001

主题

1001

帖子

8809

积分

高级会员

Rank: 5Rank: 5

积分
8809
发表于 2025-2-8 08:01:00 | 显示全部楼层 |阅读模式

htvev0ckipd64013313337.gif

htvev0ckipd64013313337.gif
, M% a6 T& T! g0 R7 l; M' j4 d7 b
点击上方蓝色字体,关注我们
5 B7 X7 o+ B, V
* E5 p5 ]# B$ l& n/ @. t! \, J) Q: V
在你遇到的问题中,关键在于RTOS(UCOSIII)与Bootloader之间的跳转、中断向量表的管理、堆栈/堆空间的管理以及外设初始化等方面。1 O; R7 H2 S% c9 r0 W
/ p4 F, Q) y! ]

lkerfrqmnzk64013313438.png

lkerfrqmnzk64013313438.png
" t) f- \4 W5 A4 j5 o  a# n2 p
根据你的描述,裸机应用没有问题,但RTOS应用从Bootloader跳转后触发串口发送数据时会导致HardFault,下面是对这个问题的深入分析与解决方案:& K$ I' x& ?# l) h* I. Q7 h+ L

" {+ J' L5 }" `6 w4 ?! b4 C

qpjh1uzwwv464013313538.jpg

qpjh1uzwwv464013313538.jpg
, I% |' h) m1 F4 j$ z& U/ a

, R) u, C" K* s' D1
$ q; S+ i' s8 z; G5 W9 ?2 Z3 O. H堆栈管理与任务上下文切换  m4 l8 t' [& Q3 o! n) ]" @
在RTOS中,系统会管理任务的上下文切换、堆栈和堆内存。
9 ], m9 L/ z1 @* z; X/ m5 {* q. F" @1 d
当从Bootloader跳转到应用时,RTOS可能没有正确处理任务上下文、堆栈指针(SP)或任务的内存分配,这可能导致应用运行后访问非法内存或执行非法指令,从而触发HardFault。
( D. j) u' S6 a, B  @/ y5 ]7 R1 Z# ]
问题点分析:
3 c- k9 X, e3 z
  • 任务堆栈:UCOSIII会为每个任务分配堆栈空间,当任务切换时会保存和恢复上下文。如果从Bootloader跳转到应用时,任务的上下文(包括堆栈)可能未正确恢复,或者堆栈空间不足以处理串口数据发送操作,导致栈溢出或堆栈指针失效。
  • 堆空间管理:RTOS管理堆内存的分配与释放。如果堆内存分配不当,可能导致在向串口发送数据时出现内存访问冲突。
    8 [: W+ n7 w6 a2 R" p

    - w- _  {: e) w/ i解决方案:
    6 o! `! j% C! {2 E  D
  • 检查堆栈和堆的分配:确认在RTOS应用中,堆栈和堆空间是否足够大,避免与其他内存区域发生冲突。你可以尝试在跳转前确认RTOS的任务栈大小和堆的状态。
  • 上下文恢复:检查在从Bootloader跳转到应用时,是否正确恢复了堆栈指针。可以在跳转时,手动恢复堆栈指针和其他重要的寄存器信息。) ~5 d: O/ k& |3 c& k& n
    # ~& ?% M% ?/ J1 M+ H  P  ~! F6 L
    2  c3 o6 [, x- h; Q8 F6 v
    中断向量表的切换, ]  n7 ?6 H/ S  ~8 S3 M
    在STM32中,中断向量表(IVT)存储了各个中断处理程序的地址。
    " u) k' m4 }8 {8 H& S7 T+ _* D9 h0 p2 J. M
    在应用和Bootloader之间切换时,必须确保IVT正确切换到应用的中断表。
    + J% D& r; ?7 p2 {% s3 h# e; l" m$ m2 @5 o* `
    否则,当串口发送数据时,会出现错误的中断处理程序,导致HardFault。/ x' B* x4 z; ^0 {% F0 ~
    - R: ^3 h9 s- o: A- |  P
    问题点分析:在Bootloader运行时,它会有一套自己的中断向量表。在跳转到应用时,中断向量表必须正确切换为应用的中断向量表。否则,当外设(如串口)触发中断时,系统会无法正确响应。如果IVT没有切换到应用的中断处理程序,串口中断会调用到Bootloader的无效中断处理程序,导致HardFault。6 o) N( W7 V0 h3 O1 x# e

    2 ~8 _+ e$ q7 A; h解决方案:手动切换中断向量表,在从Bootloader跳转到应用时,需要通过设置SCB->VTOR寄存器来切换到应用的中断向量表。确保在跳转时,正确指向应用的中断向量表。/ q0 W. K+ i5 q* ^: q6 w  q( b  e4 T# z
    . a5 g( N% Q7 [* z* P
  • // 在跳转前设置中断向量表位置SCB->VTOR = APPLICATION_VECTOR_TABLE_ADDRESS;__DSB();  // Ensure the update to VTOR is done
    ' {1 o; G2 ^& h5 J) m8 H; @3  Q* B' Y5 A$ f# a7 e4 [3 L% A6 i; ~
    外设初始化问题- y3 [, S6 z+ }' }
    从Bootloader跳转到应用时,外设(尤其是串口、DMA等)可能没有正确初始化,或者串口相关的硬件状态没有恢复。: }' w/ p3 O% l. R, H2 m

    , H+ W4 Z8 p0 z比如,Bootloader可能已经改变了串口的配置或者中断使能状态,导致在应用中向串口发送数据时,出现访问冲突或非法操作,进而引发HardFault。9 Y0 y+ V5 N: L2 g5 {% t+ j, x. F* p
    ; L: E5 g) Q9 f4 S# e5 q
    问题点分析:/ A: {2 N. _5 Z
  • 串口初始化:Bootloader可能在运行过程中对串口硬件进行了配置,而应用再次访问串口时,串口硬件的状态可能没有正确恢复,导致访问冲突。
  • DMA/中断状态:如果串口使用了DMA或者中断,Bootloader中可能会修改DMA或者中断的相关寄存器状态,导致在跳转到应用后,串口操作异常。
    9 g4 u9 y; B5 i5 }, q
    % A3 P2 ^2 l: [* E
    解决方案:重新初始化串口,在从Bootloader跳转到应用时,重新初始化串口和相关的外设。即使Bootloader和应用使用相同的串口,也建议在应用开始前进行串口的重新配置。
    " |, N; s7 g# S$ T5 e, }/ p5 P$ V( x' D
  • // 重新初始化串口UART_Init(UART_HandleTypeDef *huart);" p5 K( A, R2 J6 |" i# z  G
    45 i3 j. U) R, J$ k9 [
    Bootloader与应用之间的跳转处理
    ) \" E( f9 i- V* v( w- D7 f$ f, X8 v从Bootloader跳转到应用时,可能存在一些资源未正确恢复,或者跳转时中断向量表、堆栈等没有被正确设置,导致应用在启动时处于不稳定的状态。, n" j. Z& _0 E' v3 T* D7 K
    8 ~$ l( T1 V  ?) F
    特别是,如果在跳转时没有重置一些外设的状态,可能会导致应用启动后,外设状态未恢复,从而触发HardFault。
    8 u/ t$ \8 E/ }1 }, J0 H
    0 x7 ]3 {4 h4 s9 e/ ?: `问题点分析:; i3 N! a# V, }5 @/ v; I
  • 跳转地址:Bootloader和应用之间的跳转地址必须正确设置。如果跳转地址错误,或者跳转后堆栈指针(SP)和程序计数器(PC)没有正确初始化,会导致异常的程序行为。
  • 资源恢复:Bootloader中可能修改了一些外设配置或时钟设置,跳转到应用时这些设置可能没有恢复,导致系统异常。
    7 B4 _8 T& G; d" l! P
    9 m2 ?1 d& o' e  _! a; A' Z
    解决方案:手动设置跳转地址,确保从Bootloader跳转到应用时,正确设置程序计数器(PC)和堆栈指针(SP),并且确保跳转时的环境状态是稳定的。
    1 B& L) g) K. M' h- `+ Y7 y8 }6 e7 g1 j+ z
  • typedef void (*pFunction)(void);pFunction JumpToApplication;uint32_t JumpAddress = *(volatile uint32_t*) (APPLICATION_START_ADDRESS + 4);JumpToApplication = (pFunction) JumpAddress;__set_MSP(*(volatile uint32_t*) APPLICATION_START_ADDRESS);JumpToApplication();  // 跳转到应用, E/ ~. b8 ~' o/ z5 p
    5( S" k" Z# b7 k
    ARM Cortex-M4的硬件故障处理& A0 z5 ]2 y+ r2 l3 H2 N
    Cortex-M4内核会在发生硬件异常时触发HardFault。
    ; D- \8 I& V% A2 |1 f4 k
    ) g5 {9 ^# c5 s0 z2 e通过查看HardFault异常的堆栈信息,你可以定位具体的错误原因。  n1 L4 ?( Z5 a- M- _4 }! f
    # Y8 {# d8 n  @2 K
    问题点分析:堆栈信息,可以通过配置HardFault异常处理程序,获取堆栈信息(如LR、PC等),帮助你定位错误发生的位置。
    ) M" X: s3 L) ^0 x+ _0 _$ J7 E  e( C! t1 N6 i8 a1 O6 s8 b
  • // HardFault处理程序void HardFault_Handler(void) {    // 获取堆栈信息    __asm("MRS R0, MSP");    __asm("TST LR, #4");    __asm("ITE EQ");    __asm("MRSEQ R0, MSP");    __asm("MRS R1, PSP");    // 输出寄存器R0、R1等信息}
    8 V& |9 U! B& X/ g" H* W

    ndb4giqg3tz64013313638.jpg

    ndb4giqg3tz64013313638.jpg

    ' e% i! J! L3 X9 ?1 ~: m  I! A

    0p0whlpessz64013313738.gif

    0p0whlpessz64013313738.gif
    ( u; p5 x. @! V3 n  a
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表