FreeRTOS库函数 API Reference(二)任务控制

目录

任务控制(Task Control)

1.vTaskDelay(延迟相对时间)

2.vTaskDelayUntil(延迟绝对时间)

3.xTaskDelayUntil(延迟绝对时间)

4.uxTaskPriorityGet(获取任意任务的优先级)

5.vTaskPrioritySet(设置任何任务的优先级)

6.vTaskSuspend(暂停任何任务)

7.vTaskResume(恢复挂起的任务)

8.xTaskResumeFromISR(在中断服务函数中恢复一个任务)

9.xTaskAbortDelay(强制任务离开阻塞状态,进入就绪状态)


Links to the FreeRTOS task control API function vTaskDelay, vTaskDelayUntil, uxTaskPriorityGet, vTaskPrioritySet, vTaskSuspend, vTaskResume, xTaskResumeFromISR, vTaskSetApplicationTaskTag, xTaskCallApplicationTaskHookhttps://www.freertos.org/a00112.html

任务控制(Task Control)

1.vTaskDelay(延迟相对时间)

void vTaskDelay( const TickType_t xTicksToDelay );

INCLUDE_vTaskDelay必须定义为1,该函数才可用。

在给定的时间间隔内延迟任务。任务保持阻塞的实际时间取决于tick rate。恒定的portTICK_PERIOD_MS可用于从tick rate计算实时时间——分辨率为一个tick period。

vTaskDelay()指定任务希望解除阻塞的时间,相对于vTaskDelay()被调用的时间。例如,指定100个节拍的阻塞周期将导致任务在调用vTaskDelay()后解除100个节拍的阻塞。因此,vTaskDelay()并不是一个控制周期性任务频率的好方法,因为通过代码的路径以及其他任务和中断活动将影响调用vTaskDelay()的频率,从而影响任务下一次执行的时间。请参阅vTaskDelayUntil()获取用于促进固定频率执行的替代API函数。它通过指定调用任务应该解除阻塞的绝对时间(而不是相对时间)来实现这一点。

参数:

xTicksToDelay调用任务应该阻塞的时间,以滴答周期为单位。

使用示例:

void vTaskFunction( void * pvParameters )
 {
     /* Block for 500ms. */
     const TickType_t xDelay = 500 / portTICK_PERIOD_MS;

     for( ;; )
     {
         /* Simply toggle the LED every 500ms, blocking between each toggle. */
         vToggleLED();
         vTaskDelay( xDelay );
     }
}

2.vTaskDelayUntil(延迟绝对时间)

void vTaskDelayUntil( TickType_t *pxPreviousWakeTime,
                      const TickType_t xTimeIncrement );

INCLUDE_vTaskDelayUntil必须定义为1,该函数才可用。

延迟任务到指定时间。周期性任务可使用此功能,保证任务的执行频率恒定。

此函数与vTaskDelay()在一个重要的方面不同:vTaskDelay()指定任务希望解除阻塞的时间,相对于vTaskDelay()被调用的时间,而vTaskDelayUntil()指定任务希望解除阻塞的绝对时间。

vTaskDelay()将导致从调用vTaskDelay()开始的指定时间间隔内任务阻塞。因此,很难单独使用vTaskDelay()来生成固定的执行频率,因为任务在调用vTaskDelay()后解除阻塞,而下一次调用vTaskDelay()的任务之间的时间可能不固定[任务可能在调用之间采用不同的代码路径,或者每次执行时可能被中断或抢占不同的次数]。

vTaskDelay()指定相对于调用函数的时间的唤醒时间,vTaskDelayUntil()指定希望解除阻塞的绝对(确切)时间。

应该注意的是,如果vTaskDelayUntil()用于指定一个已经是过去的唤醒时间,它将立即返回(不阻塞)。因此,使用vTaskDelayUntil()定期执行的任务如果由于任何原因(例如,任务被临时放置到Suspended状态)而导致任务错过一次或多次定期执行,则必须重新计算它所需的唤醒时间。这可以通过检查作为pxPreviousWakeTime参数通过引用传递的变量来检测当前的tick计数。然而,在大多数使用场景下,这并不是必需的。

恒定的portTICK_PERIOD_MS可用于从tick rate计算实时时间——分辨率为一个tick period。

当调用vTaskSuspendAll()暂停RTOS调度器时,这个函数不能被调用。

参数:

pxPreviousWakeTime 指向一个变量的指针,该变量保存任务最后一次解除阻塞的时间。在第一次使用变量之前,必须用当前时间初始化变量(参见下面的示例)。接下来,变量将在vTaskDelayUntil()中自动更新。
xTimeIncrement 周期时间段。该任务将在时间点(*pxPreviousWakeTime + xTimeIncrement)被解除阻塞。使用相同的xTimeIncrement参数值调用vTaskDelayUntil将导致任务以固定的间隔周期执行。

使用示例:

 // 每10个节拍执行一个动作。
 void vTaskFunction( void * pvParameters )
 {
     TickType_t xLastWakeTime;
     const TickType_t xFrequency = 10;

     // 用当前时间初始化xLastWakeTime变量。
     xLastWakeTime = xTaskGetTickCount();

     for( ;; )
     {
         // 等待下一个周期。
         vTaskDelayUntil( &xLastWakeTime, xFrequency );

         // 执行动作。 
     }
 }

3.xTaskDelayUntil(延迟绝对时间)

BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime,
                            const TickType_t xTimeIncrement );

INCLUDE_xTaskDelayUntil必须定义为1,该函数才可用。

延迟任务到指定时间。周期性任务可使用此功能,保证任务的执行频率恒定。

此函数与vTaskDelay()在一个重要的方面不同:vTaskDelay()将导致任务从调用vTaskDelay()的时间开始阻塞指定的tick数,而xTaskDelayUntil()将导致任务从pxPreviousWakeTime参数中指定的时间开始阻塞指定的tick数。单独使用vTaskDelay()来生成固定的执行频率是很困难的,因为任务开始执行和任务调用vTaskDelay()之间的时间可能不是固定的[任务在调用之间可能采用不同的代码路径,或者每次执行时可能被中断或抢占不同的次数]。xTaskDelayUntil()可用于生成一个固定的执行频率。

vTaskDelay()指定了相对于函数调用时间的唤醒时间,而xTaskDelayUntil()指定了它希望解除阻塞的绝对(确切)时间。

宏pdMS_TO_TICKS()可用于计算以毫秒为单位指定的时间的滴答数,分辨率为一个滴答周期。

参数:

pxPreviousWakeTime 指向一个变量的指针,该变量保存任务最后一次解除阻塞的时间。在第一次使用变量之前,必须用当前时间初始化变量(参见下面的示例)。接下来,变量将在xTaskDelayUntil()中自动更新。
xTimeIncrement 周期时间段。该任务将在时间点(*pxPreviousWakeTime + xTimeIncrement)被解除阻塞。使用相同的xTimeIncrement参数值调用xTaskDelayUntil将导致任务以固定的间隔周期执行。

返回值:

一个值,可以用来检查任务是否真的被延迟了:如果是任务延迟了,pdTRUE,否则是pdFALSE。如果下一个预期唤醒时间已经过去,任务不会被延迟。

使用示例:

// 每10个节拍执行一个动作
void vTaskFunction( void * pvParameters )
{
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = 10;
    BaseType_t xWasDelayed;

    // 用当前时间初始化xLastWakeTime变量。
    xLastWakeTime = xTaskGetTickCount ();
    for( ;; )
    {
        // 等待下一个周期。
        xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency );

        // 执行动作。如果这里的代码花费的时间太长,xWasDelayed值可以用来确定是否错过了最后期限。
    }
}

4.uxTaskPriorityGet(获取任意任务的优先级)

UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );

INCLUDE_uxTaskPriorityGet必须定义为1,该函数才可用。

获取任意任务的优先级。

参数:

xTask 待查询任务的句柄。传递NULL句柄会导致返回调用任务的优先级。

返回值:

xTask的优先级。

使用示例:

void vAFunction( void )
 {
     TaskHandle_t xHandle;

     // 创建一个任务,存储该句柄。
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

     // ...

     // 使用句柄获取已创建任务的优先级。
     // 它是用tskIDLE_PRIORITY创建的,但是可能已经改变了它本身
     if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
     {
         // 任务已经改变了优先级。
     }

     // ...

     // vTaskCode的优先级比vAFunction优先级高吗?
     if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
     {
         // vAFunction的优先级(使用NULL句柄获得)更高。
     }
 }

5.vTaskPrioritySet(设置任何任务的优先级)

void vTaskPrioritySet( TaskHandle_t xTask,
                       UBaseType_t uxNewPriority );

INCLUDE_vTaskPrioritySet必须定义为1,该函数才可用。

设置任何任务的优先级。

如果设置的优先级高于当前正在执行的任务,则在函数返回之前将发生上下文切换。

参数:

xTask 正在设置优先级的任务的句柄。NULL句柄设置调用任务的优先级。
uxNewPriority 

任务将被设置的优先级。断言优先级小于configMAX_PRIORITIES。如果configASSERT未定义,则优先级被静默地限制为(configMAX_PRIORITIES - 1)。

使用示例:

void vAFunction( void )
 {
     TaskHandle_t xHandle;
     // 创建一个任务,存储该句柄。
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
     // ...
     // 使用句柄提升已创建任务的优先级。
     vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 )
     // ...
     // 使用NULL句柄将vAFunction优先级提高到相同的值。
     vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
 }

6.vTaskSuspend(暂停任何任务)

void vTaskSuspend( TaskHandle_t xTaskToSuspend );

INCLUDE_vTaskSuspend必须定义为1,该函数才可用。

暂停任何任务。当一个任务被挂起时,无论它的优先级是什么,它都不会得到任何微控制器的处理时间。

对vTaskSuspend的调用不是累计的——即在同一个任务上调用两次vTaskSuspend()仍然只需要调用一次vTaskResume()来准备被挂起的任务。

参数:

xTaskToSuspend 被挂起任务的句柄。传递NULL句柄会导致调用任务被挂起。

使用示例:

void vAFunction( void )
 {
     TaskHandle_t xHandle;

     // 创建一个任务,存储该句柄。
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

     // ...

     // 使用句柄暂停已创建的任务。
     vTaskSuspend( xHandle );

     // ...

     // 创建的任务在此期间不会运行,除非另一个任务调用vTaskResume(xHandle)。

     //...

     // 暂停vAFunction本身
     vTaskSuspend( NULL );

     // 除非另一个任务用vAFunction的句柄作为参数调用vTaskResume,否则我们无法到达这里。
 }

7.vTaskResume(恢复挂起的任务)

void vTaskResume( TaskHandle_t xTaskToResume );

INCLUDE_vTaskSuspend必须定义为1,该函数才可用。

恢复挂起的任务。

被一次或多次调用vTaskSuspend()挂起的任务将通过一次调用vTaskResume()重新运行。

参数:

xTaskToResume 已就绪的任务的句柄

使用示例:

 void vAFunction( void )
 {
     TaskHandle_t xHandle;

     // 创建一个任务,存储该句柄。
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

     // ...

     // 使用句柄暂停已创建的任务。
     vTaskSuspend( xHandle );

     // ...

     // 创建的任务在此期间不会运行,除非另一个任务调用vTaskResume(xHandle)。

     //...

     // 自己恢复挂起的任务。
     vTaskResume( xHandle );

     // 创建的任务将再次根据其在系统中的优先级获得微控制器处理时间。
 }

8.xTaskResumeFromISR(在中断服务函数中恢复一个任务

BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume );

INCLUDE_vTaskSuspend和INCLUDE_xTaskResumeFromISR必须定义为1,该函数才可用。

一个函数,用来恢复可以从ISR内部调用的挂起的任务。

一个被多个vTaskSuspend()调用挂起的任务将通过调用xTaskResumeFromISR()重新运行。

xTaskResumeFromISR()通常被认为是一个危险的函数,因为它的操作没有锁存。由于这个原因,如果中断有可能在任务挂起之前到达,从而丢失中断,那么肯定不应该使用它来同步任务和中断。使用信号量(最好是直接通知任务)可以避免这种情况的发生。使用示例提供了一个使用直接到任务通知的工作示例。

参数:

xTaskToResume 已就绪的任务句柄

返回值:

如果恢复任务会导致上下文切换,则为pdTRUE,否则为pdFALSE。这被ISR用来确定是否需要在ISR之后进行上下文切换。

使用示例:

TaskHandle_t xHandle;

 void vAFunction( void )
 {
     // 创建一个任务,存储该句柄。
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

     // ... 剩下的代码.
 }

 void vTaskCode( void *pvParameters )
 {
     for( ;; )
     {
         // ... 在这里执行一些函数

         // 任务挂起。
         vTaskSuspend( NULL );

         // 任务现在被暂停,所以直到ISR恢复它才会到达这里
     }
 }


 void vAnExampleISR( void )
 {
     BaseType_t xYieldRequired;

     // 恢复挂起的任务
     xYieldRequired = xTaskResumeFromISR( xHandle );

     // 我们应该切换上下文,使ISR返回到不同的任务。
     // 注意:这取决于您所使用的端口。查看您的端口的文档和示例。
     portYIELD_FROM_ISR( xYieldRequired );
 }

9.xTaskAbortDelay(强制任务离开阻塞状态,进入就绪状态)

BaseType_t xTaskAbortDelay( TaskHandle_t xTask );

强制任务离开阻塞状态,进入就绪状态,即使任务处于要等待的阻塞状态的事件没有发生,并且任何指定的超时还没有过期。

INCLUDE_xTaskAbortDelay必须定义为1,该函数才可用。

参数:

xTask  

将被强制退出阻塞状态的任务句柄。

返回值:

如果xTask引用的任务不在阻塞状态,则返回pdFAIL。否则返回pdPASS。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QxNL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值