【FreeRTOS】portYIELD_FROM_ISR函数详解


前言:这个函数总结来说作用就是使因获取信号量而进入阻塞态的高优先级任务及时被调用。

portYIELD_FROM_ISR函数介绍

portYIELD_FROM_ISR介绍

举个例子

使用 portYIELD_FROM_ISR 函数的例子,以及它如何影响任务调度的简单说明:

假设我们有两个任务:Task_A 和 Task_B,它们的优先级分别是 osPriorityNormal 和 osPriorityHigh。还有一个信号量 Sem_Event,Task_A 在等待这个信号量。

/* Task_A 代码 */
void Task_A(void *argument) {
    /* 等待信号量 Sem_Event */
    if(xSemaphoreTake(Sem_Event, portMAX_DELAY) == pdTRUE) {
        /* 信号量获取成功,执行任务 A 的代码 */
    }
}

/* Task_B 代码 */
void Task_B(void *argument) {
    /* 执行任务 B 的代码 */
}

/* 中断服务例程 */
void ISR_Function(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    /* ... 中断处理代码 ... */

    /* 释放信号量 Sem_Event */
    xSemaphoreGiveFromISR(Sem_Event, &xHigherPriorityTaskWoken);

    /* 如果有更高优先级的任务被唤醒,请求上下文切换 */
    if(xHigherPriorityTaskWoken != pdFALSE) {
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
}

在这个例子中,Task_A 正在等待一个信号量 Sem_Event。当中断发生时,ISR 被触发,并在其中处理一些事件。在 ISR 的末尾,它释放了 Sem_Event 信号量。

由于 Task_A 正在等待这个信号量,它现在被唤醒并准备运行。但是,如果 Task_B 正在执行,并且它的优先级低于 Task_A,那么 xHigherPriorityTaskWoken 将被设置为 pdTRUE。

portYIELD_FROM_ISR 函数在这里的作用是检查 xHigherPriorityTaskWoken。如果它为 pdTRUE,这意味着有一个更高优先级的任务已经准备好运行,因此在 ISR 结束后,调度器应该立即进行上下文切换到 Task_A。

这个例子展示了 portYIELD_FROM_ISR 如何与信号量和任务优先级协同工作,以确保在 ISR 中释放信号量后,更高优先级的任务可以得到及时的响应。这是实现实时操作系统响应性的关键机制之一。
注意,这个例子是为了说明概念而简化的,实际应用中可能需要考虑更多的细节。

常见问题汇总

Task_A等待信号量的时候是什么运行状态,为什么?

解答:
当 Task_A 等待信号量时,它处于阻塞状态。这是因为 Task_A 正在等待一个外部事件(在这种情况下是信号量的释放),这个事件将允许它继续执行。在阻塞状态下,任务不会消耗任何处理器时间,并且不能被选中进入运行状态,直到它所等待的事件发生。

在 FreeRTOS 中,任务可以因为以下几种原因进入阻塞状态:

等待时间到期,如调用 vTaskDelay()。
等待队列、信号量、事件组、通知或信号量事件。
因此,Task_A 在等待信号量时,会一直保持阻塞状态,直到信号量可用或者达到了它的超时时间。这样可以确保 CPU 资源可以被当前运行状态的任务或者其他就绪状态的任务使用。

释放完信号量Sem_Event任务Task_A不将会被执行吗,为什么还要用portYIELD_FROM_ISR,不用会怎么样?

解答:
当信号量 Sem_Event 被释放后,Task_A 会从阻塞状态变为就绪状态,这意味着它已经准备好被执行。但是,是否立即执行取决于当前运行任务的优先级和操作系统的调度策略。

使用 portYIELD_FROM_ISR 的原因是为了确保如果有更高优先级的任务变为就绪状态,那么在中断服务例程(ISR)完成后,操作系统可以立即进行上下文切换到该任务。这是特别重要的,在实时操作系统中,响应时间是关键。

如果不使用 portYIELD_FROM_ISR,则在 ISR 完成后,控制权将返回到中断之前正在执行的任务。如果该任务的优先级低于刚刚被唤醒的任务,那么系统可能不会立即切换到更高优先级的任务,而是会等到下一个调度点。这可能会导致不必要的延迟,特别是在需要快速响应的系统中。

简而言之,portYIELD_FROM_ISR 确保了任务切换的及时性,这对于维护系统的实时性能至关重要。如果不使用它,系统的响应时间可能会受到影响,尤其是在中断频繁发生的系统中。

有更高优先级的任务变为就绪状态,不就会打断低优先级的任务嘛?

解答:
在 FreeRTOS 中,当一个更高优先级的任务变为就绪状态时,确实会在下一个调度点打断当前运行的低优先级任务。这是因为 FreeRTOS 的调度器是基于优先级的抢占式调度器,它总是会选择最高优先级的就绪任务来执行。

然而,portYIELD_FROM_ISR 的使用是为了处理中断服务例程(ISR)中的特殊情况。在 ISR 中,即使有更高优先级的任务变为就绪状态,系统也不会立即进行上下文切换,因为中断处理具有最高的优先级,必须先完成。只有在 ISR 完成后,才会检查是否有更高优先级的任务就绪,并且如果有,才会进行上下文切换。

如果不使用 portYIELD_FROM_ISR,那么即使在 ISR 中释放了信号量并且有更高优先级的任务变为就绪状态,系统也会等到下一个调度点才会检查并执行上下文切换。这可能会导致不必要的延迟,特别是在对响应时间有严格要求的实时系统中。

因此,portYIELD_FROM_ISR 是一种优化机制,它允许在 ISR 完成时立即进行上下文切换,而不是等待下一个调度点,从而提高系统的响应性和实时性能。

  • 14
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值