在裸机里,__disable_irq() 只是关掉全局中断,代码执行完再开,逻辑简单可控。但在 FreeRTOS 下,调度器本身依赖 SysTick 和 PendSV 中断来切换任务,而 __disable_irq() 会把这些中断一并屏蔽。如果你在临界区里调用了会阻塞的 API(如 vTaskDelay、xQueueReceive),任务无法被切换,系统直接死锁;即使不阻塞,长时间关中断也会让 SysTick 丢失,导致时间片统计和延时精度崩坏。正确做法是使用 FreeRTOS 提供的 taskENTER_CRITICAL()/taskEXIT_CRITICAL(),它们通过 BASEPRI 只屏蔽低于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的中断,保留高优先级中断和调度器节拍。若必须用底层指令,应使用 portSET_INTERRUPT_MASK_FROM_ISR() 或 vPortRaiseBASEPRI(),并严格配对、尽量短小。记住:临界区不是关中断,而是“只关不该被打断的那部分”。
mcuku 阿沐 · 2026-10-07