电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

989

主题

989

帖子

8579

积分

高级会员

Rank: 5Rank: 5

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

htvev0ckipd64013313337.gif

htvev0ckipd64013313337.gif

3 n1 S, A$ F- I- c0 A) d; s点击上方蓝色字体,关注我们
5 `! h1 p: z# m: @) [& `# q8 L) V4 t# s& f# o4 n1 v6 n

+ G6 L/ r* R! |+ n) l5 g在你遇到的问题中,关键在于RTOS(UCOSIII)与Bootloader之间的跳转、中断向量表的管理、堆栈/堆空间的管理以及外设初始化等方面。1 _) k7 v; @6 z/ w$ ]) h
0 A% O4 Y  w& I0 f

lkerfrqmnzk64013313438.png

lkerfrqmnzk64013313438.png
% V4 K2 q4 L. o$ T, v0 y
根据你的描述,裸机应用没有问题,但RTOS应用从Bootloader跳转后触发串口发送数据时会导致HardFault,下面是对这个问题的深入分析与解决方案:
% q) J- w5 g! S% j5 [0 S3 I5 T
) j0 c8 {5 w  p: U" p% {  i  [6 ~

qpjh1uzwwv464013313538.jpg

qpjh1uzwwv464013313538.jpg

) k' T9 y- ~* Q. o- A  _" i7 k. z6 j- |9 ^
1
0 \8 k: S6 N! y. j' X堆栈管理与任务上下文切换
$ K0 u. d+ Z5 O6 |2 `0 S( b在RTOS中,系统会管理任务的上下文切换、堆栈和堆内存。
% \; [9 u7 a  _; y( ^" ?7 I9 ~( |6 x
当从Bootloader跳转到应用时,RTOS可能没有正确处理任务上下文、堆栈指针(SP)或任务的内存分配,这可能导致应用运行后访问非法内存或执行非法指令,从而触发HardFault。
" S% ?- y9 m6 `5 f0 X8 o, L, G/ @# ~. w
问题点分析:' Z" v4 y/ H5 n% u. I" j
  • 任务堆栈:UCOSIII会为每个任务分配堆栈空间,当任务切换时会保存和恢复上下文。如果从Bootloader跳转到应用时,任务的上下文(包括堆栈)可能未正确恢复,或者堆栈空间不足以处理串口数据发送操作,导致栈溢出或堆栈指针失效。
  • 堆空间管理:RTOS管理堆内存的分配与释放。如果堆内存分配不当,可能导致在向串口发送数据时出现内存访问冲突。+ a3 i7 p5 N/ V# v
    ( M, _4 _/ k8 F% Q! d
    解决方案:! D! T# \9 Q3 H# T+ M* {
  • 检查堆栈和堆的分配:确认在RTOS应用中,堆栈和堆空间是否足够大,避免与其他内存区域发生冲突。你可以尝试在跳转前确认RTOS的任务栈大小和堆的状态。
  • 上下文恢复:检查在从Bootloader跳转到应用时,是否正确恢复了堆栈指针。可以在跳转时,手动恢复堆栈指针和其他重要的寄存器信息。/ Z4 Y- P* E8 O
    # ]  Q' [- Z8 U$ H" w- j
    2, j* F5 `5 O1 D! L
    中断向量表的切换
    ) t1 V% _( E7 t* E- `在STM32中,中断向量表(IVT)存储了各个中断处理程序的地址。
    ) `4 j# G. i9 I. M# t' s
    % I' F8 Z0 O2 e* q在应用和Bootloader之间切换时,必须确保IVT正确切换到应用的中断表。/ d. U6 J; n% {3 [$ s6 b
    , }! K) ]# ?% o, g
    否则,当串口发送数据时,会出现错误的中断处理程序,导致HardFault。9 U7 }2 M5 q( m7 n/ d* T

    ' M4 `. v, h+ v# M问题点分析:在Bootloader运行时,它会有一套自己的中断向量表。在跳转到应用时,中断向量表必须正确切换为应用的中断向量表。否则,当外设(如串口)触发中断时,系统会无法正确响应。如果IVT没有切换到应用的中断处理程序,串口中断会调用到Bootloader的无效中断处理程序,导致HardFault。+ J) j, x/ m8 a  \" C2 w) Z
    & l7 E- w/ k$ h3 |: X
    解决方案:手动切换中断向量表,在从Bootloader跳转到应用时,需要通过设置SCB->VTOR寄存器来切换到应用的中断向量表。确保在跳转时,正确指向应用的中断向量表。+ X* K5 {* }7 ^: V; Q8 ]3 W. _+ H

    ; f7 ?1 \. `7 h  z) s
  • // 在跳转前设置中断向量表位置SCB->VTOR = APPLICATION_VECTOR_TABLE_ADDRESS;__DSB();  // Ensure the update to VTOR is done
    " Y4 `( L6 s; Q" G' `3; D& M% P+ C+ M0 C7 i" [4 m; G
    外设初始化问题
    2 L( D4 j6 G+ B/ i, m从Bootloader跳转到应用时,外设(尤其是串口、DMA等)可能没有正确初始化,或者串口相关的硬件状态没有恢复。( H0 b  ^% D* q& r/ O

    # Q2 }; l7 \3 {比如,Bootloader可能已经改变了串口的配置或者中断使能状态,导致在应用中向串口发送数据时,出现访问冲突或非法操作,进而引发HardFault。* p* L/ z" V. F: ^% e( L9 Z4 U. D
    8 a# _8 B! A3 @6 D
    问题点分析:
    . p* N$ K! G# {
  • 串口初始化:Bootloader可能在运行过程中对串口硬件进行了配置,而应用再次访问串口时,串口硬件的状态可能没有正确恢复,导致访问冲突。
  • DMA/中断状态:如果串口使用了DMA或者中断,Bootloader中可能会修改DMA或者中断的相关寄存器状态,导致在跳转到应用后,串口操作异常。
    . m: U7 l$ ^, g/ \2 ?# J  T9 e% u
    8 r3 g, c9 \% U0 v& [
    解决方案:重新初始化串口,在从Bootloader跳转到应用时,重新初始化串口和相关的外设。即使Bootloader和应用使用相同的串口,也建议在应用开始前进行串口的重新配置。1 j6 _5 V7 H  c% y  T: ?

    ( \. [  W# V; n
  • // 重新初始化串口UART_Init(UART_HandleTypeDef *huart);* Y- D* C% s+ h
    4- P/ v- V" e5 j0 H: \  t# z; [) N2 {
    Bootloader与应用之间的跳转处理
    4 O$ M$ O& X' ~# q% u  W* V3 B: J( u从Bootloader跳转到应用时,可能存在一些资源未正确恢复,或者跳转时中断向量表、堆栈等没有被正确设置,导致应用在启动时处于不稳定的状态。4 N. \  ]6 O. y6 d, u/ u5 s+ c
    9 `2 W; A9 n/ E/ A  U& |8 P$ v, m
    特别是,如果在跳转时没有重置一些外设的状态,可能会导致应用启动后,外设状态未恢复,从而触发HardFault。
    & O% g0 R  h6 t
    , r. @6 V6 ?4 u问题点分析:! K4 h8 C* n# J
  • 跳转地址:Bootloader和应用之间的跳转地址必须正确设置。如果跳转地址错误,或者跳转后堆栈指针(SP)和程序计数器(PC)没有正确初始化,会导致异常的程序行为。
  • 资源恢复:Bootloader中可能修改了一些外设配置或时钟设置,跳转到应用时这些设置可能没有恢复,导致系统异常。8 o: P1 t; H! G5 F
    " u& b! n3 }+ J. }1 {
    解决方案:手动设置跳转地址,确保从Bootloader跳转到应用时,正确设置程序计数器(PC)和堆栈指针(SP),并且确保跳转时的环境状态是稳定的。
    , M$ w# X$ [% g4 K8 V
    4 m9 u1 H  I2 M; g6 e/ b# e
  • 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();  // 跳转到应用% _- M4 ~( _) B6 m9 m! J
    5
    , y% r! h% o: u# L* nARM Cortex-M4的硬件故障处理% O: Q6 ]0 _" E4 I6 f# L
    Cortex-M4内核会在发生硬件异常时触发HardFault。+ c+ K1 F: h3 B0 c

    7 i& g7 m; [4 F9 h! U9 L/ O通过查看HardFault异常的堆栈信息,你可以定位具体的错误原因。, a" y8 {8 Z" |% n

    ! q# P9 ]" X6 t9 I1 W+ ]1 u4 O问题点分析:堆栈信息,可以通过配置HardFault异常处理程序,获取堆栈信息(如LR、PC等),帮助你定位错误发生的位置。
    - i4 n- V! _) |4 ?$ B2 i8 R% Z2 }) \: I
  • // 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等信息}& ~0 e4 o6 n: |. T: k6 Z

    ndb4giqg3tz64013313638.jpg

    ndb4giqg3tz64013313638.jpg

    ' j6 J2 X5 l! o- l

    0p0whlpessz64013313738.gif

    0p0whlpessz64013313738.gif

    - Q- @$ B% I4 S/ f3 U点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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