7

我试图理解为什么用户必须调用该taskYIELD_FROM_ISR()方法以及为什么该方法中的 RTOS 不自动调用它xStreamBufferSendFromISR

我的问题是指FreeRTOS_Manual p。369.

/* A stream buffer that has already been created. */
StreamBufferHandle_t xStreamBuffer;

void vAnInterruptServiceRoutine( void ) {
  size_t xBytesSent;
  char *pcStringToSend = "String to send";
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;

  /* Attempt to send the string to the stream buffer. */
  xBytesSent = xStreamBufferSendFromISR(xStreamBuffer,(void *) pcStringToSend,strlen( pcStringToSend),&xHigherPriorityTaskWoken);

  if(xBytesSent != strlen(pcStringToSend)){
    /* There was not enough free space in the stream buffer for the entire string to be written, ut xBytesSent bytes were written. */
  }

  /* 
    If xHigherPriorityTaskWoken was set to pdTRUE inside xStreamBufferSendFromISR() then a    
    task that has a priority above the priority of the currently executing task was unblocked 
    and a context switch should be performed to ensure the ISR returns to the unblocked task. 
    In most FreeRTOS ports this is done by simply passing xHigherPriorityTaskWoken into 
    taskYIELD_FROM_ISR(), which will test the variables value, and perform the context switch 
    if necessary. Check the documentation for the port in use for port specific instructions. 
  */

  taskYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

我对场景的理解

前提条件

  • 有两个任务
    • Task1(高优先级)和 Task2(低优先级)
  • Task1 处于阻塞状态,等待 streamBuffer 输入
  • Task2 处于运行状态并从vAnInterruptServiceRoutine

在 ISR 内

  • ISR 方法调用xStreamBufferSendFromISR()
  • 这个调用意味着,Task1 的 Blocked-State 变为 Ready-State

案例 A 如果 ISR 方法现在正在返回,则不会调用调度程序,并且 Task2 会一直运行,直到时间片周期结束,然后调度程序会切换到高优先级 Task1。

案例 B 如果 ISR 方法taskYIELD_FROM_ISR(xHigherPriorityTaskWoken);最后调用,调度程序将被调用,返回 ISR 后,Task1 将运行而不是 Task2。

问题

  1. 是不是,Task2 将一直执行到一个时间片周期结束,或者任务切换是否还有另一个触发器?
  2. 为什么taskYIELD_FROM_ISR()调用时 RTOS 不自动调用该方法xStreamBufferSendFromISR()
4

2 回答 2

8
  1. 是的,如果不调用,调度程序会在下一个计划的滴答声中taskYIELD_FROM_ISR提供上下文。Task1这可以通过 Segger SystemView 进行验证。 uartPrintTask信号量上的块,然后从缓冲区打印数据。请注意 uartPrintTask “就绪”和“运行”之间的长时间延迟。这个延迟是可变的 - 尽管它永远不会持续超过 1mS(示例中的滴答速率) 在此处输入图像描述

现在,taskYIELD_FROM_ISR在 ISR 末尾添加了相同的示例。 uartPrintTask在 ISR 2 之后始终执行 在此处输入图像描述 。FreeRTOS 不能自动从 ISR 调用任何内容。您可以完全控制所有中断。 taskYIELD_FROM_ISR应放置在 ISR 实现的末尾(但您可能已将调用xStreamBufferSendFromISR放置在 ISR 中的任何位置)。

FreeRTOS 的一大优点(在我看来)是它不会劫持任何东西并提供大量的灵活性。您可以让中断完全在 RTOS“下方”执行——FreeRTOS 不需要知道任何关于它们的信息。不自动调用taskYIELD_FROM_ISR是这种灵活性的另一个例子(在我看来)。

SafeRTOS 手册

在中断服务例程中调用 xQueueSendFromISR() 或 xQueueReceiveFromISR() 可能会导致任务离开阻塞状态,如果未阻塞任务的优先级高于被中断任务,则需要进行上下文切换。当 xQueueSend() 或 xQueueReceive() 导致优先级高于调用任务的任务退出阻塞状态时,将透明地执行上下文切换(在 API 函数内)。这种行为是任务所需要的,但不是中断服务例程所需要的。因此,xQueueSendFromISR() 和 xQueueReceiveFromISR() 不是自己执行上下文切换,而是返回一个指示是否需要上下文切换的值。如果需要上下文切换,应用程序编写者可以使用 taskYIELD_FROM_ISR() 在最合适的时间执行上下文切换,通常在中断处理程序结束时。有关详细信息,请参阅第 69 页的“xQueueSendFromISR()”和第 71 页的“xQueueReceiveFromISR()”,它们分别描述了 xQueueSendFromISR() 和 xQueueReceiveFromISR() 函数。

于 2019-11-07T05:53:23.930 回答
0
  • 1)我认为是的
  • 2)我不太确定这一点。我认为这样做是为了保持快速中断并保持较低的上下文切换开销。因此,您可以选择是否触发上下文切换,具体取决于您需要的响应时间。
于 2019-10-31T09:40:05.477 回答