STM32F411RE调用FreeRTOS调度器后程序卡死问题求助
我在STM32F411RE开发板上运行FreeRTOS任务,核心代码如下:
void my_task(void *pvParameters) { while (1) { // Example: // Turn on LED // delay // Turn off LED } } int main(void) { BaseType_t task_created = xTaskCreate(my_task, "my_task", 1024, NULL, 3, NULL); if (task_created != pdPASS) { // do something. } vTaskStartScheduler(); return 0; }
调用vTaskStartScheduler()后,timer.c中的prvTimerTask函数执行到prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty )时卡死,此时xNextExpireTime = 0且xListWasEmpty = 1。
使用GDB调试时,单步进入prvProcessTimerOrBlockTask函数不会卡死,可执行到下一个函数prvProcessReceivedCommands(),但执行该函数时仍会卡死。
FreeRTOSConfig.h中的相关配置如下:
#define configCPU_CLOCK_HZ 100000000UL //100MHz #define configSYSTICK_CLOCK_HZ (configCPU_CLOCK_HZ) #define configTICK_RATE_HZ (100) #define configUSE_TIMERS 1 #define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) #define configIDLE_SHOULD_YIELD 1 #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 64 * 1024 ) )
请问为何调用调度器后会出现这种卡死情况?
1. SysTick时钟配置不匹配
STM32F411RE的SysTick时钟默认是AHB时钟的1/8,但你直接将configSYSTICK_CLOCK_HZ设为与configCPU_CLOCK_HZ一致(100MHz),若未提前修改SysTick的时钟源为AHB不分频,会导致tick计数计算完全错误,最终让xNextExpireTime出现异常值0,触发定时器任务的错误阻塞逻辑。
解决办法:
- 若未修改SysTick时钟源,修正配置:
#define configSYSTICK_CLOCK_HZ (configCPU_CLOCK_HZ / 8) - 若已通过
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK)将时钟源改为AHB不分频,需确认该代码执行在vTaskStartScheduler()之前。
2. 定时器任务栈空间不足
默认情况下,prvTimerTask使用configMINIMAL_STACK_SIZE作为栈大小,你设置的128字(对应512字节)在处理定时器命令时可能不够用。单步调试时栈压力小,能走到prvProcessReceivedCommands(),但执行该函数时栈溢出,触发异常导致卡死。
解决办法:
在FreeRTOSConfig.h中单独增大定时器任务栈空间:
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) // 例如改为256字
3. 系统时钟初始化错误
如果SystemClock_Config()未将STM32F411RE的AHB时钟正确配置到100MHz,configCPU_CLOCK_HZ的定义与实际硬件时钟不匹配,会导致FreeRTOS的tick周期计算错误,进而引发定时器任务异常。
解决办法:
检查系统时钟初始化代码,通过读取RCC->CFGR寄存器验证实际AHB时钟频率是否为100MHz,确保硬件配置与configCPU_CLOCK_HZ一致。
4. 中断优先级配置冲突
FreeRTOS要求SysTick中断优先级必须低于configMAX_SYSCALL_INTERRUPT_PRIORITY,若优先级配置错误,SysTick中断无法正常触发,系统tick停止更新,最终导致xNextExpireTime异常。
解决办法:
在FreeRTOSConfig.h中补充中断优先级配置(适配STM32F411RE的4位优先级分组):
#define configPRIO_BITS 4 #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 #define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) #define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
同时确保SysTick的中断优先级设置符合上述要求。
内容的提问来源于stack exchange,提问作者EvG

