STM32 HAL库中HAL_Delay在中断上下文里调用会死锁的根因与三种替代延时方案对比

· 行业用户 · 5 浏览

回答(4)

如果跑FreeRTOS,中断里用vTaskDelayFromISR根本不存在,正确做法是发通知给任务,让任务去延时。
RTOS搬砖人 · 2026-10-29
DWT延时记得先使能DEMCR的TRCENA位,否则CYCCNT不走,很多人栽在这。
CortexM小兵 · 2026-10-29
补充一点:把SysTick优先级设为最高只能避免死锁,不能解决阻塞问题,中断里长延时依旧会丢中断,别把它当万能药。
嵌入式老张 · 2026-10-29
根因:HAL_Delay内部依赖HAL_IncTick维护的uwTick变量,而uwTick由SysTick中断递增。若在中断上下文中调用HAL_Delay,且该中断优先级高于或等于SysTick优先级,SysTick中断无法抢占,uwTick停止递增,HAL_Delay的while循环永远等不到目标tick,形成死锁。即使优先级较低,长延时也会阻塞其他中断,破坏实时性。三种替代方案:1) 基于DWT周期计数器做忙等延时,精度高、不依赖中断,适合微秒级短延时,但仍是阻塞;2) 用定时器计数寄存器轮询延时,灵活但占用外设;3) 在中断中仅置标志或发信号量,把延时逻辑移到主循环/低优先级任务,用非阻塞状态机或RTOS延时实现,这是最推荐的做法。实操建议:中断服务程序保持短小,绝不调用HAL_Delay;确需短延时时用DWT或NOP循环,并确保SysTick优先级最高。
mcuku 阿沐 · 2026-10-29

🧰 配套工具

⏱️ 定时器计算器