电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

905

主题

905

帖子

7256

积分

高级会员

Rank: 5Rank: 5

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

htvev0ckipd64013313337.gif

htvev0ckipd64013313337.gif

9 T( I  `/ L9 \点击上方蓝色字体,关注我们% P1 i  R% F) Q" A" @4 C
/ _' d2 C& M& Y. T0 p0 k  j1 W

% J6 a6 N! q- c/ G, U5 I在你遇到的问题中,关键在于RTOS(UCOSIII)与Bootloader之间的跳转、中断向量表的管理、堆栈/堆空间的管理以及外设初始化等方面。
, J+ v" ]9 D. m$ I6 G2 F2 [
0 w: l. X) |, @0 |: L) |

lkerfrqmnzk64013313438.png

lkerfrqmnzk64013313438.png

: |% A" T1 `1 [5 Q# ?9 C根据你的描述,裸机应用没有问题,但RTOS应用从Bootloader跳转后触发串口发送数据时会导致HardFault,下面是对这个问题的深入分析与解决方案:; q4 P5 e* v/ B/ n1 _
$ q6 w+ p* A' Z4 i

qpjh1uzwwv464013313538.jpg

qpjh1uzwwv464013313538.jpg
9 B0 H5 Y7 }8 m1 p$ G2 O# [; j

  x, h) ?# C! s5 D: J4 B1
1 z9 X+ t7 e) z, R  q. \堆栈管理与任务上下文切换: ^0 O+ c% j. R* P2 a
在RTOS中,系统会管理任务的上下文切换、堆栈和堆内存。6 b; N$ X( a# K, R8 b8 r

) O& H6 N+ a% N- k& q) x" J; Q1 J当从Bootloader跳转到应用时,RTOS可能没有正确处理任务上下文、堆栈指针(SP)或任务的内存分配,这可能导致应用运行后访问非法内存或执行非法指令,从而触发HardFault。) C' R5 t7 U7 `& ?  d' `4 w3 {3 ^' z

: J3 P; t' ]/ t% q1 z! y6 y7 g问题点分析:. F2 |4 L5 k* r5 l8 D2 ~" ^: `; K6 R& s
  • 任务堆栈:UCOSIII会为每个任务分配堆栈空间,当任务切换时会保存和恢复上下文。如果从Bootloader跳转到应用时,任务的上下文(包括堆栈)可能未正确恢复,或者堆栈空间不足以处理串口数据发送操作,导致栈溢出或堆栈指针失效。
  • 堆空间管理:RTOS管理堆内存的分配与释放。如果堆内存分配不当,可能导致在向串口发送数据时出现内存访问冲突。# y' Z( R: h4 L, S3 i- n- k  Z. l% a
    , `& V# F# [: v  m* Z
    解决方案:
    5 N5 G/ t& @: N
  • 检查堆栈和堆的分配:确认在RTOS应用中,堆栈和堆空间是否足够大,避免与其他内存区域发生冲突。你可以尝试在跳转前确认RTOS的任务栈大小和堆的状态。
  • 上下文恢复:检查在从Bootloader跳转到应用时,是否正确恢复了堆栈指针。可以在跳转时,手动恢复堆栈指针和其他重要的寄存器信息。
    # ~6 @8 g. M. J1 P
    9 b! d% L2 E- |) L1 c$ j' |
    2. p* {, R# G' R7 C& D7 }
    中断向量表的切换
    " q  x5 P) S* g8 T+ L在STM32中,中断向量表(IVT)存储了各个中断处理程序的地址。
    6 u/ I! Y( n7 P7 x5 a  G% A9 G" e3 U9 k2 z* t6 n7 c; M% K
    在应用和Bootloader之间切换时,必须确保IVT正确切换到应用的中断表。
    1 ~7 _0 O4 ~# V& m! @, Z; f; r' ^$ ?( E
    否则,当串口发送数据时,会出现错误的中断处理程序,导致HardFault。
    3 c2 l9 _9 Z) h6 E6 ?- L" R0 }# y3 L+ w- r/ [
    问题点分析:在Bootloader运行时,它会有一套自己的中断向量表。在跳转到应用时,中断向量表必须正确切换为应用的中断向量表。否则,当外设(如串口)触发中断时,系统会无法正确响应。如果IVT没有切换到应用的中断处理程序,串口中断会调用到Bootloader的无效中断处理程序,导致HardFault。
    . f7 p0 L+ `+ u8 `. D
    7 h0 v) e, x  ^" [; p解决方案:手动切换中断向量表,在从Bootloader跳转到应用时,需要通过设置SCB->VTOR寄存器来切换到应用的中断向量表。确保在跳转时,正确指向应用的中断向量表。
    " O) y7 l7 q9 r- C: ~
    % {$ g+ V1 g6 O& L0 n3 z
  • // 在跳转前设置中断向量表位置SCB->VTOR = APPLICATION_VECTOR_TABLE_ADDRESS;__DSB();  // Ensure the update to VTOR is done. U3 Y/ t1 N0 v$ u- D7 \. n
    3
    : Y* P* I+ y9 ^( @+ o外设初始化问题8 h, L7 |' s2 ^  r
    从Bootloader跳转到应用时,外设(尤其是串口、DMA等)可能没有正确初始化,或者串口相关的硬件状态没有恢复。9 w5 D2 K6 f  i9 ~4 o# _
    ! A# O2 Q  g* T5 X9 \( _
    比如,Bootloader可能已经改变了串口的配置或者中断使能状态,导致在应用中向串口发送数据时,出现访问冲突或非法操作,进而引发HardFault。
    2 c+ j! k, F6 U+ o
    5 X: a* p3 d7 B. `' d  b% j问题点分析:9 E6 T4 l+ e: h9 H1 A1 n
  • 串口初始化:Bootloader可能在运行过程中对串口硬件进行了配置,而应用再次访问串口时,串口硬件的状态可能没有正确恢复,导致访问冲突。
  • DMA/中断状态:如果串口使用了DMA或者中断,Bootloader中可能会修改DMA或者中断的相关寄存器状态,导致在跳转到应用后,串口操作异常。
    " }7 w. T* M6 ?

    7 [1 n' O2 b, J* T! G% M解决方案:重新初始化串口,在从Bootloader跳转到应用时,重新初始化串口和相关的外设。即使Bootloader和应用使用相同的串口,也建议在应用开始前进行串口的重新配置。9 i7 f; N! h3 |! O7 e9 ?% I# a

    * I, D, G9 }2 {" \* ?
  • // 重新初始化串口UART_Init(UART_HandleTypeDef *huart);5 M0 _/ \' ?% O6 G+ M7 a
    4( `/ n8 I$ n2 \" i5 i* D' {
    Bootloader与应用之间的跳转处理+ k9 g# v1 E, Y, s
    从Bootloader跳转到应用时,可能存在一些资源未正确恢复,或者跳转时中断向量表、堆栈等没有被正确设置,导致应用在启动时处于不稳定的状态。
    ( v  k2 Y$ d5 M* H% X1 r$ B
    8 t: D6 u- T. j4 @8 {特别是,如果在跳转时没有重置一些外设的状态,可能会导致应用启动后,外设状态未恢复,从而触发HardFault。
    8 X  P( ^- W+ R: j/ z* a# I" Q
    - A% v$ X9 X1 {6 I2 K( {% c+ e9 F问题点分析:
    2 U0 R% A- \1 |) f+ N
  • 跳转地址:Bootloader和应用之间的跳转地址必须正确设置。如果跳转地址错误,或者跳转后堆栈指针(SP)和程序计数器(PC)没有正确初始化,会导致异常的程序行为。
  • 资源恢复:Bootloader中可能修改了一些外设配置或时钟设置,跳转到应用时这些设置可能没有恢复,导致系统异常。7 ?, x* N5 t3 a! U
    7 Q2 [6 a" o7 s0 E' j* K7 H
    解决方案:手动设置跳转地址,确保从Bootloader跳转到应用时,正确设置程序计数器(PC)和堆栈指针(SP),并且确保跳转时的环境状态是稳定的。% S. k2 x7 s4 J* l- a1 \
    4 L9 `) u" b! }0 `- c9 n
  • 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();  // 跳转到应用* J3 `+ o% M& t+ E5 F; u
    5
    4 w+ m1 _6 Y" v) ^8 B# j% R! {( KARM Cortex-M4的硬件故障处理
    " T  k0 @/ j. nCortex-M4内核会在发生硬件异常时触发HardFault。3 c4 T, o  b, z9 i% }, y. I

    4 R% O- Q: k$ ]+ O* B, B* C通过查看HardFault异常的堆栈信息,你可以定位具体的错误原因。
    - [) \) I: O  |8 }: G. D
    8 w, A. [1 e; S9 E  h问题点分析:堆栈信息,可以通过配置HardFault异常处理程序,获取堆栈信息(如LR、PC等),帮助你定位错误发生的位置。
    # N$ x) c! g3 B9 u8 m4 V. q3 V: T* `! ]
  • // 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等信息}
    ; i1 U3 Q. t' Y3 C( `/ n) P

    ndb4giqg3tz64013313638.jpg

    ndb4giqg3tz64013313638.jpg
    . o0 L8 ?. a! Q0 b" d4 r/ E2 I

    0p0whlpessz64013313738.gif

    0p0whlpessz64013313738.gif
    % `7 A: v/ S1 R- m" y
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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