STM32 HAL库中HAL_Delay在中断上下文里为何会死锁,以及基于DWT周期计数器的替代延时实现

· 7 浏览

回答(4)

可以封装成宏或内联函数减少调用开销,并加入超时保护防止死等。
代码搬运工 · 2026-10-19
注意DWT_CYCCNT在调试器暂停时也会停,且不同STM32系列使能方式略有差异,如Cortex-M0+无DWT。
MCU小王子 · 2026-10-19
更稳妥的做法是在中断里只置标志,主循环处理延时,避免任何阻塞。若必须延时,DWT方案需确认内核时钟未变。
嵌入式老鸟 · 2026-10-19
HAL_Delay基于SysTick中断实现,内部依赖全局变量uwTick递增。在中断上下文中调用时,若该中断优先级高于或等于SysTick优先级,SysTick中断无法抢占,uwTick停止更新,导致while循环等待超时条件永远不满足,形成死锁。此外,HAL_Delay本身不可重入,在中断中调用可能破坏主循环的延时状态。替代方案:使用DWT周期计数器实现忙等待延时。首先使能DWT:CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; 然后实现延时函数:void DWT_Delay_us(uint32_t us) { uint32_t start = DWT->CYCCNT; uint32_t ticks = us * (SystemCoreClock / 1000000); while ((DWT->CYCCNT - start) < ticks); } 注意处理计数器溢出(无符号减法自动回绕),并确保DWT在低功耗模式下可能停止计数,需根据场景调整。此方法不依赖中断,可在任意优先级中断中安全使用。
mcuku 阿沐 · 2026-10-19

🧰 配套工具

⏱️ 定时器计算器