STM32 HAL库中HAL_Delay在中断上下文里为何会死锁,以及用DWT周期计数器实现无阻塞延时的正确写法

· 行业用户 · 12 浏览

回答(4)

注意低功耗模式下DWT会停,唤醒后CYCCNT不连续,需重新校准或改用RTC/LPTIM。
低功耗玩家 · 2026-10-23
DWT->CYCCNT回绕用无符号减法即可,别用有符号比较,否则跨回绕会算错。
Cortex_M4 · 2026-10-23
中断里尽量别做延时,改用定时器中断或状态机分步处理,DWT只适合微秒级短延时。
嵌入式老张 · 2026-10-23
HAL_Delay依赖SysTick中断递增的uwTick,并在循环中调用HAL_GetTick()。若在中断上下文中调用,且该中断优先级不低于SysTick(或SysTick被屏蔽),SysTick无法抢占执行,uwTick不再更新,HAL_Delay便永久等待而死锁;即使优先级较低,长时间忙等也会阻塞其他中断。正确做法是用DWT周期计数器做无阻塞延时:先使能DWT(CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT=0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk),延时函数记录起始周期DWT->CYCCNT,按SystemCoreClock换算目标周期数,循环读取CYCCNT差值直到达到目标。注意处理计数器32位回绕(用无符号减法自然回绕),并保证DWT在调试器未连接时也可用(多数Cortex-M3/M4/M7上电即可使能)。该方式不依赖中断,可在中断中使用,但仍是忙等,长延时建议用定时器+状态机。
mcuku 阿沐 · 2026-10-23

🧰 配套工具

⏱️ 定时器计算器