从裸机到 FreeRTOS:中断服务程序里调用 xQueueSendFromISR 的边界条件与实测延迟

· 5 浏览

回答(4)

若数据量大,可考虑用流缓冲区 xStreamBufferSendFromISR,比队列开销小,且支持单生产者单消费者场景。
RTOS爱好者 · 2026-10-09
实测延迟受队列长度和内存屏障影响,建议用 DWT 周期计数器测,比 GPIO 翻转更精确,能到 CPU 周期级。
码农小陈 · 2026-10-09
补充一点:如果 ISR 优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY,调用 FromISR 会直接触发断言,调试阶段务必打开 configASSERT。
嵌入式老张 · 2026-10-09
在 FreeRTOS 中,ISR 里必须用 xQueueSendFromISR(或 xQueueSendToBackFromISR),不能调用阻塞版 xQueueSend。关键边界条件:1) 中断优先级必须低于 configMAX_SYSCALL_INTERRUPT_PRIORITY(Cortex-M 上数值越大优先级越低),否则会触发 configASSERT 或破坏内核临界区;2) 必须传入 pxHigherPriorityTaskWoken 变量,并在 ISR 退出前根据其值调用 portYIELD_FROM_ISR(),否则被唤醒的高优先级任务要等下一个 tick 才运行;3) 队列满时函数立即返回 errQUEUE_FULL,不会阻塞,需自行处理丢包或计数;4) 不要在 ISR 中做耗时操作,发送的数据最好用值传递或指向静态/全局缓冲区。实测延迟方面,在 STM32F407 @168MHz 上,空队列发送约 1.2~2.5us,队列满返回约 0.8us,加上 portYIELD_FROM_ISR 的上下文切换约 3~6us。建议用 GPIO 翻转+示波器测量,并注意编译器优化等级和中断嵌套对结果的影响。
mcuku 阿沐 · 2026-10-09

🧰 配套工具

⏱️ 定时器计算器