Homepage  

Trace Hook Macros
[FreeRTOS Fundamentals]

Description

Trace hook macros are a very powerful feature introduced in FreeRTOS.org V5.0.0 that permit you to collect data on how your embedded application is behaving.

Key points of interest within the FreeRTOS.org source code contain empty macros that an application can re-define for the purpose of proving application specific trace facilities. The application need only implement those macros of particular interest - with unused macros remaining empty and therefore not impacting the application timing.


Examples

Following are some examples of how these macros can be used:
  • Setting a digital output to indicate which task is executing - allowing a logic analyzer to be used to view and record the task execution sequence and timing.
  • Similarly - setting an analogue output to a voltage that represents which task is executing - allowing an oscilloscope to be used to view and record the task execution sequence and timing.
  • Logging task execution sequences, task timing, kernel events and API calls for offline analysis.
  • Integrating kernel events into third party debuggers.

Example 1

The FreeRTOS.org task tag functionality provides a simple mechanism for setting up logging via digital or analogue outputs. For example, the tag value can be set to a voltage that is unique to that task. The traceSWITCHED_IN() macro can then be defined to simply set an analogue output to the value associated with the task being switched in. For example:

    */ First task sets its tag value to 1. */
    void vTask1( void *pvParameters )
    {
        */ This task is going to be represented by a voltage scale of 1. */
        vTaskSetApplicationTaskTag( NULL, ( void * ) 1 );    
    
        for( ;; )
        {
            */ Task code goes here. */
        }
    }
    /*************************************************/
    
    */ Second task sets its tag value to 2. */
    void vTask1( void *pvParameters )
    {
        */ This task is going to be represented by a voltage scale of 2. */
        vTaskSetApplicationTaskTag( NULL, ( void * ) 2 );    
    
        for( ;; )
        {
            */ Task code goes here. */
        }
    }
    /*************************************************/
	    
    */ Define the traceTASK_SWITCHED_IN() macro to output the voltage associated
    with the task being selected to run on port 0. */
    #define traceTASK_SWICTHED_IN() vSetAnalogueOutput( 0, ( int ) pxCurrentTCB->pxTaskTag )

Example 2

API call logging can be used to record the reason a context switch occurred. Kernel call logging can be used to record the sequence in which tasks execute. For example:
/* traceBLOCKING_ON_QUEUE_RECEIVE() is just one of the macros that can be used to record why
a context switch is about to occur. */
#define traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue)     \
    ulSwitchReason = reasonBLOCKING_ON_QUEUE_READ;

/* log_event() is an application defined function that logs which tasks ran when, and why. */
#define traceTASK_SWITCHED_OUT()                    \
    log_event( pxCurrentTCB, ulSwitchReason );


Defining

Macros that are called from within interrupts, particularly the tick interrupt, must execute quickly and not use much stack space. Setting variables, writing to trace registers, or outputting do ports are all acceptable. Attempting to fprintf() log data to a slow disk will not work!

Macro definitions must occur before the inclusion of FreeRTOS.h. The easiest place to define trace macros is at the bottom of FreeRTOSConfig.h, or in a separate header file that is included from the bottom of FreeRTOSConfig.h.

The table below describes the available macros. The macro parameters are used to indicate which task, queue, semaphore or mutex was associated with the event being recorded.

Macro definition
Description
traceTASK_INCREMENT_TICK()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.
traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue)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(pxQueue)Indicates that the currently executing task is about to block following an attempt to write to a full queue.
traceGIVE_MUTEX_RECURSIVE(pxMutex)Called from within xSemaphoreGiveRecursive().
traceQUEUE_CREATE()Called from within xQueueCreate() if the queue was successfully created.
traceQUEUE_CREATE_FAILED()Called from within xQueueCreate() if the queue was not successfully created due to there being insufficient heap memory available.
traceCREATE_MUTEX()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(pxMutex)Called from within xSemaphoreGiveRecursive() if the mutex was successfully 'given'.
traceGIVE_MUTEX_RECURSIVE_FAILED(pxMutex)Called from within xSemaphoreGiveRecursive() if the mutex was not successfully given as the calling task was not the mutex owner.
traceTAKE_MUTEX_RECURSIVE(pxMutex)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(pxQueue)Called from within xQueueSend(), xQueueSendToFront(), xQueueSendToBack(), or any of the semaphore 'give' functions, when the queue send was successful.
traceQUEUE_SEND_FAILED(pxQueue)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(pxQueue)Called from within xQueueReceive() or any of the semaphore 'take' functions when the queue receive was successful.
traceQUEUE_RECEIVE_FAILED()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()Called from within xQueuePeek()
traceQUEUE_SEND_FROM_ISR(pxQueue)Called from within xQueueSendFromISR() when the send operation was successful.
traceQUEUE_SEND_FROM_ISR_FAILED(pxQueue)Called from within xQueueSendFromISR() when the send operation failed due to the queue already being full.
traceQUEUE_RECEIVE_FROM_ISR(pxQueue)Called from within xQueueReceiveFromISR() when the receive operation was successful.
traceQUEUE_RECEIVE_FROM_ISR_FAILED(pxQueue)Called from within xQueueReceiveFromISR() when the receive operation failed due to the queue already being empty.
traceQUEUE_DELETE(pxQueue)Called from within vQueueDelete().
traceTASK_CREATE(pxTask)Called from within xTaskCreate() when the task is successfully created.
traceTASK_CREATE_FAILED()Called from within xTaskCreate() when the task was not successfully created due to there being insufficient heap space available.
traceTASK_DELETE(pxTask)Called from within vTaskDelete().
traceTASK_DELAY_UNTIL()Called from within vTaskDelayUntil().
traceTASK_DELAY()Called from within vTaskDelay().
traceTASK_PRIORITY_SET(pxTask,uxNewPriority)Called from within vTaskPrioritySet().
traceTASK_SUSPEND(pxTask)Called from within vTaskSuspend().
traceTASK_RESUME(pxTask)Called from within vTaskResume().
traceTASK_RESUME_FROM_ISR(pxTask)Called from within xTaskResumeFromISR().





Copyright (C) 2003 - 2008 Richard Barry
Any and all data, files, source code, html content and documentation included in the FreeRTOS distribution or available on this site are the exclusive property of Richard Barry. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Richard Barry.