本文小编为大家详细介绍“FreeRTOS实时操作系统的任务应用函数是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“FreeRTOS实时操作系统的任务应用函数是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
1.获取任务系统状态
1.1函数描述
UBaseType_t uxTaskGetSystemState( TaskStatus_t * constpxTaskStatusArray, const UBaseType_tuxArraySize, unsigned long * constpulTotalRunTime );
该函数向TaskStatus_t结构体填充相关信息,系统中每一个任务的信息都可以填充到TaskStatus_t结构体数组中,数组大小由uxArraySize指定。结构体TaskStatus_t定义如下:
typedef struct xTASK_STATUS{ TaskHandle_t xHandle; const signed char *pcTaskName; UBaseType_t xTaskNumber; eTaskState eCurrentState; UBaseType_t uxCurrentPriority; UBaseType_t uxBasePriority; unsigned long ulRunTimeCounter; unsigned short usStackHighWaterMark;}TaskStatus_t;
注意,这个函数仅用来调试用,调用此函数会挂起所有任务,直到函数最后才恢复挂起的任务,因此任务可能被挂起很长时间。在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY必须设置为1,此函数才有效。
1.2参数描述
pxTaskStatusArray
:指向TaskStatus_t类型的结构体数组。这个数组至少要包含1个元素。RTOS控制的任务数量可以使用API函数uxTaskGetNumberOfTasks()获取。
uxArraySize
:参数pxTaskStatusArray指向的数组大小,也就是该数组的索引数目。
pulTotalRunTime
:如果在文件FreeRTOSConfig.h中设置宏configGENERATE_RUN_TIME_STATS为1,则该函数将总运行时间写入*pulTotalRunTime中。pulTotalRunTime可以设置为NULL,表示忽略总运行时间。
1.3返回值
被填充的TaskStatus_t结构体数量。这个值应该等于通过调用API函数uxTaskGetNumberOfTasks()返回的值,但如果传递给uxArraySize参数的值太小,则返回0。
1.4用法举例
void vTaskGetRunTimeStats(signed char *pcWriteBuffer ){ TaskStatus_t*pxTaskStatusArray; volatileUBaseType_t uxArraySize, x; unsignedlong ulTotalRunTime, ulStatsAsPercentage; *pcWriteBuffer = 0x00; uxArraySize = uxTaskGetNumberOfTasks (); pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t )); if(pxTaskStatusArray != NULL ) { uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize,&ulTotalRunTime ); ulTotalRunTime /= 100UL; if(ulTotalRunTime > 0 ) { for( x = 0; x < uxArraySize; x++ ) { ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter /ulTotalRunTime; if( ulStatsAsPercentage > 0UL ) { sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); } else { sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[x ].ulRunTimeCounter ); } pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); } } vPortFree( pxTaskStatusArray ); }}
2.获取当前任务句柄
2.1函数描述
TaskHandle_t xTaskGetCurrentTaskHandle(void );
在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetCurrentTaskHandle必须设置为1,此函数才有效。
2.2返回值
返回当前任务(调用该函数的任务)的句柄。
3.获取空闲任务句柄
3.1函数描述
TaskHandle_t xTaskGetIdleTaskHandle(void );
在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetIdleTaskHandle必须设置为1,此函数才有效。
3.2返回值
返回空闲任务句柄。空闲任务在RTOS调度器启动时自动创建。
4.获取任务堆栈最大使用深度
4.1函数描述
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
任务的堆栈空间会随着任务执行以及中断处理而增长或缩小。该函数可以返回任务启动后的最小剩余堆栈空间。换句话说,可以间接估算出一个任务最多需要多少堆栈空间。在文件FreeRTOSConfig.h中,宏INCLUDE_uxTaskGetStackHighWaterMark 必须设置成1,此函数才有效。
4.2参数描述
xTask:任务句柄。NULL表示查看当前任务的堆栈使用情况。
4.3返回值
返回最小剩余堆栈空间,以字为单位。比如一个32为架构处理器,返回值为1表示有4字节堆栈空间没有使用过。如果返回值为0,则任务很可能已经发生了堆栈溢出。
4.4用法举例
void vTask1( void * pvParameters ) { UBaseType_tuxHighWaterMark; uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL ); for( ;; ) { vTaskDelay( 1000 ); uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL ); } }
5.获取任务状态
5.1函数描述
eTaskState eTaskGetState( TaskHandle_txTask );
返回一个枚举类型的任务状态值。在文件FreeRTOSConfig.h中,宏INCLUDE_eTaskGetState必须设置为1,此函数才有效。
5.2参数描述
xTask:任务句柄
5.3返回值
下表列出返回值和对应的任务状态。
6.获取任务描述内容
6.1函数描述
char * pcTaskGetTaskName( TaskHandle_txTaskToQuery );
获取任务的描述内容,在文件FreeRTOSConfig.h中,宏INCLUDE_pcTaskGetTaskName必须设置成1,此函数才有效。
6.2参数描述
xTaskToQuery:任务的句柄。NULL表示获取当前任务的描述内容指针。
6.3返回值
一个指针,指向任务描述字符串。
7.获取系统节拍次数
7.1函数描述
volatile TickType_t xTaskGetTickCount(void );
这个函数不能在ISR中调用。在ISR中用xTaskGetTickCountFromISR(),原型为volatileTickType_t xTaskGetTickCountFromISR( void )。
7.2返回值
返回从vTaskStartScheduler函数调用后的系统时钟节拍次数。
8.获取调度器状态
8.1函数描述
BaseType_t xTaskGetSchedulerState( void);
获取调度器当前状态。在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetSchedulerState或configUSE_TIMERS必须定义为1,此函数才有效。
8.2返回值
&&&返回值是以下常量之一(定义在task.h):taskSCHEDULER_NOT_STARTED(未启动)、taskSCHEDULER_RUNNING(正常运行)、taskSCHEDULER_SUSPENDED(挂起)。
9.获取任务总数
9.1函数描述
UBaseType_t uxTaskGetNumberOfTasks(void );
&&&获取RTOS内核当前管理的任务总数。包含所有就绪、阻塞和挂起状态的任务。对于一个删除的任务,如果它的堆栈空间还没有被空闲任务释放掉,则这个被删除的任务也含在计数值中。
9.2返回值
&&&返回RTOS内核当前管理的任务总数。
10.获取所有任务详情
10.1函数描述
void vTaskList( char *pcWriteBuffer );
&&&将每个任务的状态、堆栈使用情况等以字符的形式保存到参数pcWriteBuffer指向的区域。vTaskList()函数调用usTaskGetSystemState()函数,然后将得到的信息格式化为程序员易读的字符形式。输出的内容例子如下图所示,图中State一栏中,B表示阻塞、R表示就绪、D表示删除(等待清除内存)、S表示挂起或阻塞。
&&&注意,调用这个函数会挂起所有任务,这一过程可能持续较长时间,因此本函数仅在调试时使用。在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS必须定义为1,此函数才有效。
10.2参数描述
pcWriteBuffer:任务的信息会写入这个缓冲区,为ASCII表单形式。这个缓冲区要足够大,以容纳生成的报告,每个任务大约需要40个字节。
11.获取任务运行时间
11.1函数描述
void vTaskGetRunTimeStats( char*pcWriteBuffer );
这个函数用于统计每个任务的运行时间。要使用这个函数必须满足一些条件,那就是必须有一个用于时间统计的定时器或计数器,这个定时器或计数器的精度要至少大于10倍的系统节拍周期。这个定时器或计数器的配置以及获取定时时间是由两个宏定义实现的,这两个宏一般在文件FreeRTOSConfig.h中定义。配置定时器或计数器的宏为portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),获取定时时间的宏为portGET_RUN_TIME_COUNTER_VALUE。实现了这两个宏定义后,还必须在文件FreeRTOSConfig.h中将宏configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_FUNCTIONS设置为1,此API函数才有效。
&&&这个API函数调用usTaskGetSystemState()函数获取每个任务的状态信息,并把其中的运行时间格式化为程序员易读的字符形式,并将这些信息保存到参数pcWriteBuffer指向的区域。
&&&注意,调用这个函数会挂起所有任务,这一过程可能持续较长时间,因此本函数仅在调试时使用。
11.2参数描述
pcWriteBuffer:任务的运行时间信息会写入这个缓冲区,为ASCII表单形式。这个缓冲区要足够大,以容纳生成的报告,每个任务大约需要40个字节。
11.3用法举例
&&&以lpc17xx系列为控制为例,我们使用定时器0来作为统计基准时钟。
11.3.1使能函数宏
&&&在文件FreeRTOSConfig.h中,设置宏configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_FUNCTIONS为1,
11.3.2定时初始化定时器代码
void vConfigureTimerForRunTimeStats( void ){ PCONP |= 0x02UL; PCLKSEL0 = (PCLKSEL0& (~(0x3<<2))) | (0x01 << 2); T0TCR = 0x02; T0CTCR = 0x00; T0PR = ( configCPU_CLOCK_HZ / 10000UL ) - 1UL; T0TCR = 0x01;}
11.3.3定义配置定时器和获取定时时间宏
&&&在文件FreeRTOSConfig.h中,定义下列代码:
extern void vConfigureTimerForRunTimeStats( void );#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()#defineportGET_RUN_TIME_COUNTER_VALUE() T0TC
12.设置任务标签值
12.1函数描述
voidvTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_tpxTagValue );
&&&可以给每个任务分配一个标签值。这个值一般用于应用程序,RTOS内核不会使用。在文件FreeRTOSConfig.h中,宏configUSE_APPLICATION_TASK_TAG必须设置为1,此函数才有效。
12.2参数描述
xTask:任务句柄。NULL表示当前任务。pxTagValue:要分配给任务的标签值。这是一个TaskHookFunction_t类型的函数指针,但也可以给任务标签分配任意的值。
注:TaskHookFunction_t原型定义:typedef BaseType_t (*TaskHookFunction_t)(void * )
12.3用法举例
void vATask( void *pvParameters ){ vTaskSetApplicationTaskTag( NULL, ( void * ) 1 ); for( ;; ) { }}static BaseType_t prvExampleTaskHook( void * pvParameter ){ return 0;}void vAnotherTask( void *pvParameters ){ vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook ); for( ;; ) { }}#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook(pxCurrentTCB,0 )
13.获取任务标签值
13.1函数描述
TaskHookFunction_txTaskGetApplicationTaskTag( TaskHandle_t xTask );
返回分配给任务的标签值。程序员定义标签值,RTOS内核通常不会访问标签值。
函数仅对高级用户使用。在文件FreeRTOSConfig.h中,宏configUSE_APPLICATION_TASK_TAG必须设置为1,此函数才有效。
13.2参数描述
xTask:任务句柄。NULL表示当前任务。
13.3返回值
返回指定任务的标签值。
14.执行任务的应用钩子函数
14.1函数描述
BaseType_txTaskCallApplicationTaskHook( TaskHandle_txTask, void*pvParameter );
可以为每个任务分配一个标签值,当这个值是一个TaskHookFunction_t类型函数指针时,相当于应用程序向任务注册了一个回调函数,而API函数xTaskCallApplicationTaskHook用来调用这个回调函数。
一般这个函数配合RTOS跟踪钩子宏使用,见12.设置任务标签值一节的用法举例。
14.2参数描述
xTask:任务句柄。NULL表示当前任务。pvParameter:作为参数传递给应用钩子函数
15.设置线程本地存储指针
15.1函数描述
void vTaskSetThreadLocalStoragePointer(TaskHandle_t xTaskToSet, BaseType_t xIndex, void*pvValue )
此函数仅用于高级用户。
线程本地存储允许应用程序在任务的控制块中存储一些值,每个任务都有自己独立的储存空间。
比如,许多库函数都包含一个叫做errno的全局变量。某些库函数使用errno返回库函数错误信息,应用程序检查这个全局变量来确定发生了那些错误。在单线程程序中,将errno定义成全局变量是可以的,但是在多线程应用中,每个线程(任务)必须具有自己独有的errno值,否则,一个任务可能会读取到另一个任务的errno值。
FreeRTOS提供了一个灵活的机制,使得应用程序可以使用线程本地存储指针来读写线程本地存储。在文件FreeRTOSConfig.h中,宏configNUM_THREAD_LOCAL_STORAGE_POINTERS指定每个任务线程本地存储指针数组的大小。API函数vTaskSetThreadLocalStoragePointer()用于向指针数组中写入值,API函数pvTaskGetThreadLocalStoragePointer()用于从指针数组中读取值。
15.2参数描述
xTaskToSet
:任务句柄。NULL表示当前任务。
xIndex
:写入到线程本地存储数组的索引号,线程本笃存储数组的大小由宏configNUM_THREAD_LOCAL_STORAGE_POINTERS设定,该宏在文件FreeRTOSConfig.h中。
pvValue
:写入到指定索引地址的数据值
15.3用法举例
&&参见16.获取线程本地存储指针一节。
16.读取线程本地存储指针
16.1函数描述
void*pvTaskGetThreadLocalStoragePointer( TaskHandle_txTaskToQuery, BaseType_txIndex );
此函数仅用于高级用户。从线程本地存储指针数组中读取值。更详细描述见15.设置线程本地存储指针一节。
16.2参数描写
xTaskToQuery
:任务句柄。NULL表示当前任务。
xIndex
:写入到线程本地存储数组的索引号,线程本笃存储数组的大小由宏configNUM_THREAD_LOCAL_STORAGE_POINTERS设定,该宏在文件FreeRTOSConfig.h中。
16.3返回值
返回一个指针,这个指针存储在线程本地存储指针数组中,数组索引由参数xIndex指定。
16.4用法举例
16.4.1存储一个整形数
uint32_tulVariable;vTaskSetThreadLocalStoragePointer(NULL, 1, ( void * ) 0x12345678 );ulVariable= ERROR_CODE;vTaskSetThreadLocalStoragePointer(NULL, 0, ( void * ) ulVariable );ulVariable= ( uint32_t ) pvTaskGetThreadLocalStoragePointer( NULL, 5 );
16.4.2存储结构提
typedefstruct{ uint32_t ulValue1; uint32_t ulValue2;}xExampleStruct;xExampleStruct*pxStruct;pxStruct= pvPortMalloc( sizeof( xExampleStruct ) );pxStruct->ulValue1= 0;pxStruct->ulValue2= 1;vTaskSetThreadLocalStoragePointer(NULL, 0, ( void * ) pxStruct );pxStruct= ( xExampleStruct * ) pvTaskGetThreadLocalStoragePointer( NULL, 0 );
17.设置超时状态
17.1函数描述
void vTaskSetTimeOutState( TimeOut_t *const pxTimeOut );
此函数仅用于高级用户,通常与API函数xTaskCheckForTimeOut()共同使用。
任务因为等待某事件而进入阻塞状态,通常情况下任务会设置一个等待超时周期。如果在等待事件超时,任务会退出阻塞状态。想象一个这样的应用,某任务等待一个事件而进入阻塞状态,但是事件迟迟不发生,超时后任务退出阻塞状态继续执行任务。假如任务等待的事件仍然没有发生,则任务又会阻塞在该事件下。只要任务等待的事件一直不发生,这个任务进入阻塞然后超时退出阻塞,再进入阻塞的循环就会一直存在。是不是可以设定一个总超时时间,只要总阻塞时间大于这个总超时时间,则可以结束这个任务或进行相应记录?freeRTOS提供了两个API函数来完成这个功能,这就是vTaskSetTimeOutState()和xTaskCheckForTimeOut()。
vTaskSetTimeOutState()函数用于设置初始条件,之后调用xTaskCheckForTimeOut()函数检查任务总阻塞时间是否超过总超时时间,如果没有超过,则调整剩余的超时时间计数器。
17.2参数描述
pxTimeOut:指向一个结构体的指针,该结构体用来保存确定超时是否发生的必要信息。vTaskSetTimeOutState()函数会设置结构体的成员。
17.3用法举例
参见18.超时检测。
18.超时检测
18.1函数描述
BaseType_t xTaskCheckForTimeOut(TimeOut_t * const pxTimeOut, TickType_t* const pxTicksToWait );
此函数仅用于高级用户,通常与API函数vTaskSetTimeOutState共同使用。
详细描述见17.设置超时状态。
18.2参数描述
pxTimeOut
:指向一个结构体的指针。该结构体保存确定超时是否发生的必要信息。使用API函数vTaskSetTimeOutState初始化该结构体。
pxTicksToWait
:TickType_t指针,指向的变量保存总超时时间。
18.3返回值
pdTRUE:总超时发生pdFALSE:总超时未发生
18.4用法举例
size_txUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes ){ size_t uxReceived = 0; TickType_t xTicksToWait = MAX_TIME_TO_WAIT; TimeOut_t xTimeOut; vTaskSetTimeOutState( &xTimeOut ); while( UART_bytes_in_rx_buffer(pxUARTInstance ) < uxWantedBytes ) { if( xTaskCheckForTimeOut( &xTimeOut,&xTicksToWait ) != pdFALSE ) { break; } ulTaskNotifyTake( pdTRUE, xTicksToWait ); } uxReceived = UART_read_from_receive_buffer(pxUARTInstance, pucBuffer, uxWantedBytes ); return uxReceived;}
读到这里,这篇“FreeRTOS实时操作系统的任务应用函数是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。