FreeRTOS移植程序卡在HardFault_Handler中断处理函数中
硬件环境stm32f103c8t6
使用stm32cubemx生成代码;使用TIM4;移植FreeRTOSv10.3.0
使用官方Demo中的FreeRTOS_Config.h
新增以下三个宏定义:
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
SVC提供上下文切换功能、PendSV提供任务调度功能、SysTicjk提供RTOS心跳机制;
使用这三个宏可以确保RTOS不使用stm32默认的空回调函数、而是使用RTOS提供的汇编代码以及Systick中断回调代码;
以下为AI总结:
您问到了 HardFault 的核心原因!
答案是:即使您没有定义这三个宏,这三个函数依然存在,但它们是空的(或错误的),并且与 HardFault 机制密切相关。
1. 为什么 HardFault 发生?
当您没有定义这三个宏时,CPU 依然会执行 SVC_Handler 和 PendSV_Handler,因为它们写在 STM32 的启动文件(.s 文件)中。
这些启动文件中的默认实现通常是:
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B . ; <-- 无限循环
ENDP
问题不在于函数本身空不空,而在于 FreeRTOS 试图在启动时依赖这些函数做内存操作。
-
vTaskStartScheduler()内部:- FreeRTOS 计算第一个任务的栈地址和初始寄存器值。
- FreeRTOS 触发 SVC 异常(调用
SVC_Handler)。
-
当
SVC_Handler是默认空函数时: 它没有执行 FreeRTOS 提供的汇编代码(vPortSVCHandler),就没有进行 栈指针的切换(从 MSP 切换到 PSP)。 -
后果: FreeRTOS 的启动流程被破坏,导致内存中的栈环境被错误使用或破坏,最终触发 HardFault。HardFault 发生在 FreeRTOS 的启动汇编代码无法找到正确入口或内存状态错误时。
2. 为什么定义了宏就正常了?
当您添加了这三个宏后:
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
这些宏使得 FreeRTOS 提供的包含正确汇编代码的函数(例如 vPortSVCHandler)覆盖了启动文件中的默认空函数。
结果:
- 当 FreeRTOS 触发 SVC 时,程序执行的是 正确的汇编代码,它成功完成了 栈指针的切换 和 寄存器的初始化。
- 内存环境恢复正常,启动成功,避免了 HardFault。
所以,您的异常不是因为宏本身,而是因为宏缺失导致了 FreeRTOS 启动时,关键的汇编内存操作(上下文切换)没有被执行,从而引发了内存访问错误。
Hardfault参考网站
浙公网安备 33010602011771号