FreeRTOS库函数 API Reference(五)任务实用程序

目录

任务实用程序Task Utilities

1.uxTaskGetSystemState() 获取系统中任务状态。

2.vTaskGetInfo() 获取某个任务信息

3.xTaskGetCurrentTaskHandle() 获取当前正在运行的任务的任务句柄

4.xTaskGetIdleTaskHandle() 获取空闲任务的任务句柄。

5.uxTaskGetStackHighWaterMark() 获取任务的堆栈的历史剩余最小值,FreeRTOS 中叫做“高水位线”

6.eTaskGetState() 获取某个任务的状态 这个状态是 eTaskState 类型

7.pcTaskGetName() 获取某个任务的任务名字

8.xTaskGetHandle() 根据任务名字查找某个任务的句柄

9.xTaskGetTickCount()  获取系统时间计数器值

10.xTaskGetTickCountFromISR() 在中断服务函数中获取时间计数器值

11.xTaskGetSchedulerState() 获取任务调度器的壮态,开启或未开启

12.uxTaskGetNumberOfTasks()  获取当前系统中存在的任务数量

13.vTaskList() 以一种表格的形式输出当前系统中所有任务的详细信息

14.vTaskStartTrace() 启动RTOS内核活动跟踪

15.ulTaskEndTrace()  停止RTOS内核活动跟踪

16.vTaskGetRunTimeStats() 获取每个任务的运行时间

17.vTaskGetIdleRunTimeCounter() 返回Idle任务的运行时计数器

18.vTaskSetApplicationTaskTag() 设置任务标签(Tag)值

19.xTaskGetApplicationTaskTag() xTaskGetApplicationTaskTagFromISR()获取某个任务的标签(Tag)值

20.xTaskCallApplicationTaskHook() 使用标签将钩子(或回调)函数分配给任务

21.pvTaskGetThreadLocalStoragePointer() 获取线程本地存储指针

22.vTaskSetThreadLocalStoragePointer() 

23.vTaskSetTimeOutState() 超时结构体变量 xTimeOut 的初始化

24.xTaskCheckForTimeOut()


RTOS task (thread) utilities including API functions for tracing FreeRTOS, getting the RTOS tick count, getting a task handle, getting the RTOS kernel or RTOS scheduler state, listing the tasks in the embedded system, and obtaining run time task statistics.https://www.freertos.org/a00021.html

任务实用程序Task Utilities

1.uxTaskGetSystemState() 获取系统中任务状态。

UBaseType_t uxTaskGetSystemState(
                       TaskStatus_t * const pxTaskStatusArray,
                       const UBaseType_t uxArraySize,
                       unsigned long * const pulTotalRunTime );

configUSE_TRACE_FACILITY必须在自由贸易协定.h中定义为 1,才能使 uxTaskGetSystemState() 可用。

uxTaskGetSystemState() 为系统中的每个任务填充一个TaskStatus_t结构。TaskStatus_t结构包含任务句柄的成员、任务名称、任务优先级、任务状态以及任务消耗的运行时间总量等。

请参阅 vTaskGetInfo() 以获取为单个任务(而不是每个任务)填充TaskStatus_t结构的版本。

注意:此函数仅用于调试使用,因为其使用会导致调度程序长时间保持挂起状态。

参数:

pxTaskStatusArray  指向TaskStatus_t结构体数组的指针。对于RTOS控制下的每个任务,数组必须至少包含一个TaskStatus_t结构体。RTOS控制下的任务数量可以通过使用uxTaskGetNumberOfTasks() API函数来确定。
uxArraySize  pxTaskStatusArray参数指向的数组的大小。大小指定为数组中的索引数(数组中包含的TaskStatus_t结构的数量),而不是数组中的字节数。
pulTotalRunTime  如果在FreeRTOSConfig.h中将configGENERATE_RUN_TIME_STATS设置为1,那么uxTaskGetSystemState()将*pulTotalRunTime设置为自目标启动以来的总运行时间(由运行时统计时钟定义)。可以将pulTotalRunTime设置为NULL,以省略总的运行时值。

返回值:

由uxTaskGetSystemState()填充的TaskStatus_t结构的数量。这应该等于uxTaskGetNumberOfTasks() API函数返回的数字,但如果传递给uxArraySize参数的值太小,则将为零。

使用示例:

/* 这个例子演示了如何从uxTaskGetSystemState()提供的原始数据生成
   一个人类可读的运行时统计信息表。人类可读的表被写入pcWriteBuffer。
   (请参阅vTaskList() API函数,它实际上就是这样做的)。 */
void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
{
    TaskStatus_t *pxTaskStatusArray;
    volatile UBaseType_t uxArraySize, x;
    unsigned long ulTotalRunTime, ulStatsAsPercentage;

   /* 确保写缓冲区不包含字符串。 */
   *pcWriteBuffer = 0x00;

   /* 获取任务数量的快照,以防在此函数执行时发生更改。 */
   uxArraySize = uxTaskGetNumberOfTasks();

   /* 为每个任务分配一个TaskStatus_t结构体。可以在编译时静态分配数组。 */
   pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );

   if( pxTaskStatusArray != NULL )
   {
      /* 生成每个任务的原始状态信息。 */
      uxArraySize = uxTaskGetSystemState( pxTaskStatusArray,
                                 uxArraySize,
                                 &ulTotalRunTime );

      /* 百分比计算。 */
      ulTotalRunTime /= 100UL;

      /* 避免除零误差。 */
      if( ulTotalRunTime > 0 )
      {
         /* 对于pxTaskStatusArray数组中每个填充的位置,
            将原始数据格式化为人类可读的ASCII数据。 */
         for( x = 0; x < uxArraySize; x++ )
         {
            /* 任务使用的运行时间占总运行时间的百分比是多少?
               这将始终四舍五入到最接近的整数。
               ulTotalRunTimeDiv100已经被100除。 */
            ulStatsAsPercentage =
                  pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;

            if( ulStatsAsPercentage > 0UL )
            {
               sprintf( pcWriteBuffer, "%stt%lutt%lu%%rn",
                                 pxTaskStatusArray[ x ].pcTaskName,
                                 pxTaskStatusArray[ x ].ulRunTimeCounter,
                                 ulStatsAsPercentage );
            }
            else
            {
               /* 如果这里的百分比为零,则该任务消耗的时间少于总运行时间的1%。 */
               sprintf( pcWriteBuffer, "%stt%lutt<1%%rn",
                                 pxTaskStatusArray[ x ].pcTaskName,
                                 pxTaskStatusArray[ x ].ulRunTimeCounter );
            }

            pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
         }
      }

      /* 不再需要数组,释放它消耗的内存。 */
      vPortFree( pxTaskStatusArray );
   }
}

 The TaskStatus_t definition

typedef struct xTASK_STATUS
{
   /* 结构中其他信息与之相关的任务句柄。 */
   TaskHandle_t xHandle;

   /* 指向任务名称的指针。任务名字。
      这个值将是无效的,如果任务被删除,因为结构被填充! */
   const signed char *pcTaskName;

   /* 任务编号 */
   UBaseType_t xTaskNumber;

   /* 填充结构时任务存在的状态。 */
   eTaskState eCurrentState;

   /* 填充结构时,任务运行的优先级(可以继承)。 */
   UBaseType_t uxCurrentPriority;

   /* 任务基础优先级。如果任务的当前优先级已经被继承,任务将返回的优先级,
      以避免在获取互斥锁时发生无界优先级反转。
      只有在FreeRTOSConfig.h中将configUSE_MUTEXES定义为1时才有效。 */
   UBaseType_t uxBasePriority;

   /* 到目前为止分配给任务的总运行时间,由运行时统计时钟定义。
      只有在FreeRTOSConfig.h中将configGENERATE_RUN_TIME_STATS定义为1时才有效。 */
   unsigned long ulRunTimeCounter;

   /* 指向任务堆栈区域的基地址。 */
   StackType_t *pxStackBase;

   /* 自创建任务以来为任务保留的最小堆栈空间。
      这个值越接近零,任务越接近溢出堆栈。 */
   configSTACK_DEPTH_TYPE usStackHighWaterMark;
} TaskStatus_t;

2.vTaskGetInfo() 获取某个任务信息

void vTaskGetInfo( TaskHandle_t xTask,
                   TaskStatus_t *pxTaskStatus,
                   BaseType_t xGetFreeStackSpace,
                   eTaskState eState );

configUSE_TRACE_FACILITY必须在FreeRTOSConfig.h中定义为1,以便vTaskGetInfo()可用。

uxTaskGetSystemState()为系统中的每个任务填充TaskStatus_t结构体,而vTaskGetInfo()仅为单个任务填充TaskStatus_t结构体。TaskStatus_t结构包含任务句柄的成员、任务名称、任务优先级、任务状态和任务所消耗的运行时间总量。

注意:此函数只用于调试,因为它的使用导致调度器在一段较长时间内保持挂起状态。

参数:

xTask  正在查询的任务的句柄。将xTask设置为NULL将返回调用任务的信息。
pxTaskStatus  由pxTaskStatus指向的TaskStatus_t结构将被xTask参数中传递的句柄所引用的任务信息填充。
xGetFreeStackSpace TaskStatus_t结构包含一个成员,用于报告正在查询的任务的堆栈高水位标记。堆栈高水位标志是有史以来存在的堆栈空间的最小值,因此该数字越接近零,任务越接近溢出其堆栈。计算堆栈高水位需要相当长的时间,并且会使系统暂时无响应—因此提供xGetFreeStackSpace参数来允许跳过高水位检查。如果xGetFreeStackSpace没有设置为pdFALSE,高水位值只会写入TaskStatus_t结构。
eState  TaskStatus_t结构包含一个成员来报告正在查询的任务的状态。获取任务状态的速度不如简单的赋值那么快——因此提供了eState参数,以允许从TaskStatus_t结构中省略状态信息。要获得状态信息,然后将eState设置为eInvalid -否则在eState中传递的值将作为任务状态在TaskStatus_t结构中报告

使用示例:

void vAFunction( void )
{
    TaskHandle_t xHandle;
    TaskStatus_t xTaskDetails;

    /* 从任务名称获取任务句柄。 */
    xHandle = xTaskGetHandle( "Task_Name" );

    /* 检查句柄是否为空。 */
    configASSERT( xHandle );

    /* 使用句柄可获取关于任务的进一步信息。 */
    vTaskGetInfo( /* 正在查询的任务的句柄。 */
                  xHandle,
                  /* TaskStatus_t结构用来完成关于xTask的信息。 */
                  &xTaskDetails,
                  /* 在TaskStatus_t结构中包含堆栈高水位标志值。 */
                  pdTRUE,
                  /* 在TaskStatus_t结构中包含任务状态。 */
                  eInvalid );
}

3.xTaskGetCurrentTaskHandle() 获取当前正在运行的任务的任务句柄

TaskHandle_t xTaskGetCurrentTaskHandle( void );

INCLUDE_xTaskGetCurrentTaskHandle必须设置为1,该函数才可用。

返回值:当前正在运行(调用)的任务句柄。

4.xTaskGetIdleTaskHandle() 获取空闲任务的任务句柄。

TaskHandle_t xTaskGetIdleTaskHandle( void );

INCLUDE_xTaskGetIdleTaskHandle必须设置为1,该函数才可用。

返回值:与空闲任务相关联的任务句柄。Idle任务在RTOS调度器启动时自动创建。

5.uxTaskGetStackHighWaterMark() 获取任务的堆栈的历史剩余最小值,FreeRTOS 中叫做“高水位线”

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );

INCLUDE_uxTaskGetStackHighWaterMark必须定义为1,以便uxTaskGetStackHighWaterMark函数可用;

任务使用的堆栈会随着任务的执行和中断的处理而增大或缩小。uxTaskGetStackHighWaterMark()返回自任务开始执行以来可用于任务的最小剩余堆栈空间——即当任务堆栈处于最大(最深)值时,剩余未使用的堆栈空间。这就是所谓的堆栈“高水位标记”。

参数:

xTask 正在查询的任务的句柄。通过传递NULL作为xTask参数,任务可以查询自己的高水位标记。

返回值:

返回的值是以字为单位的高水位标记(例如,在32位机器上,返回值为1表示有4个字节的堆栈未使用)。如果返回值是零,那么任务可能已经溢出了它的堆栈。如果返回值接近于零,那么任务已经接近溢出堆栈。

使用示例:

void vTask1( void * pvParameters )
{
    UBaseType_t uxHighWaterMark;

    /* 在进入任务时检查我们自己的高水位。 */
    uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );

    for( ;; )
    {
        /* 调用任何函数。 */
        vTaskDelay( 1000 );

        /* 调用该函数将使用一些堆栈空间,因此我们现在期望
           uxTaskGetStackHighWaterMark()返回的值比进入任务时被调用时的值要低。 */
        uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
    }
}

6.eTaskGetState() 获取某个任务的状态 这个状态是 eTaskState 类型

eTaskState eTaskGetState( TaskHandle_t xTask );

以枚举类型返回在执行eTaskGetState()时任务存在的状态。

INCLUDE_eTaskGetState必须在FreeRTOSConfig.h中设置为1,以便eTaskGetState()可用。

参见2.vTaskGetInfo()。

参数:

xTask 
要查询的任务的任务句柄

返回值:

下表列出了对于xTask参数所引用的任务可能存在的每个可能状态,eTaskGetState()将返回的值。

任务状态返回值
就绪态eReady
运行态eRunning 
阻塞态eBlocked
挂起态eSuspended
任务被删除eDeleted 
typedef enum
{
    eRunning = 0,   //运行状态
    eReady,         //就绪态
    eBlocked,       //阻塞态
    eSuspended,     //挂起态
    eDeleted,       //任务被删除
    eInvalid        //无效
} eTaskState;

7.pcTaskGetName() 获取某个任务的任务名字

char * pcTaskGetName( TaskHandle_t xTaskToQuery );

从任务的句柄中查找任务的名称。

参数:

xTaskToQuery 要查询的任务的句柄。xTaskToQuery可以设置为NULL来查询调用任务的名称。

返回值:

指向主题任务名称的指针,它是一个标准的以NULL结尾的C字符串。

8.xTaskGetHandle() 根据任务名字查找某个任务的句柄

TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );

根据任务名称查找任务的句柄。

注意:这个函数需要相对较长的时间来完成,并且应该对每个任务只调用一次。一旦获得了任务的句柄,就可以将其存储在本地以供重用。

INCLUDE_xTaskGetHandle必须在FreeRTOSConfig.h中设置为1才能使xTaskGetHandle()可用。

参数:

pcNameToQuery  

任务的文本名称(作为标准的C NULL终止字符串)。

查看xTaskCreate()和xTaskCreateStatic() API函数的pcName参数来获取关于设置任务文本名称的信息。

返回值:

如果一个任务在pcNameToQuery中传递了该名称,那么将返回该任务的句柄,否则返回NULL。

9.xTaskGetTickCount()  获取系统时间计数器值

volatile TickType_t xTaskGetTickCount( void );

这个函数不能从ISR中调用。ISR使用xTaskGetTickCountFromISR()。

返回值:自调用vTaskStartScheduler以来的计时次数。

10.xTaskGetTickCountFromISR() 在中断服务函数中获取时间计数器值

volatile TickType_t xTaskGetTickCountFromISR( void );

xTaskGetTickCount()的一个版本,可以从ISR中调用。

返回值:自调用vTaskStartScheduler以来的计时次数。

11.xTaskGetSchedulerState() 获取任务调度器的壮态,开启或未开启

BaseType_t xTaskGetSchedulerState( void );

INCLUDE_xTaskGetSchedulerState或configUSE_TIMERS必须在FreeRTOSConfig.h中设置为1,该函数才可用。

返回值:

taskSCHEDULER_NOT_STARTED调度器未启动
taskSCHEDULER_RUNNING调度器正在运行
taskSCHEDULER_SUSPENDED调度器挂起

12.uxTaskGetNumberOfTasks()  获取当前系统中存在的任务数量

UBaseType_t uxTaskGetNumberOfTasks( void );

返回值:RTOS内核当前管理的任务数量。这包括所有就绪、阻塞和挂起的任务。已被删除但尚未被空闲任务释放的任务也将包含在计数中。

13.vTaskList() 以一种表格的形式输出当前系统中所有任务的详细信息

void vTaskList( char *pcWriteBuffer );

configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS必须在FreeRTOSConfig.h中定义为1才能使用该函数。

注意:此功能将在其持续时间内禁用中断。它不用于正常的应用程序运行时使用,而是作为调试辅助。

vTaskList()调用uxTaskGetSystemState(),然后将uxTaskGetSystemState()生成的原始数据格式化为一个人类可读的(ASCII)表,该表显示每个任务的状态,包括任务的堆栈高水位标记(高水位标记越小,任务越接近溢出其堆栈)。

在ASCII表中,下列字母表示任务的状态:

“B” —— 阻塞

“R” —— 就绪

'D'  —— 删除(等待清理)

'S'  —— 挂起,或阻塞没超时

vTaskList()是一个实用函数,只是为了方便而提供。它不被认为是内核的一部分。请参阅vTaskGetRunTimeStats()获取一个实用函数,该函数生成运行时任务利用率信息的类似表。

参数:

pcWriteBuffer  以ASCII格式将上述细节写入其中的缓冲区。假定这个缓冲区足够大,可以包含生成的报告。每个任务大约40字节就足够了。

14.vTaskStartTrace() 启动RTOS内核活动跟踪

void vTaskStartTrace( char * pcBuffer, unsigned long ulBufferSize );

[该函数与旧的跟踪实用程序有关——在FreeRTOS V7.1.0中被删除了——用户可能会发现新的跟踪钩子宏更容易使用,更强大。]

启动RTOS内核活动跟踪。跟踪记录哪个任务在何时运行的标识。

跟踪文件以二进制格式存储。一个单独的DOS实用程序称为convtrce.exe是用来将其转换为一个标签分隔的文本文件,可以在电子表格中查看和绘制。

参数:

pcBuffer 跟踪将写入其中的缓冲区。
ulBufferSize pcBuffer的大小,以字节为单位。跟踪将继续,直到缓冲区被填满,或者调用ulTaskEndTrace()。

15.ulTaskEndTrace()  停止RTOS内核活动跟踪

[该函数与旧的跟踪实用程序有关——在FreeRTOS V7.1.0中被删除了——用户可能会发现新的跟踪钩子宏更容易使用,更强大。]

停止RTOS内核活动跟踪。看vTaskStartTrace()。

参数:已写入跟踪缓冲区的字节数。

16.vTaskGetRunTimeStats() 获取每个任务的运行时间

void vTaskGetRunTimeStats( char *pcWriteBuffer );

有关此特性的完整描述,请参阅运行时统计页面。 Run Time Stats 

configGENERATE_RUN_TIME_STATS、configUSE_STATS_FORMATTING_FUNCTIONS和configSUPPORT_DYNAMIC_ALLOCATION都必须定义为1才能使用此函数。然后,应用程序还必须提供portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()和portGET_RUN_TIME_COUNTER_VALUE的定义,以配置外围计时器/计数器并分别返回计时器的当前计数值。计数器应至少是滴答计数的10倍。

注意:此功能将在其持续时间内禁用中断。它不用于正常的应用程序运行时使用,而是作为调试辅助。

vTaskGetRunTimeStats()调用uxTaskGetSystemState(),然后将uxTaskGetSystemState()生成的原始数据格式化为一个人类可读的(ASCII)表,该表显示每个任务在运行状态下花费的时间(每个任务消耗了多少CPU时间)。数据以绝对值和百分比值的形式提供。绝对值的分辨率取决于应用程序提供的运行时stats时钟的频率。

vTaskGetRunTimeStats()是为了方便而提供的实用函数。它不被认为是内核的一部分。请参阅vTaskList()获取生成每个任务状态信息的实用函数。

参数:

pcWriteBuffer 

以ASCII格式将执行时间写入其中的缓冲区。

假定这个缓冲区足够大,可以包含生成的报告。每个任务大约40字节就足够了。

17.vTaskGetIdleRunTimeCounter() 返回Idle任务的运行时计数器

TickType_t xTaskGetIdleRunTimeCounter( void );

返回Idle任务的运行时计数器。这个函数可以用来确定空闲任务接收多少CPU时间。有关运行时统计特性的完整描述,请参阅运行时统计页面。Run Time Stats

configGENERATE_RUN_TIME_STATS和INCLUDE_xTaskGetIdleTaskHandle必须都定义为1,该函数才可用。然后,应用程序还必须提供portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()和portGET_RUN_TIME_COUNTER_VALUE的定义,以配置外围计时器/计数器并分别返回计时器的当前计数值。建议使计时器的频率至少为滴答计数的10倍。

18.vTaskSetApplicationTaskTag() 设置任务标签(Tag)

void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
                                 TaskHookFunction_t pxTagValue );

configUSE_APPLICATION_TASK_TAG必须定义为1,该函数才可用。更多信息请参见RTOS Configuration文档。

可以给每个任务分配一个“tag”值。这个值仅供应用程序使用- RTOS内核本身不会以任何方式使用它。RTOS跟踪宏文档页面提供了一个很好的例子,说明应用程序如何利用这个特性。RTOS trace macros

参数:

xTask 正在为其分配标记值的任务的句柄。将xTask传递为NULL会导致将标签分配给调用任务。
pxTagValue 分配给任务标记的值。这是TaskHookFunction_t类型,允许分配函数指针作为标签,尽管实际上可以分配任何值。请参阅下面的示例。

使用示例:

/* 在本例中,一个整数被设置为任务标记值。
   请参阅RTOS跟踪钩子宏文档页面,
   以获得如何使用这种赋值的示例。 */
void vATask( void *pvParameters )
{
  /* 将标记值1赋给我自己。 */
  vTaskSetApplicationTaskTag( NULL, ( void * ) 1 );

  for( ;; )
  {
    /* 任务代码 */
  }
}
/***********************************************/

/* 在这个例子中,一个回调函数被分配为任务标记。
   首先定义回调函数——根据本例,它必须具有TaskHookFunction_t类型。 */
static BaseType_t prvExampleTaskHook( void * pvParameter )
{
  /* 执行一些操作——可以是记录一个值、更新任务状态、输出一个值等等。 */

  return 0;
}

/* 现在定义将prvExampleTaskHook设置为其钩子/标签值的任务。
   这实际上是在注册任务回调,如xTaskCallApplicationTaskHook()文档页面所述。 */
void vAnotherTask( void *pvParameters )
{
  /* 注册回调函数。 */
  vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );

  for( ;; )
  {
    /* 任务代码 */
  }
}

/* 作为一个使用钩子(回调)的例子,我们可以让RTOS内核调用每个在重新调度期间
   被切换出去的任务的钩子函数。 */
#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook( pxCurrentTCB, 0 )

19.xTaskGetApplicationTaskTag() xTaskGetApplicationTaskTagFromISR()获取某个任务的标签(Tag)

TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask );
TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask );

configUSE_APPLICATION_TASK_TAG必须定义为1才能使用这些函数。更多信息请参见RTOS Configuration文档。

xTaskGetApplicationTaskTagFromISR()是xTaskGetApplicationTaskTag()的一个版本,可以从中断服务例程(ISR)中调用。

返回与任务关联的'tag'值。标记值的含义和用法由应用程序编写人员定义。RTOS内核本身通常不会访问标记值。

本功能仅适用于高级用户。

参数:

xTask 正在查询的任务的句柄。任务可以通过使用NULL作为参数值来查询自己的标记值。

返回值:正在查询的任务的'tag'值。

使用示例:

/* In this example, an integer is set as the task tag value. */
void vATask( void *pvParameters )
{
    /* Assign a tag value of 1 to the currently executing task.
    The (void *) cast is used to prevent compiler warnings. */
    vTaskSetApplicationTaskTag( NULL, ( void * ) 1 );

    for( ;; )
    {
        /* Rest of task code goes here. */
    }
}

void vAFunction( void )
{
    TaskHandle_t xHandle;
    int iReturnedTaskHandle;

   /* 通过vATask()函数创建一个任务,将创建任务的句柄存储在xTask变量中。 */

   /* 创建任务。 */
   if( xTaskCreate(
             vATask,         /* 指向实现该任务的函数的指针。 */
             "Demo task",    /* 赋予任务的文本名称。 */
             STACK_SIZE,     /* 应该为任务创建的堆栈的大小。这是用字定义的,而不是字节。 */
             NULL,           /* 任务不使用参数。 */
             TASK_PRIORITY,  /* 分配给新创建任务的优先级。 */
             &xHandle        /* 正在创建的任务的句柄将放置在xHandle中。 */
             ) == pdPASS )
   {
       /* 任务创建成功。延迟一小段时间以允许任务运行。 */
       vTaskDelay( 100 );

       /* 分配给任务的标记值是什么?
          返回的标记值存储在一个整数中,因此转换为一个整数以防止编译器发出警告。 */
       iReturnedTaskHandle = ( int ) xTaskGetApplicationTaskTag( xHandle );
   }
}

20.xTaskCallApplicationTaskHook() 使用标签将钩子(或回调)函数分配给任务

BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
                                         void *pvParameter );

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

可以给每个任务分配一个“tag”值。通常这个值只供应用程序使用,RTOS内核不访问它。但是,也可以使用标签将钩子(或回调)函数分配给任务——通过调用xTaskCallApplicationTaskHook()来执行该钩子函数。每个任务都可以定义自己的回调,或者根本不定义回调。

虽然可以使用函数的第一个参数来调用任何任务的钩子函数,但任务钩子函数最常见的用法是使用跟踪钩子宏,如下面的例子所示。

任务钩子函数必须具有TaskHookFunction_t类型,即接受一个void *形参,并返回一个BaseType_t类型的值。void *形参可用于向钩子函数传递任何信息。

参数:

xTask 被调用其钩子函数的任务句柄。传递NULL作为xTask将调用与当前执行任务相关的钩子函数。
pvParameter 传递给钩子函数的值。它可以是指向结构体的指针,也可以是简单的数值。

使用示例:

/* 在这个例子中,一个回调函数被分配为任务标记。
   首先定义回调函数——根据本例,它必须具有TaskHookFunction_t类型。 */
static BaseType_t prvExampleTaskHook( void * pvParameter )
{
   /* 执行一些操作——可以是记录一个值、更新任务状态、输出一个值等等。 */

   return 0;
}

/* 现在定义将prvExampleTaskHook设置为其钩子/标签值的任务。
   这实际上是在注册任务回调,如xTaskCallApplicationTaskHook()文档页面所述。 */
void vAnotherTask( void *pvParameters )
{
   /* 注册回调函数。 */
   vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );

   for( ;; )
   {
      /* 任务代码 */
   }
}

/* 作为一个使用钩子(回调)的例子,我们可以让RTOS内核调用每个
   在重新调度期间被切换出去的任务的钩子函数。 */
#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook( pxCurrentTCB, 0 )

21.pvTaskGetThreadLocalStoragePointer() 获取线程本地存储指针

void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
                                          BaseType_t xIndex );

从任务的线程本地存储阵列检索值。

本功能仅适用于高级用户。

参数:

xTaskToQuery 从其中读取线程本地数据的任务的句柄。通过使用NULL作为参数值,任务可以读取自己的线程本地数据。
xIndex 

正在从其中读取数据的线程本地存储阵列的索引。

可用数组索引的数量由FreeRTOSConfig.h中的confignum_thread_local_storage_pointer编译时配置常量来设置。

返回值:存储在任务xTaskToQuery的线程本地存储阵列的索引位置xIndex中的值。

使用示例:请参阅线程本地存储阵列文档页面上提供的示例。

22.vTaskSetThreadLocalStoragePointer() 

void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, 
                                        BaseType_t xIndex, 
                                        void *pvValue )

在任务的线程本地存储阵列中设置一个值。

此功能仅适用于高级用户。

参数:

xTaskToSet 正在向其写入线程本地数据的任务的句柄。通过使用NULL作为参数值,任务可以向自己的线程写入本地数据。
xIndex 

正在向其写入数据的线程本地存储阵列的索引。

可用数组索引的数量由FreeRTOSConfig.h中的confignum_thread_local_storage_pointer编译时配置常量来设置。

pvValue 要写入由xIndex参数指定的索引中的值。

使用示例:请参阅线程本地存储阵列文档页面上提供的示例。

23.vTaskSetTimeOutState() 超时结构体变量 xTimeOut 的初始化

void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut );

本功能仅适用于高级用户。

任务可以进入阻塞状态等待事件发生。通常,任务不会无限期地处于Blocked状态,而是指定一个超时时间。如果在任务等待的事件发生之前超时,任务将从阻塞状态移除。

如果一个任务在等待事件发生的过程中多次进入和退出阻塞状态,则必须调整每次进入阻塞状态的超时时间,以确保所有处于阻塞状态的时间总和不超过原来指定的超时时间。xTaskCheckForTimeOut()执行调整,考虑到偶尔发生的滴答计数溢出,否则手动调整容易出错。

vTaskSetTimeOutState()与xTaskCheckForTimeOut()一起使用。调用vTaskSetTimeOutState()来设置初始条件,之后可以调用xTaskCheckForTimeOut()来检查超时条件,并在未发生超时时调整剩余的块时间。

参数:

pxTimeOut  指向结构体的指针,该结构体将被初始化以保存确定是否发生超时所需的信息。

使用示例:

/* 驱动程序库函数,用于从一个被UART中断填充的Rx缓冲区接收uxWantedBytes。
如果Rx缓冲区中没有足够的字节,那么任务将进入阻塞状态,直到它被通知更多的数据
已被放入缓冲区。如果仍然没有足够的数据,则任务重新进入阻塞状态,并且使用
xTaskCheckForTimeOut()重新计算阻塞时间,以确保花费在阻塞状态的总时间不超过
MAX_TIME_TO_WAIT。这个过程会一直持续到缓冲区至少包含uxWantedBytes字节,
或者在Blocked状态下花费的总时间达到MAX_TIME_TO_WAIT——此时任务将读取任意数量
的可用字节,直至最大uxWantedBytes。 */
size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes )
{
    size_t uxReceived = 0;
    TickType_t xTicksToWait = MAX_TIME_TO_WAIT;
    TimeOut_t xTimeOut;

   /* 初始化xTimeOut。这记录了这个函数被输入的时间。 */
   vTaskSetTimeOutState( &xTimeOut );

   /* 循环,直到缓冲区包含所需的字节数,或发生超时。 */
   while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes )
   {
      /* 缓冲区没有包含足够的数据,所以这个任务将进入阻塞状态。
         调整xTicksToWait以计算该函数中到目前为止花费在Blocked状态的所有时间,
         以确保花费在Blocked状态的总时间不超过MAX_TIME_TO_WAIT。 */
      if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE )
      {
         /* 在所需的字节数可用之前超时,退出循环。 */
         break;
      }

      /* 等待最大数量的xTicksToWait滴答,以收到接收中断已将更多数据放入缓冲区的通知。*/
      ulTaskNotifyTake( pdTRUE, xTicksToWait );
   }

   /* 尝试将uxWantedBytes从接收缓冲区读入pucBuffer。
      返回实际读取的字节数(可能小于uxWantedBytes)。 */
   uxReceived = UART_read_from_receive_buffer( pxUARTInstance,
                                               pucBuffer,
                                               uxWantedBytes );

   return uxReceived;
}

24.xTaskCheckForTimeOut()

BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
                                 TickType_t * const pxTicksToWait );

本功能仅适用于高级用户。

任务可以进入阻塞状态等待事件发生。通常,任务不会无限期地处于Blocked状态,而是指定一个超时时间。如果在任务等待的事件发生之前超时,任务将从阻塞状态移除。

如果一个任务在等待事件发生的过程中多次进入和退出阻塞状态,则必须调整每次进入阻塞状态的超时时间,以确保所有处于阻塞状态的时间总和不超过原来指定的超时时间。xTaskCheckForTimeOut()执行调整,考虑到偶尔发生的滴答计数溢出,否则手动调整容易出错。

xTaskCheckForTimeOut()与vTaskSetTimeOutState()一起使用。调用vTaskSetTimeOutState()来设置初始条件,之后可以调用xTaskCheckForTimeOut()来检查超时条件,并在未发生超时时调整剩余的块时间。

参数:

pxTimeOut  指向一个结构体的指针,该结构体保存确定是否发生超时所需的信息。pxTimeOut使用vTaskSetTimeOutState()初始化。
pxTicksToWait 用于传递调整后的块时间,这是在考虑了已在Blocked状态下花费的时间后剩下的块时间。

返回值:

如果返回pdTRUE,则没有块时间剩余,并且发生了超时。

如果返回pdFALSE,则仍然存在一些块时间,因此没有发生超时。

使用示例:

/* 驱动程序库函数,用于从一个被UART中断填充的Rx缓冲区接收uxWantedBytes。
如果Rx缓冲区中没有足够的字节,那么任务将进入阻塞状态,直到它被通知更多的数据
已被放入缓冲区。如果仍然没有足够的数据,则任务重新进入阻塞状态,并且使用
xTaskCheckForTimeOut()重新计算阻塞时间,以确保花费在阻塞状态的总时间不超过
MAX_TIME_TO_WAIT。这个过程会一直持续到缓冲区至少包含uxWantedBytes字节,
或者在Blocked状态下花费的总时间达到MAX_TIME_TO_WAIT——此时任务将读取任意数量
的可用字节,直至最大uxWantedBytes。 */
size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes )
{
    size_t uxReceived = 0;
    TickType_t xTicksToWait = MAX_TIME_TO_WAIT;
    TimeOut_t xTimeOut;

   /* 初始化xTimeOut。这记录了这个函数被输入的时间。 */
   vTaskSetTimeOutState( &xTimeOut );

   /* 循环,直到缓冲区包含所需的字节数,或发生超时。 */
   while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes )
   {
      /* 缓冲区没有包含足够的数据,所以这个任务将进入阻塞状态。
         调整xTicksToWait以计算该函数中到目前为止花费在Blocked状态的所有时间,
         以确保花费在Blocked状态的总时间不超过MAX_TIME_TO_WAIT。 */
      if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE )
      {
         /* 在所需的字节数可用之前超时,退出循环。 */
         break;
      }

      /* 等待最大数量的xTicksToWait滴答,以收到接收中断已将更多数据放入缓冲区的通知。*/
      ulTaskNotifyTake( pdTRUE, xTicksToWait );
   }

   /* 尝试将uxWantedBytes从接收缓冲区读入pucBuffer。
      返回实际读取的字节数(可能小于uxWantedBytes)。 */
   uxReceived = UART_read_from_receive_buffer( pxUARTInstance,
                                               pucBuffer,
                                               uxWantedBytes );

   return uxReceived;
}
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

QxNL

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

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

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

打赏作者

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

抵扣说明:

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

余额充值