电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

800

主题

800

帖子

6001

积分

高级会员

Rank: 5Rank: 5

积分
6001
发表于 昨天 08:01 | 显示全部楼层 |阅读模式

htvev0ckipd64013313337.gif

htvev0ckipd64013313337.gif
1 L- p9 f* P" v# c6 O2 i& A
点击上方蓝色字体,关注我们
+ G% J) Q  ^; L8 z6 T1 D9 p# U) S. v* i: ^+ C- t8 h4 I

$ W0 z' T) o& z* {0 d3 e在你遇到的问题中,关键在于RTOS(UCOSIII)与Bootloader之间的跳转、中断向量表的管理、堆栈/堆空间的管理以及外设初始化等方面。
1 {7 x2 H+ B8 R) F2 w; @/ ^
/ t; n# n2 d* P. T, g+ V7 Z7 I

lkerfrqmnzk64013313438.png

lkerfrqmnzk64013313438.png
$ p# Z0 [2 t3 w4 ~2 z
根据你的描述,裸机应用没有问题,但RTOS应用从Bootloader跳转后触发串口发送数据时会导致HardFault,下面是对这个问题的深入分析与解决方案:9 Q$ f% t5 ]& O, D

' M1 a! N& p/ w1 p& D

qpjh1uzwwv464013313538.jpg

qpjh1uzwwv464013313538.jpg

6 m0 D% p1 d& |- C0 }2 A; w1 U3 U
1+ n  C% M* ]3 ^1 V7 v' \) `3 k
堆栈管理与任务上下文切换- x4 B  J. X  A0 y9 Z2 m- ^
在RTOS中,系统会管理任务的上下文切换、堆栈和堆内存。
9 k7 ~: O$ l0 \% P5 I, _; X1 \
& d. ]! j; m/ `& a当从Bootloader跳转到应用时,RTOS可能没有正确处理任务上下文、堆栈指针(SP)或任务的内存分配,这可能导致应用运行后访问非法内存或执行非法指令,从而触发HardFault。$ `0 c2 Z( T7 s! }0 G
! L2 b6 W9 _) J9 q" l+ X
问题点分析:  Q7 I+ i4 g- t- W/ {5 e: w
  • 任务堆栈:UCOSIII会为每个任务分配堆栈空间,当任务切换时会保存和恢复上下文。如果从Bootloader跳转到应用时,任务的上下文(包括堆栈)可能未正确恢复,或者堆栈空间不足以处理串口数据发送操作,导致栈溢出或堆栈指针失效。
  • 堆空间管理:RTOS管理堆内存的分配与释放。如果堆内存分配不当,可能导致在向串口发送数据时出现内存访问冲突。
    . e) N  ~% A/ \1 L" N8 ?3 j
      x" M) a! ]/ m
    解决方案:. T# ?  d" I4 M0 }) s
  • 检查堆栈和堆的分配:确认在RTOS应用中,堆栈和堆空间是否足够大,避免与其他内存区域发生冲突。你可以尝试在跳转前确认RTOS的任务栈大小和堆的状态。
  • 上下文恢复:检查在从Bootloader跳转到应用时,是否正确恢复了堆栈指针。可以在跳转时,手动恢复堆栈指针和其他重要的寄存器信息。
      x5 @( G7 ]( x  O

    , M3 R; A! n$ _8 T) w$ i" r5 S2
    % q8 i5 d& Y6 t" [3 Z; G9 P% D中断向量表的切换  f) O( f9 e7 d! r9 y
    在STM32中,中断向量表(IVT)存储了各个中断处理程序的地址。
    7 Q5 P. L$ l% M; x) `
    5 s, I; L* [" m- I在应用和Bootloader之间切换时,必须确保IVT正确切换到应用的中断表。
    0 [3 O( S! K. G; @( m3 i( }1 t; F" F* K  N$ j
    否则,当串口发送数据时,会出现错误的中断处理程序,导致HardFault。( v$ P$ X4 X( J7 X
    2 V! h& h6 F1 \% w' w( D
    问题点分析:在Bootloader运行时,它会有一套自己的中断向量表。在跳转到应用时,中断向量表必须正确切换为应用的中断向量表。否则,当外设(如串口)触发中断时,系统会无法正确响应。如果IVT没有切换到应用的中断处理程序,串口中断会调用到Bootloader的无效中断处理程序,导致HardFault。
    2 i  ^% G, v4 C# \) j
    1 H2 F* E6 k% A& k解决方案:手动切换中断向量表,在从Bootloader跳转到应用时,需要通过设置SCB->VTOR寄存器来切换到应用的中断向量表。确保在跳转时,正确指向应用的中断向量表。* I1 N+ z+ C+ ]7 W" `! k8 ?

    5 }; t1 N) M/ T, i1 \: u2 ~+ r
  • // 在跳转前设置中断向量表位置SCB->VTOR = APPLICATION_VECTOR_TABLE_ADDRESS;__DSB();  // Ensure the update to VTOR is done
    6 @" |* i& p( O' f3; l: n9 F' h9 |
    外设初始化问题
    2 n1 q! T) [  k( @从Bootloader跳转到应用时,外设(尤其是串口、DMA等)可能没有正确初始化,或者串口相关的硬件状态没有恢复。+ T& K4 y) o3 ]
    ! n, P$ A; ~- p: W  l/ a/ K
    比如,Bootloader可能已经改变了串口的配置或者中断使能状态,导致在应用中向串口发送数据时,出现访问冲突或非法操作,进而引发HardFault。
    & f* y! u5 v% h% E  B- V0 g
    % }% m2 f9 V7 L4 C) O问题点分析:
    ! h5 F' Y# c2 N+ {
  • 串口初始化:Bootloader可能在运行过程中对串口硬件进行了配置,而应用再次访问串口时,串口硬件的状态可能没有正确恢复,导致访问冲突。
  • DMA/中断状态:如果串口使用了DMA或者中断,Bootloader中可能会修改DMA或者中断的相关寄存器状态,导致在跳转到应用后,串口操作异常。
    1 J3 C* ?  p4 [7 z

    * l2 @7 p' `# z% Z& J- J解决方案:重新初始化串口,在从Bootloader跳转到应用时,重新初始化串口和相关的外设。即使Bootloader和应用使用相同的串口,也建议在应用开始前进行串口的重新配置。
    $ m$ i* i( m: v6 o0 B. T
    ! [9 B' q, w! e; p$ ~' Q/ ^" Y9 j  s
  • // 重新初始化串口UART_Init(UART_HandleTypeDef *huart);
    7 p8 S- C( l/ l, D0 d+ D: I4
    ' x/ Y0 U9 @/ x! ^6 Y. n) ~Bootloader与应用之间的跳转处理5 [# p/ ]# d' {9 c9 J/ u% x6 y9 l
    从Bootloader跳转到应用时,可能存在一些资源未正确恢复,或者跳转时中断向量表、堆栈等没有被正确设置,导致应用在启动时处于不稳定的状态。
    6 b# [1 a0 Y/ m8 O0 r$ y8 v5 z" T) C' Z2 }+ w- ^
    特别是,如果在跳转时没有重置一些外设的状态,可能会导致应用启动后,外设状态未恢复,从而触发HardFault。
    7 A! _! ^" n8 F
    0 Y5 Y# I% J9 n! a9 Q8 \4 O. D问题点分析:7 m& t/ y% K% r/ b) ~  V3 W
  • 跳转地址:Bootloader和应用之间的跳转地址必须正确设置。如果跳转地址错误,或者跳转后堆栈指针(SP)和程序计数器(PC)没有正确初始化,会导致异常的程序行为。
  • 资源恢复:Bootloader中可能修改了一些外设配置或时钟设置,跳转到应用时这些设置可能没有恢复,导致系统异常。: V1 S7 g& i1 H6 {
    3 r  t- ?7 t4 U3 `
    解决方案:手动设置跳转地址,确保从Bootloader跳转到应用时,正确设置程序计数器(PC)和堆栈指针(SP),并且确保跳转时的环境状态是稳定的。
    ( G" R& x+ o& z8 {4 S8 b9 \4 `. q' S$ e9 \+ ]/ L+ P" w+ w
  • 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();  // 跳转到应用
    4 O/ i& @* {2 p1 K5
    # s: w2 Y" Y' UARM Cortex-M4的硬件故障处理  p! ~& T/ o* }) p: W1 b1 J' q
    Cortex-M4内核会在发生硬件异常时触发HardFault。
    9 g. V! F: i  Z1 h9 B
    ) L, Z$ c: r* u& c' k9 R, t. l通过查看HardFault异常的堆栈信息,你可以定位具体的错误原因。# a" h) k% W" d7 |
    : M# H) Q( H! A- D+ _( m, X
    问题点分析:堆栈信息,可以通过配置HardFault异常处理程序,获取堆栈信息(如LR、PC等),帮助你定位错误发生的位置。
    / v) K) P" B# H6 s6 y: l6 p) R& x" l, ^) {
  • // 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等信息}; H2 M# J5 Z9 K. H' \

    ndb4giqg3tz64013313638.jpg

    ndb4giqg3tz64013313638.jpg

    " I6 C3 I/ }1 h6 s- M3 P0 _" f6 h8 p

    0p0whlpessz64013313738.gif

    0p0whlpessz64013313738.gif
    4 j; w1 ~& P5 d- y6 p
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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