Quality RTOS & Embedded Software
About   Contact   Support   FAQ

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs Books & Kits Visualisation Ecosystem FreeRTOS Labs Training




Last site update Oct 5 2014

Trace Hook Macros
[More Advanced]

Also available: FreeRTOS+Trace, a third party trace tool for FreeRTOS - part of the FreeRTOS+ ecosystem

Description

Trace hook macros are a very powerful feature that permit you to collect data on how your embedded application is behaving.

Key points of interest within the FreeRTOS source code contain empty macros that an application can re-define for the purpose of providing 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, RTOS kernel events and API calls for offline analysis.
  • Integrating RTOS kernel events into third party debuggers.

Example 1

The FreeRTOS 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 vTask2( 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_SWITCHED_IN() vSetAnalogueOutput( 0, ( int ) pxCurrentTCB->pxTaskTag )

Example 2

API call logging can be used to record the reason a context switch occurred. RTOS 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(xQueue)      \
    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 to 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(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() 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(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() when the task is successfully created.
traceTASK_CREATE_FAILED(pxNewTCB)Called from within xTaskCreate() 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.






[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




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