14-FreeRTOS任务控制

简介: 14-FreeRTOS任务控制

1-vTaskDelay


1.1 函数描述


这是相对延时

1//task.c/task.h
2void vTaskDelay( const TickType_t xTicksToDelay );

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

调用vTaskDelay()函数后,任务会进入阻塞状态,持续时间由vTaskDelay()函数的参数xTicksToDelay指定,单位是系统节拍时钟周期。常量portTICK_RATE_MS 用来辅助计算真实时间,此值是系统节拍时钟中断的周期,单位是毫秒。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelay 必须设置成1,此函数才能有效。

vTaskDelay()指定的延时时间是从调用vTaskDelay()后开始计算的相对时间。比如vTaskDelay(100),那么从调用vTaskDelay()后,任务进入阻塞状态,经过100个系统时钟节拍周期,任务解除阻塞。因此,vTaskDelay()并不适用与周期性执行任务的场合。此外,其它任务和中断活动,会影响到vTaskDelay()的调用(比如调用前高优先级任务抢占了当前任务),因此会影响任务下一次执行的时间。API函数vTaskDelayUntil()可用于固定频率的延时,它用来延时一个绝对时间。


1.2 参数描述

xTicksToDelay :调用任务应该阻塞的时间总数(以tick为单位)。

1.3 用例

1void vTaskFunction( void * pvParameters )
 2{
 3/* 阻塞(延时) 500ms. */
 4const TickType_t xDelay = 500 / portTICK_PERIOD_MS;
 5
 6for( ;; )
 7{
 8/* 只需每500毫秒切换一次LED,在每次切换之间阻塞。 */
 9vToggleLED();
10vTaskDelay( xDelay );
11}
12}

2-vTaskDelayUntil

绝对延时


2.1 函数描述

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

INCLUDE_vTaskDelayUntil 必须设置为1,才可使用。

把任务延迟到指定的时间节点。周期性任务可以使用此函数,以此确保任务恒定的执行频率。

与vTaskDelay()函数的不同之处在于:vTaskDelay()指定的延时时间是从调用vTaskDelay()之后(执行完该函数)开始算起的,但是vTaskDelayUntil()指定的延时时间是一个绝对时间。

从调用vTaskDelay(),任务就会进入阻塞状态(就是延时任务需要等待的时间),持续时间由vTaskDelay()函数的参数指定,单位是系统节拍时钟周期。因此vTaskDelay()并不适用于周期性执行任务的场合。因为调用vTaskDelay()到任务解除阻塞的时间不总是固定的并且该任务下一次调用vTaskDelay()函数的时间也不总是固定的(两次执行同一任务的时间间隔本身就不固定,中断或高优先级任务抢占也可能会改变每一次执行时间)。

vTaskDelay()指定一个从调用vTaskDelay()函数后开始计时,到任务解除阻塞为止的相对时间,而vTaskDelayUntil()指定一个绝对时间,每当时间到达,则解除任务阻塞。

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

常量portTICK_RATE_MS 用来辅助计算真实时间,此值是系统节拍时钟中断的周期,单位是毫秒。

当调用vTaskSuspendAll()函数挂起RTOS调度器时,不可以使用此函数。


2.1 参数描述

pxPreviousWakeTime:指针,指向一个变量,该变量保存任务最后一次解除阻塞的时间。第一次使用前,该变量必须初始化为当前时间。之后这个变量会在vTaskDelayUntil()函数内自动更新。
xTimeIncrement
周期时间。当时间等于(*pxPreviousWakeTime + xTimeIncrement)时,任务解除阻塞。如果不改变参数xTimeIncrement的值,调用该函数的任务会按照固定频率执行。


2.2 用法用例

1Example usage:
 2// 每十个节拍执行一次.
 3void vTaskFunction( void * pvParameters )
 4{
 5TickType_t xLastWakeTime;
 6const TickType_t xFrequency = 10;
 7
 8//使用当前时间初始化变量xLastWakeTime
 9xLastWakeTime = xTaskGetTickCount();
10
11for( ;; )
12{
13// 等待下一个周期
14vTaskDelayUntil( &xLastWakeTime, xFrequency );
15
16// 需要执行的周期任务函数
17}
18}


3- xTaskDelayUntil


3.1 函数描述

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

BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime,

const TickType_t xTimeIncrement );

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

这个函数和vTaskDelay()不同在于:vTaskDelay()被调用的时候阻塞指定的计时数,而xTaskDelayUntil()被调用的时候会在pxPreviousWakeTime参数中指定阻塞时间的计时数,说白了这种可以生成相对稳定的计数值。而vTaskDelay()想要一个固定的执行频率相对来说是比较困难的,因为任务的开始到结束的时间是不固定的。

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

宏pdMS_TO_TICKS()以毫秒为单位指定的时间的节拍数。


3.2 参数描述

pxPreviousWakeTime:指向一个变量的指针,该变量保存了任务上次解除阻塞的时间。变量必须在第一次使用之前用当前时间初始化(参见下面的示例)。接下来,变量会在xTaskDelayUntil()中自动更新。
xTimeIncrement :周期时间段。任务将在特定时间(*pxPreviousWakeTime + xTimeIncrement)被解除阻塞。使用相同的xTimeIncrement参数值调用xTaskDelayUntil将导致任务以固定的间隔周期执行。
Returns:可用于检查任务是否实际延迟的值:如果任务方式延迟,则pdTRUE,否则为pdFALSE。如果下一个预期唤醒时间已经过去,任务将不会被延迟。


3.3 Example usage:

1// 每10节拍执行一次操作
 2void vTaskFunction( void * pvParameters )
 3{
 4TickType_t xLastWakeTime;
 5const TickType_t xFrequency = 10;
 6BaseType_t xWasDelayed;
 7
 8// 用当前时间初始化xLastWakeTime变量.
 9xLastWakeTime = xTaskGetTickCount ();
10for( ;; )
11{
12//等待下一个周期。
13xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency );
14
15// 在此执行操作。xWasDelayed值可用于确定
16// 如果代码耗时过长,看看是否超时
17}
18}


4-uxTaskPriorityGet


4.1 函数描述

获取指定任务的优先级

UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );

INCLUDE_uxTaskPriorityGet必须设置为1才可使用。


4.2 参数描述

xTask:待查询任务的句柄。如果设置为NULL表示当前运行的任务,
返回:返回指定任务的优先级


4.3 用例

1voidvAFunction( void )
 2{
 3xTaskHandlexHandle;
 4// 创建任务,保存任务句柄
 5xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
 6// ...
 7// 使用句柄获取创建的任务的优先级
 8if( uxTaskPriorityGet( xHandle ) !=tskIDLE_PRIORITY )
 9{
10// 任务可以改变自己的优先级
11}
12// ...
13// 当前任务优先级比创建的任务优先级高?
14if( uxTaskPriorityGet( xHandle ) <uxTaskPriorityGet( NULL ) )
15{
16// 当前优先级较高
17}


5 vTaskPrioritySet


5.1 函数描述

void vTaskPrioritySet( TaskHandle_t xTask,

UBaseType_t uxNewPriority );

INCLUDE_vTaskPrioritySet必须设置1.

设置指定任务的优先级。如果设置的优先级高于当前运行的任务,在函数返回前会进行一次上下文切换。


5.2 参数描述

xTask:要设置优先级任务的句柄,为NULL表示设置当前运行的任务。
uxNewPriority:要设置的新优先级。
优先级必须为小于configMAX_PRIORITIES。如果configASSERT没有定义,优先级将静默地限制在(configMAX_PRIORITIES - 1)。


5.3 用例

1voidvAFunction( void )
 2{
 3xTaskHandlexHandle;
 4// 创建任务,保存任务句柄。
 5xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
 6// ...
 7// 使用句柄来提高创建任务的优先级
 8vTaskPrioritySet( xHandle,tskIDLE_PRIORITY + 1 );
 9// ...
10// 使用NULL参数来提高当前任务的优先级,设置成和创建的任务相同。
11vTaskPrioritySet( NULL, tskIDLE_PRIORITY +1 );
12}

6-vTaskSuspend


6.1 函数描述

void vTaskSuspend( TaskHandle_t xTaskToSuspend );

NCLUDE_vTaskSuspend必须设置1

指定任务挂起。挂起的任务不会得到 MCU的处理时间,不管优先级的级别是多高。

调用vTaskSuspend函数是不会累计的:即使多次调用vTaskSuspend ()函数将一个任务挂起,也只需调用一次vTaskResume ()函数就能使挂起的任务解除挂起状态。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必须设置成1,此函数才有效。


6.2 参数描述

xTaskToSuspend:要挂起的任务句柄。为NULL表示挂起当前任务。

6.3 用例

1void vAFunction( void )
 2{
 3TaskHandle_t xHandle;
 4
 5// Create a task, storing the handle.
 6xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
 7
 8// ...
 9
10// Use the handle to suspend the created task.
11vTaskSuspend( xHandle );
12
13// ...
14
15// The created task will not run during this period, unless
16// another task calls vTaskResume( xHandle ).
17
18//...
19
20// Suspend ourselves.
21vTaskSuspend( NULL );
22
23// We cannot get here unless another task calls vTaskResume
24// with our handle as the parameter.
25}


7 vTaskResume


7.1 函数描述

1void vTaskResume( TaskHandle_t xTaskToResume );

INCLUDE_vTaskSuspend 必须设置为1

恢复挂起的任务。

通过调用一次或多次vTaskSuspend()挂起的任务,可以调用一次vTaskResume ()函数来再次恢复运行。


7.2 参数描述

xTaskToResume : 要恢复运行的任务句柄。

7.3 用法用例

1void vAFunction( void )
 2{
 3TaskHandle_t xHandle;
 4
 5// Create a task, storing the handle.
 6xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
 7
 8// ...
 9
10// Use the handle to suspend the created task.
11vTaskSuspend( xHandle );
12
13// ...
14
15// The created task will not run during this period, unless
16// another task calls vTaskResume( xHandle ).
17
18//...
19
20// Resume the suspended task ourselves.
21vTaskResume( xHandle );
22
23// The created task will once again get microcontroller processing
24// time in accordance with its priority within the system.
25}


8- xTaskResumeFromISR

恢复挂起的任务,在中断服务函数中使用


8.1 函数描述

1BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume );

NCLUDE_vTaskSuspend 和INCLUDE_xTaskResumeFromISR必须设置为1

从ISR内部调用的恢复挂起任务的函数。

通过调用一次或多次vTaskSuspend()函数而挂起的任务,只需调用一次xTaskResumeFromISR()函数即可恢复运行。

xTaskResumeFromISR()不可用于任务和中断间的同步,如果中断恰巧在任务被挂起之前到达,这就会导致一次中断丢失(任务还没有挂起,调用xTaskResumeFromISR()函数是没有意义的,只能等下一次中断)。这种情况下,可以使用信号量作为同步机制。

8.2 参数描述

xTaskToResume :要恢复运行的任务句柄
Returns:如果恢复任务将需要上下文切换,则为pdTRUE,否则为pdFALSE。ISR使用它来确定在ISR之后是否需要上下文切换。

8.3 用例

1TaskHandle_t xHandle;
 2
 3void vAFunction( void )
 4{
 5// Create a task, storing the handle.
 6xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
 7
 8// ... Rest of code.
 9}
10
11void vTaskCode( void *pvParameters )
12{
13// The task being suspended and resumed.
14for( ;; )
15{
16// ... Perform some function here.
17
18// The task suspends itself.
19vTaskSuspend( NULL );
20
21// The task is now suspended, so will not reach here until the ISR resumes it.
22}
23}
24
25
26void vAnExampleISR( void )
27{
28BaseType_t xYieldRequired;
29
30// Resume the suspended task.
31xYieldRequired = xTaskResumeFromISR( xHandle );
32
33// We should switch context so the ISR returns to a different task.
34// NOTE: How this is done depends on the port you are using. Check
35// the documentation and examples for your port.
36portYIELD_FROM_ISR( xYieldRequired );
37}

9-xTaskAbortDelay9.1函数描述

1BaseType_t xTaskAbortDelay( TaskHandle_t xTask );

强制任务退出阻塞状态,使任务进入就绪状态。即使任务在阻塞状态下等待的事件还没有发生,并且阻塞时间还没有到达。

INCLUDE_xTaskAbortDelay 必须设置为1

9.2 参数描述

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

要获得任务的句柄,使用xTaskCreate()创建任务并使用pxCreatedTask参数,或使用xTaskCreateStatic()创建任务并存储返回值,或在调用xTaskGetHandle()时使用任务的名称。

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


相关文章
|
6月前
【FreeRTOS】中断管理(二)
【FreeRTOS】中断管理
126 0
|
6月前
【FreeRTOS】中断管理(三)
【FreeRTOS】中断管理
|
6月前
|
API 调度
【FreeRTOS】软件定时器的使用
【FreeRTOS】软件定时器的使用
176 0
|
IDE 调度 开发工具
如何在S32DS中使用SystemView分析FreeRTOS
如何在S32DS中使用SystemView分析FreeRTOS
如何在S32DS中使用SystemView分析FreeRTOS
|
6月前
|
API C语言
【FreeRTOS】中断管理(一)
【FreeRTOS】中断管理
121 0
|
6月前
|
API
FreeRTOS软件定时器的原理以及使用实例
FreeRTOS软件定时器的原理以及使用实例
147 0
|
6月前
|
API 调度
FreeRTOS深入教程(中断管理)
FreeRTOS深入教程(中断管理)
313 0
|
芯片
STM32窗口看门狗和独立看门狗的区别,看门狗介绍及代码演示
STM32窗口看门狗和独立看门狗的区别,看门狗介绍及代码演示
214 0
|
API 调度
18-FreeRTOS内核控制
18-FreeRTOS内核控制