Nucleo-WL55JC1更换FreeRTOS时基源触发死循环问题排查
Nucleo-WL55JC1 更换FreeRTOS时基源后程序卡死问题分析与解决
问题背景
使用Nucleo-WL55JC1开发板搭建FreeRTOS双线程LED闪烁示例,为规避CubeIDE警告,将系统时基源从SysTick替换为TIM1后,程序无法正常运行:指定的PB15引脚蓝色LED始终不亮,暂停调试后发现程序卡在startup_stm32wl55jcix.s文件的默认中断处理死循环中;改回SysTick时基源后,程序运行恢复正常。
相关代码如下:
main.c 核心代码片段
/* 闪烁线程实现 */ void StartBlink01(void *argument) { for(;;) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_15); osDelay(500); } } void StartBlink02(void *argument) { for(;;) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_15); osDelay(600); } } /* TIM1周期中断回调 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM1) { HAL_IncTick(); } } /* GPIO初始化函数 */ static void MX_GPIO_Init(void) { __HAL_RCC_GPIOC_CLK_ENABLE(); }
CubeIDE生成的TIM1中断处理函数
void TIM1_UP_IRQHandler(void) { HAL_TIM_IRQHandler(&htim1); }
原因分析
- TIM1中断优先级配置错误:FreeRTOS调度依赖系统时基中断,若TIM1的中断优先级低于
configMAX_SYSCALL_INTERRUPT_PRIORITY(FreeRTOS配置中定义的可调用系统API的最低中断优先级),会导致调度器无法正常切换线程,触发未处理中断进入死循环。 - TIM1初始化不完整:仅修改时基源选择但未正确配置TIM1的时钟使能、预分频器、自动重装载值等参数,会导致定时器无法产生1ms周期的中断,
uwTick停止更新,osDelay等FreeRTOS时间相关API失效,线程无法被调度。 - GPIOB时钟未启用:
MX_GPIO_Init仅开启了GPIOC时钟,LED所在的GPIOB时钟未使能,即使线程执行引脚翻转操作也无法控制LED状态。 - NVIC未启用TIM1中断:若CubeMX未正确配置NVIC开启TIM1更新中断,会导致定时器触发中断后无对应处理函数,跳转到默认死循环。
解决步骤
完整配置TIM1定时器
在CubeMX中重新配置TIM1:- 选择正确时钟源,根据系统时钟计算预分频器和自动重装载值,确保定时器每1ms触发一次更新中断(例如MSI时钟4MHz时,预分频器设为3,自动重装载值设为999)。
- 启用TIM1的更新中断。
- 在NVIC设置中,将TIM1_UP_TIM16_IRQn的中断优先级设置为高于
configMAX_SYSCALL_INTERRUPT_PRIORITY(例如抢占优先级设为5,子优先级设为0,具体需匹配FreeRTOS配置)。
启用GPIOB时钟
修改MX_GPIO_Init函数,添加GPIOB时钟使能:static void MX_GPIO_Init(void) { __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); // 新增:开启GPIOB时钟 }验证中断配置
确认stm32wlxx_it.c中的TIM1_UP_IRQHandler正确调用HAL_TIM_IRQHandler(&htim1),且HAL_TIM_PeriodElapsedCallback中正确判断TIM1实例并执行HAL_IncTick()。检查FreeRTOS配置
打开FreeRTOSConfig.h,确保configUSE_TIMERS设置为1,且configMAX_SYSCALL_INTERRUPT_PRIORITY的配置不阻止TIM1中断的正常触发。
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

