如何从高优先级 ISR 中唤醒 FreeRtos 任务?
Posted
技术标签:
【中文标题】如何从高优先级 ISR 中唤醒 FreeRtos 任务?【英文标题】:How to wake up a FreeRtos task from a high priority ISR? 【发布时间】:2014-12-03 14:01:21 【问题描述】:使用:
Stm32F10x、F2xx、F4xx FreeRtos 8.1.1 gcc-arm-none-eabi-4_8-2014q2我有一个必须以高中断优先级运行的 ISR,因此禁止在此 ISR 中调用 FreeRtos Api(请参阅 here 和 here)。
在某些情况下,这些 ISR 会检测到条件,在这些条件下,休眠的 FreeRtos 任务应该以至少可能的延迟唤醒。
通常(如果由于足够低的优先级而允许 ISR 调用 FreeRtos Api)我会使用队列或信号量来解决这个问题。
但是如何通过高优先级 ISR 实现这一点?
我目前的临时方法是这样的(简要概述):
volatile int flag = 0;
void XYZ_IRQHandler()
if (someCondition)
flag = 1
void FreeRtosTaskFunction(void* parameters)
for (;;)
if (flag == 1)
doSomething();
vTaskDelay(1); // sleep 10ms (tick frequency is 100Hz)
但是这种方法有缺点:
延迟(从在 ISR 中设置标志直到任务唤醒)最多为 1 个 FreeRtos 滴答声。 需要轮询标志(浪费 CPU 周期)。有什么建议可以更好地解决这个问题,尤其是延迟更短?
【问题讨论】:
【参考方案1】:我有一个想法,虽然未经测试似乎应该可行。
我假设您的 ISR 具有高优先级,因为它需要极低的延迟来执行不受其他中断影响的事情(即在准确的时间进行测量),并且任务应该很快完成,但不是t 非常关键(即传输或显示值)。
在您的高优先级 ISR 中,执行时序关键功能,然后触发低优先级内部中断。
当高优先级 ISR 完成时(以及任何其他待处理),将调用低优先级 ISR。然后它可以调用 FreeRTOS API 并立即启动任务。
【讨论】:
任何想法/链接如何触发内部中断? 好的,在 st-lib 中找到EXTI_GenerateSWInterrupt()
。不幸的是,它需要浪费一条 EXTI Line 和一个 irq 通道。但我会试一试。
Here 是另一种不使用 EXTI 的方法,但由于使用了 FreeRtos 跟踪宏,这对我的项目来说有点过于 hacky。我现在将基于 EXTI 的解决方案与 FreeRtos 信号量结合使用。【参考方案2】:
解决方案是使用 FreeRTOS Task notification。
您的任务将挂起,然后在 ISR 事件发生后立即恢复/唤醒。
【讨论】:
FreeRtos 任务通知(随 FreeRtos 8.2 引入)是信号量的不错替代品。但请注意,也不允许从具有高中断优先级的 ISR 调用该 api。以上是关于如何从高优先级 ISR 中唤醒 FreeRtos 任务?的主要内容,如果未能解决你的问题,请参考以下文章