1.4.3 跟踪特性
优质
小牛编辑
144浏览
2023-12-01
跟踪钩子宏是一个很强大的功能,用来收集嵌入式应用的相关数据。freeRTOS提供的源代码中的跟踪宏是空的,因此开发者可以根据自己的需求设计宏需要跟踪的数据,不使用的空的宏不会影响应用程序的时序。
如下几个使用跟踪宏的例子:
- 设置一个数字输出,用来表明当前执行的任务。可以使用逻辑分析仪来观察、记录、分析任务的执行序列及时序
- 相似的,可以设置模拟输出,比如电压,则可以使用示波器来观察时序
- 记录任务的执行序列、时序、RTOS内核事件和API调用,这些数据可以用来离线分析应用
- 在第三方调试器中集成RTOS内核事件
例子1
为每个任务提供一个数字的或者模拟的标签值,每个任务的标签值都是特定的,将traceSWITCHED_IN()
宏设置为输出这个标签值:
/* 第一个任务标签值设为1\. */
void vTask1( void *pvParameters )
{/* 使用电压灯等级1代表任务1 */vTaskSetApplicationTaskTag( NULL, ( void * ) 1 );
for( ;; ){
/* Task code goes here. */}
}
/*************************************************/
/* 第二个任务标签值设为2. */
void vTask2( void *pvParameters )
{/* 使用电压等级2代表任务2 */vTaskSetApplicationTaskTag( NULL, ( void * ) 2 );
for( ;; ){
/* Task code goes here. */}
}
/*************************************************/
/* 设置宏输出任务的标签值,使用通道0. */
#define traceTASK_SWITCHED_IN() vSetAnalogueOutput( 0, (int)pxCurrentTCB->pxTaskTag )
例子2
API调用记录可以用来记录上下文切换的原因,RTOS内核调用记录可以用来记录任务的执行序列,比如:
/* traceBLOCKING_ON_QUEUE_RECEIVE() 可以用来记录上下文切换的原因 */
#define traceBLOCKING_ON_QUEUE_RECEIVE(xQueue) \ulSwitchReason = reasonBLOCKING_ON_QUEUE_READ;
/* log_event() 用来记录任务的执行时间及原因 */
#define traceTASK_SWITCHED_OUT()\log_event( pxCurrentTCB, ulSwitchReason );
定义
在中断中调用的宏必须是短小精悍的,设置变量、写跟踪寄存器、端口输出是可以接受的,但是像fprintf()
这类试图输出数据到存储器的功能,因为占用时间太长,而不被允许。
所有的宏定义必须在包含freeRTOS.h
配置文件之前,最简单的方式是在freeRTOS.h
文件的开头定义这些宏,当然也可以在单独的文件中定义,但是包含顺序需要在freeRTOS.h
之前。
下表列出了这些可用的宏,宏的参数暗示了事件记录时的关联对象(队列、互斥量、信号量)
Macro definition | Description |
traceTASK_INCREMENT_TICK(xTickCount) | Called during the tick interrupt. |
traceTASK_SWITCHED_OUT() | Called before a new task is selected to run. At this point pxCurrentTCB contains the handle of the task about to leave the Running state. |
traceTASK_SWITCHED_IN() | Called after a task has been selected to run. At this point pxCurrentTCB contains the handle of the task about to enter the Running state. |
traceMOVED_TASK_TO_READY_STATE(xTask) | Called when a task is transitioned into the Ready state. |
traceBLOCKING_ON_QUEUE_RECEIVE(xQueue) | Indicates that the currently executing task is about to block following an attempt to read from an empty queue, or an attempt to 'take' an empty semaphore or mutex. |
traceBLOCKING_ON_QUEUE_SEND(xQueue) | Indicates that the currently executing task is about to block following an attempt to write to a full queue. |
traceGIVE_MUTEX_RECURSIVE(xMutex) | Called from within xSemaphoreGiveRecursive(). |
traceGIVE_MUTEX_RECURSIVE_FAILED(xMutex) | Called from within xSemaphoreGiveRecursive(). |
traceQUEUE_CREATE(pxNewQueue) | Called from within xQueueCreate() or xQueueCreateStatic() if the queue was successfully created. |
traceQUEUE_CREATE_FAILED() | Called from within xQueueCreate() or xQueueCreateStatic() if the queue was not successfully created due to there being insufficient heap memory available. |
traceCREATE_MUTEX(pxNewMutex) | Called from within xSemaphoreCreateMutex() if the mutex was successfully created. |
traceCREATE_MUTEX_FAILED() | Called from within xSemaphoreCreateMutex() if the mutex was not successfully created due to there being insufficient heap memory available. |
traceGIVE_MUTEX_RECURSIVE(xMutex) | Called from within xSemaphoreGiveRecursive() if the mutex was successfully 'given'. |
traceGIVE_MUTEX_RECURSIVE_FAILED(xMutex) | Called from within xSemaphoreGiveRecursive() if the mutex was not successfully given as the calling task was not the mutex owner. |
traceTAKE_MUTEX_RECURSIVE(xMutex) | Called from within xQueueTakeMutexRecursive(). |
traceCREATE_COUNTING_SEMAPHORE() | Called from within xSemaphoreCreateCounting() if the semaphore was successfully created. |
traceCREATE_COUNTING_SEMAPHORE_FAILED() | Called from within xSemaphoreCreateCounting() if the semaphore was not successfully created due to insufficient heap memory being available. |
traceQUEUE_SEND(xQueue) | Called from within xQueueSend(), xQueueSendToFront(), xQueueSendToBack(), or any of the semaphore 'give' functions, when the queue send was successful. |
traceQUEUE_SEND_FAILED(xQueue) | Called from within xQueueSend(), xQueueSendToFront(), xQueueSendToBack(), or any of the semaphore 'give' functions when the queue send operation failed due to the queue being full (after any block time that was specified). |
traceQUEUE_RECEIVE(xQueue) | Called from within xQueueReceive() or any of the semaphore 'take' functions when the queue receive was successful. |
traceQUEUE_RECEIVE_FAILED(xQueue) | Called from within xQueueReceive() or any of the semaphore 'take' functions when the queue receive operation failed because the queue was empty (after any block time that was specified). |
traceQUEUE_PEEK(xQueue) | Called from within xQueuePeek() |
traceQUEUE_SEND_FROM_ISR(xQueue) | Called from within xQueueSendFromISR() when the send operation was successful. |
traceQUEUE_SEND_FROM_ISR_FAILED(xQueue) | Called from within xQueueSendFromISR() when the send operation failed due to the queue already being full. |
traceQUEUE_RECEIVE_FROM_ISR(xQueue) | Called from within xQueueReceiveFromISR() when the receive operation was successful. |
traceQUEUE_RECEIVE_FROM_ISR_FAILED(xQueue) | Called from within xQueueReceiveFromISR() when the receive operation failed due to the queue already being empty. |
traceQUEUE_DELETE(xQueue) | Called from within vQueueDelete(). |
traceTASK_CREATE(xTask) | Called from within xTaskCreate() (or xTaskCreateStatic()) when the task is successfully created. |
traceTASK_CREATE_FAILED(pxNewTCB) | Called from within xTaskCreate() (or xTaskCreateStatic()) when the task was not successfully created due to there being insufficient heap space available. |
traceTASK_DELETE(xTask) | Called from within vTaskDelete(). |
traceTASK_DELAY_UNTIL() | Called from within vTaskDelayUntil(). |
traceTASK_DELAY() | Called from within vTaskDelay(). |
traceTASK_PRIORITY_SET(xTask,uxNewPriority) | Called from within vTaskPrioritySet(). |
traceTASK_SUSPEND(xTask) | Called from within vTaskSuspend(). |
traceTASK_RESUME(xTask) | Called from within vTaskResume(). |
traceTASK_RESUME_FROM_ISR(xTask) | Called from within xTaskResumeFromISR(). |
traceTIMER_COMMAND_RECEIVED(pxTimer, xCommandID, xCommandValue) | Called within the timer service task each time it receives a command, before the command is actually processed. |
traceTIMER_COMMAND_SEND(pxTimer, xCommandID, xOptionalValue, xStatus) | Called from within any API function that sends a command to the timer service task, for example, xTimerReset(), xTimerStop(), etc. xStatus will be pdFAIL if the command was not successfully sent to the timer command queue. |
traceTIMER_CREATE(pxNewTimer) | Called from within xTimerCreate() if the timer was successfully created. |
traceTIMER_CREATE_FAILED() | Called from within xTimerCreate() if the timer was not successfully created due to there being insufficient heap memory available. |
traceTIMER_EXPIRED(pxTimer) | Called when a software timer expires, before the timer callback is executed. |