/* * Trace Recorder for Tracealyzer v4.6.0 * Copyright 2021 Percepio AB * www.percepio.com * * SPDX-License-Identifier: Apache-2.0 */ #ifndef TRC_RECORDER_H #define TRC_RECORDER_H /** * @file * * @brief The public API of the Percepio trace recorder. */ #ifdef __cplusplus extern "C" { #endif /** * @brief Trace Recorder APIs * @defgroup trace_recorder_apis Trace Recorder APIs * @{ * @} */ #define TRC_ACKNOWLEDGED ( 0xABC99123 ) #include #include #include #include #ifndef TRC_CFG_TEST_MODE #define TRC_CFG_TEST_MODE 0 #endif /* Unless defined by the kernel port, we assume there is no support for * the classic snapshot mode and default to streaming mode where * the new RingBuffer snapshot mode provides snapshot functionality. */ #ifndef TRC_CFG_RECORDER_MODE #define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_STREAMING #endif #if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT ) #include #include /* Calls xTraceError if the _assert condition is false. For void functions, * where no return value is to be provided. */ #define TRC_ASSERT_VOID( _assert, _err ) if( !( _assert ) ) { prvTraceError( _err ); return; } /* Calls xTraceError if the _assert condition is false. For non-void functions, * where a return value is to be provided. */ #define TRC_ASSERT_RET( _assert, _err, _return ) if( !( _assert ) ) { prvTraceError( _err ); return _return; } typedef uint8_t traceUBChannel; typedef uint8_t traceObjectClass; #undef traceHandle #if ( TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1 ) typedef uint16_t traceHandle; #else /* (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) */ typedef uint8_t traceHandle; #endif /* (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) */ #include #include /* Not yet available in snapshot mode */ #define vTraceConsoleChannelPrintF( fmt, ... ) ( void ) #define xTraceConsoleChannelPrintF( fmt, ... ) ( void ) #define prvTraceStoreEvent_None( ... ) #define prvTraceStoreEvent_Handle( ... ) #define prvTraceStoreEvent_Param( ... ) #define prvTraceStoreEvent_HandleParam( ... ) #define prvTraceStoreEvent_ParamParam( ... ) #define prvTraceStoreEvent_HandleParamParam( ... ) #define prvTraceStoreEvent_ParamParamParam( ... ) #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) */ #if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING ) #include #include /* Unless specified in trcConfig.h we assume this is a single core target */ #ifndef TRC_CFG_CORE_COUNT #define TRC_CFG_CORE_COUNT 1 #endif /* Unless specified in trcConfig.h we assume this is a single core target */ #ifndef TRC_CFG_GET_CURRENT_CORE #define TRC_CFG_GET_CURRENT_CORE() 0 #endif /* Unless specified in trcConfig.h or trcKernelPortConfig.h we assume * GCC statement expressions aren't supported. */ #ifndef TRC_CFG_USE_GCC_STATEMENT_EXPR #define TRC_CFG_USE_GCC_STATEMENT_EXPR 0 #endif /* Backwards compatibility */ typedef TraceISRHandle_t traceHandle; /* Maximum event size */ #define TRC_MAX_BLOB_SIZE ( 16 * sizeof( uint32_t ) ) /* Platform name length */ #define TRC_PLATFORM_CFG_LENGTH 8 /* Header size */ #define TRC_HEADER_BUFFER_SIZE ( sizeof( uint32_t ) + sizeof( uint16_t ) + sizeof( uint16_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint32_t ) + ( sizeof( char ) * ( TRC_PLATFORM_CFG_LENGTH ) ) + sizeof( uint16_t ) + sizeof( uint8_t ) + sizeof( uint8_t ) ) typedef struct TraceHeaderBuffer { uint8_t buffer[ TRC_HEADER_BUFFER_SIZE ]; } TraceHeaderBuffer_t; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ #if ( TRC_USE_TRACEALYZER_RECORDER == 1 ) /******************************************************************************/ /*** Common API - both Snapshot and Streaming mode ****************************/ /******************************************************************************/ /** * @brief * * Initializes the recorder data. xTraceInitialize() or xTraceEnable(...) * must be called before any attempts at adding trace data/information. * See xTraceEnable(...) for more information. * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceInitialize( void ); /** * @brief * * This function enables tracing. * To use the trace recorder, the startup must call xTraceInitialize() or * xTraceEnable(...) before any RTOS calls are made (including "create" calls). * Three start options are provided: * * TRC_START: Starts the tracing directly. In snapshot mode this allows for * starting the trace at any point in your code, assuming xTraceInitialize() * has been called in the startup. Can also be used for streaming without * Tracealyzer control, e.g. to a local flash file system (assuming such a * "stream port", see trcStreamPort.h). * * TRC_START_AWAIT_HOST: For streaming mode only. Initializes the trace recorder * if necessary and waits for a Start command from Tracealyzer ("Start Recording" * button). This call is intentionally blocking! By calling xTraceEnable with * this option from the startup code, you start tracing at this point and capture * the early events. * * TRC_START_FROM_HOST: For streaming mode only. Initializes the trace recorder * if necessary and creates a task that waits for a Start command from * Tracealyzer ("Start Recording" button). This call is not blocking. * * @example Usage examples * * Snapshot trace, from startup: * * xTraceEnable(TRC_START); // Will call xTraceInitialize() * * * Snapshot trace, from a later point: * * xTraceInitialize(); * * ... * xTraceEnable(TRC_START); // e.g., in task context, at some relevant event * * Streaming trace, from startup (can only be used with certain stream ports): * * xTraceInitialize(); * * xTraceEnable(TRC_START); * * Streaming trace, from startup: * * xTraceEnable(TRC_START_AWAIT_HOST); // Blocks! * * * Streaming trace, from a later point: * * xTraceInitialize(); * * xTraceEnable(TRC_START); * * Streaming trace, system executes normally until host starts tracing: * * xTraceInitialize(); * * xTraceEnable(TRC_START_FROM_HOST) * * @param[in] uiStartOption Start option. * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceEnable( uint32_t uiStartOption ); /** * @brief Disables tracing. * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceDisable( void ); /** * @brief * * For snapshot mode only: Sets the "filter group" to assign when creating * RTOS objects, such as tasks, queues, semaphores and mutexes. This together * with vTraceSetFilterMask allows you to control what events that are recorded, * based on the objects they refer to. * * There are 16 filter groups named FilterGroup0 .. FilterGroup15. * * Note: We don't recommend filtering out the Idle task, so make sure to call * vTraceSetFilterGroup just before initializing the RTOS, in order to assign * such "default" objects to the right Filter Group (typically group 0). * * Example: * * // Assign tasks T1 to FilterGroup0 (default) * * * // Assign Q1 and Q2 to FilterGroup1 * vTraceSetFilterGroup(FilterGroup1); * * * * // Assigns Q3 to FilterGroup2 * vTraceSetFilterGroup(FilterGroup2); * * * // Only include FilterGroup0 and FilterGroup2, exclude FilterGroup1 (Q1 and Q2) from the trace * vTraceSetFilterMask( FilterGroup0 | FilterGroup2 ); * * // Assign the default RTOS objects (e.g. Idle task) to FilterGroup0 * vTraceSetFilterGroup(FilterGroup0); * * * Note that you may define your own names for the filter groups using * preprocessor definitions, to make the code easier to understand. * * Example: * * #define BASE FilterGroup0 * #define USB_EVENTS FilterGroup1 * #define CAN_EVENTS FilterGroup2 * * Note that filtering per event type (regardless of object) is also available * in trcKernelPortConfig.h for certain kernels. * * @param[in] filterGroup Filter group */ void vTraceSetFilterGroup( uint16_t filterGroup ); /** * @brief * * For snapshot mode only: Sets the "filter mask" that is used to filter * the events by object. This can be used to reduce the trace data rate, i.e., * if your streaming interface is a bottleneck or if you want longer snapshot * traces without increasing the buffer size. * * Note: There are two kinds of filters in the recorder. The other filter type * excludes all events of certain kinds (e.g., OS ticks). See trcConfig.h. * * The filtering is based on bitwise AND with the Filter Group ID, assigned * to RTOS objects such as tasks, queues, semaphores and mutexes. * This together with vTraceSetFilterGroup allows you to control what * events that are recorded, based on the objects they refer to. * * See example for vTraceSetFilterGroup. * * @param[in] filterMask Filter mask */ void vTraceSetFilterMask( uint16_t filterMask ); #if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT ) #include /** * @brief Returns lower 16 bits of a value * * @param[in] value The starting value */ #define TRACE_GET_LOW16( value ) ( ( uint16_t ) ( ( value ) & 0x0000FFFF ) ) /** * @brief Returns upper 16 bits * * @param[in] value The starting value */ #define TRACE_GET_HIGH16( value ) ( ( uint16_t ) ( ( ( value ) >> 16 ) & 0x0000FFFF ) ) /** * @brief Sets lower 16 bits * * @param[in] current The starting value * @param[in] value The value to set */ #define TRACE_SET_LOW16( current, value ) ( ( ( current ) & 0xFFFF0000 ) | ( value ) ) /** * @brief Sets upper 16 bits * * @param[in] current The starting value * @param[in] value The value to set */ #define TRACE_SET_HIGH16( current, value ) ( ( ( current ) & 0x0000FFFF ) | ( ( ( uint32_t ) ( value ) ) << 16 ) ) #if defined( TRC_CFG_ENABLE_STACK_MONITOR ) && ( TRC_CFG_ENABLE_STACK_MONITOR == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) /** * @brief Adds a task to the stack monitor * * @param[in] task The task */ void prvAddTaskToStackMonitor( void * task ); /** * @brief Remove a task from the stack monitor * * @param[in] task The task */ void prvRemoveTaskFromStackMonitor( void * task ); /** * @brief Reports on the current stack usage */ void prvReportStackUsage( void ); #else /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ #define prvAddTaskToStackMonitor( task ) #define prvRemoveTaskFromStackMonitor( task ) #define prvReportStackUsage() #endif /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ /** * @brief Query if recorder is enabled * * @retval 1 if recorder is enabled * @retval 0 if recorder is disabled */ uint32_t xTraceIsRecorderEnabled( void ); /** * @brief * * @retval 1 if recorder is initialized * @retval 0 if recorder isn't initialized */ uint32_t xTraceIsRecorderInitialized( void ); /** * @brief * * Creates an event that ends the current task instance at this very instant. * This makes the viewer to splits the current fragment at this point and begin * a new actor instance, even if no task-switch has occurred. * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceTaskInstanceFinishedNow( void ); /** * @brief * * Marks the current "task instance" as finished on the next kernel call. * * If that kernel call is blocking, the instance ends after the blocking event * and the corresponding return event is then the start of the next instance. * If the kernel call is not blocking, the viewer instead splits the current * fragment right before the kernel call, which makes this call the first event * of the next instance. * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceTaskInstanceFinishedNext( void ); /** * @brief Registers a string and returns a handle that can be used when tracing * * @param[in] label Label * @param[out] pxString String handle * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceStringRegister( const char * label, TraceStringHandle_t * pxString ); /** * @brief Registers a string and returns a handle that can be used when tracing * * @deprecated Backwards compatibility * * @param[in] name Name. * * @return TraceStringHandle_t String handle */ TraceStringHandle_t xTraceRegisterString( const char * name ); #if ( TRC_CFG_SCHEDULING_ONLY == 0 ) && ( TRC_CFG_INCLUDE_USER_EVENTS == 1 ) /** * @brief * * Generates "User Events", with formatted text and data, similar to a "printf". * User Events can be used for very efficient logging from your application code. * It is very fast since the actual string formatting is done on the host side, * when the trace is displayed. The execution time is just some microseconds on * a 32-bit MCU. * * User Events are shown as yellow labels in the main trace view of $PNAME. * * An advantage of User Events is that data can be plotted in the "User Event * Signal Plot" view, visualizing any data you log as User Events, discrete * states or control system signals (e.g. system inputs or outputs). * * You may group User Events into User Event Channels. The yellow User Event * labels show the logged string, preceded by the channel name within brackets. * * Example: * * "[MyChannel] Hello World!" * * The User Event Channels are shown in the View Filter, which makes it easy to * select what User Events you wish to display. User Event Channels are created * using xTraceStringRegister(). * * Example: * * TraceStringHandle_t adc_uechannel; * xTraceStringRegister("ADC User Events", &adc_uechannel); * ... * xTracePrintF(adc_uechannel, * "ADC channel %d: %d volts", * ch, adc_reading); * * The following format specifiers are supported in both modes: * %d - signed integer. * %u - unsigned integer. * %X - hexadecimal, uppercase. * %x - hexadecimal, lowercase. * %s - string (see comment below) * * For integer formats (%d, %u, %x, %X) you may also use width and padding. * If using -42 as data argument, two examples are: * "%05d" -> "-0042" * "%5d" -> " -42". * * String arguments are supported in both snapshot and streaming, but in streaming * mode you need to use xTraceStringRegister and use the returned TraceStringHandle_t as * the argument. In snapshot you simply provide a char* as argument. * * Snapshot: xTracePrintF(myChn, "my string: %s", str); * Streaming: xTracePrintF(myChn, "my string: %s", strTraceString); * * In snapshot mode you can specify 8-bit or 16-bit arguments to reduce RAM usage: * %hd -> 16 bit (h) signed integer (d). * %bu -> 8 bit (b) unsigned integer (u). * * However, in streaming mode all data arguments are assumed to be 32 bit wide. * Width specifiers (e.g. %hd) are accepted but ignored (%hd treated like %d). * * The maximum event size also differs between the modes. In streaming this is * limited by a maximum payload size of 52 bytes, including format string and * data arguments. So if using one data argument, the format string is limited * to 48 byte, etc. If this is exceeded, the format string is truncated and you * get a warning in Tracealyzer. * * In snapshot mode you are limited to maximum 15 arguments, that must not exceed * 32 bytes in total (not counting the format string). If exceeded, the recorder * logs an internal error (displayed when opening the trace) and stops recording. * * @param[in] chn Channel. * @param[in] fmt Formatting. * @param[in] ... * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTracePrintF( TraceStringHandle_t chn, const char * fmt, ... ); #else #define xTracePrintF( chn, fmt, ... ) ( ( void ) ( chn ), ( void ) ( fmt ), TRC_SUCCESS ) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ #endif #if ( TRC_CFG_SCHEDULING_ONLY == 0 ) && ( TRC_CFG_INCLUDE_USER_EVENTS == 1 ) /** * @brief * * xTracePrintF variant that accepts a va_list. * See xTracePrintF documentation for further details. * * @param[in] eventLabel * @param[in] formatStr * @param[in] vl * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceVPrintF( TraceStringHandle_t eventLabel, const char * formatStr, va_list vl ); #else #define xTraceVPrintF( chn, formatStr, vl ) ( ( void ) ( chn ), ( void ) ( formatStr ), ( void ) ( vl ), TRC_SUCCESS ) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ #endif #if ( TRC_CFG_SCHEDULING_ONLY == 0 ) && ( TRC_CFG_INCLUDE_USER_EVENTS == 1 ) /** * @brief A faster version of xTracePrintF, that only allows for logging a string. * * Example: * * TraceStringHandle_t chn; * xTraceStringRegister("MyChannel", &chn); * ... * xTracePrint(chn, "Hello World!"); * * @param[in] chn Channel. * @param[in] str String. * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTracePrint( TraceStringHandle_t chn, const char * str ); #else #define xTracePrint( chn, str ) ( ( void ) ( chn ), ( void ) ( str ), TRC_SUCCESS ) #endif /******************************************************************************/ /*** Extended API for Snapshot mode *******************************************/ /******************************************************************************/ /** * @brief Trace stop callback type. */ typedef void (* TRACE_STOP_HOOK)( void ); /** * @brief Sets a function to be called when the recorder is stopped. * * @note Snapshot mode only! * * @param[in] stopHookFunction */ void vTraceSetStopHook( TRACE_STOP_HOOK stopHookFunction ); /** * @brief * * Resets the recorder. * * Only necessary if a restart is desired - this is not * needed in the startup initialization. * * @note Snapshot mode only! */ void vTraceClear( void ); /*****************************************************************************/ /*** INTERNAL SNAPSHOT FUNCTIONS *********************************************/ /*****************************************************************************/ #define TRC_UNUSED #ifndef TRC_CFG_INCLUDE_OBJECT_DELETE #define TRC_CFG_INCLUDE_OBJECT_DELETE 0 #endif #ifndef TRC_CFG_INCLUDE_READY_EVENTS #define TRC_CFG_INCLUDE_READY_EVENTS 1 #endif #ifndef TRC_CFG_INCLUDE_OSTICK_EVENTS #define TRC_CFG_INCLUDE_OSTICK_EVENTS 0 #endif /* This macro will create a task in the object table */ #undef trcKERNEL_HOOKS_TASK_CREATE #define trcKERNEL_HOOKS_TASK_CREATE( SERVICE, CLASS, pxTCB ) \ if( ( pxTCB ) != 0 ) \ { \ TRACE_SET_OBJECT_NUMBER( TASK, pxTCB ); \ TRACE_SET_OBJECT_FILTER( TASK, pxTCB, CurrentFilterGroup ); \ prvTraceSetObjectName( TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ), TRACE_GET_TASK_NAME( pxTCB ) ); \ prvTraceSetPriorityProperty( TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ), TRACE_GET_TASK_PRIORITY( pxTCB ) ); \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ) ); \ } \ else \ { \ /* pxTCB is null */ \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ { \ prvTraceStoreKernelCall( SERVICE, TRACE_CLASS_TASK, 0 ); \ } \ } /* This macro will remove the task and store it in the event buffer */ #undef trcKERNEL_HOOKS_TASK_DELETE #define trcKERNEL_HOOKS_TASK_DELETE( SERVICE, SERVICE_NAME, SERVICE_PROP, pxTCB ) \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ) ); \ prvTraceStoreObjectNameOnCloseEvent( SERVICE_NAME, TRACE_GET_TASK_NUMBER( pxTCB ), TRACE_CLASS_TASK ); \ prvTraceStoreObjectPropertiesOnCloseEvent( SERVICE_PROP, TRACE_GET_TASK_NUMBER( pxTCB ), TRACE_CLASS_TASK ); \ prvTraceSetPriorityProperty( TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ), TRACE_GET_TASK_PRIORITY( pxTCB ) ); \ prvTraceSetObjectState( TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ), TASK_STATE_INSTANCE_NOT_ACTIVE ); \ prvTraceFreeObjectHandle( TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ) ); /* This macro will setup a task in the object table */ #undef trcKERNEL_HOOKS_OBJECT_CREATE #define trcKERNEL_HOOKS_OBJECT_CREATE( SERVICE, CLASS, pxObject ) \ TRACE_SET_OBJECT_NUMBER( CLASS, pxObject ); \ TRACE_SET_OBJECT_FILTER( CLASS, pxObject, CurrentFilterGroup ); \ prvMarkObjectAsUsed( TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ) ); \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ if( TRACE_GET_OBJECT_FILTER( CLASS, pxObject ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ) ); \ prvTraceSetObjectState( TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ), 0 ); /* This macro will setup a task in the object table */ #undef trcKERNEL_HOOKS_OBJECT_CREATE_FAILED #define trcKERNEL_HOOKS_OBJECT_CREATE_FAILED( SERVICE, TRACE_CLASS ) \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ { \ prvTraceStoreKernelCall( SERVICE, TRACE_CLASS, 0 ); \ } /* This macro will remove the object and store it in the event buffer */ #undef trcKERNEL_HOOKS_OBJECT_DELETE #define trcKERNEL_HOOKS_OBJECT_DELETE( SERVICE, SERVICE_NAME, SERVICE_PROP, CLASS, pxObject ) \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ if( TRACE_GET_OBJECT_FILTER( CLASS, pxObject ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ) ); \ prvTraceStoreObjectNameOnCloseEvent( SERVICE_NAME, TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ), TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ) ); \ prvTraceStoreObjectPropertiesOnCloseEvent( SERVICE_PROP, TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ), TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ) ); \ prvTraceFreeObjectHandle( TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ) ); /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE #define trcKERNEL_HOOKS_KERNEL_SERVICE( SERVICE, CLASS, pxObject ) \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ if( TRACE_GET_OBJECT_FILTER( CLASS, pxObject ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ) ); /* This macro will create a call to a kernel service with a certain result, with a null object as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT( SERVICE, TRACECLASS ) \ if( TRACE_GET_TASK_FILTER( TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACECLASS, 0 ); /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM( SERVICE, CLASS, pxObject, param ) \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ if( TRACE_GET_OBJECT_FILTER( CLASS, pxObject ) & CurrentFilterMask ) \ prvTraceStoreKernelCallWithParam( SERVICE, TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ), ( uint32_t ) param ); /* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM( SERVICE, TRACECLASS, param ) \ if( TRACE_GET_TASK_FILTER( TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ prvTraceStoreKernelCallWithParam( SERVICE, TRACECLASS, 0, param ); /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY( SERVICE, param ) \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ prvTraceStoreKernelCallWithNumericParamOnly( SERVICE, ( uint32_t ) param ); /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR #define trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR( SERVICE, CLASS, pxObject ) \ if( TRACE_GET_OBJECT_FILTER( CLASS, pxObject ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ) ); /* This macro will create a call to a kernel service with a certain result, with a null object as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_FROM_ISR #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_FROM_ISR( SERVICE, TRACECLASS ) \ prvTraceStoreKernelCall( SERVICE, TRACECLASS, 0 ); /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR( SERVICE, CLASS, pxObject, param ) \ if( TRACE_GET_OBJECT_FILTER( CLASS, pxObject ) & CurrentFilterMask ) \ prvTraceStoreKernelCallWithParam( SERVICE, TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ), ( uint32_t ) param ); /* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM_FROM_ISR #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM_FROM_ISR( SERVICE, TRACECLASS, param ) \ prvTraceStoreKernelCallWithParam( SERVICE, TRACECLASS, 0, param ); /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR( SERVICE, param ) \ prvTraceStoreKernelCallWithNumericParamOnly( SERVICE, ( uint32_t ) param ); /* This macro will set the state for an object */ #undef trcKERNEL_HOOKS_SET_OBJECT_STATE #define trcKERNEL_HOOKS_SET_OBJECT_STATE( CLASS, pxObject, STATE ) \ prvTraceSetObjectState( TRACE_GET_OBJECT_TRACE_CLASS( CLASS, pxObject ), TRACE_GET_OBJECT_NUMBER( CLASS, pxObject ), ( uint8_t ) STATE ); /* This macro will flag a certain task as a finished instance */ #undef trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED #define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED() \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ prvTraceSetTaskInstanceFinished( TRACE_GET_TASK_NUMBER( TRACE_GET_CURRENT_TASK() ) ); #if ( TRC_CFG_INCLUDE_READY_EVENTS == 1 ) /* This macro will create an event to indicate that a task became Ready */ #undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE #define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE( pxTCB ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ prvTraceStoreTaskReady( TRACE_GET_TASK_NUMBER( pxTCB ) ); #else /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/ #undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE #define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE( pxTCB ) #endif /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/ /* This macro will update the internal tick counter and call prvTracePortGetTimeStamp(0) to update the internal counters */ #undef trcKERNEL_HOOKS_INCREMENT_TICK #define trcKERNEL_HOOKS_INCREMENT_TICK() \ { \ extern uint32_t uiTraceTickCount; \ uiTraceTickCount++; \ prvTracePortGetTimeStamp( 0 ); \ } #if ( TRC_CFG_INCLUDE_OSTICK_EVENTS == 1 ) /* This macro will create an event indicating that the OS tick count has increased */ #undef trcKERNEL_HOOKS_NEW_TIME #define trcKERNEL_HOOKS_NEW_TIME( SERVICE, xValue ) \ prvTraceStoreKernelCallWithNumericParamOnly( SERVICE, xValue ); #else /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/ #undef trcKERNEL_HOOKS_NEW_TIME #define trcKERNEL_HOOKS_NEW_TIME( SERVICE, xValue ) #endif /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/ /* This macro will create a task switch event to the currently executing task */ #undef trcKERNEL_HOOKS_TASK_SWITCH #define trcKERNEL_HOOKS_TASK_SWITCH( pxTCB ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ prvTraceStoreTaskswitch( TRACE_GET_TASK_NUMBER( pxTCB ) ); /* This macro will create an event to indicate that the task has been suspended */ #undef trcKERNEL_HOOKS_TASK_SUSPEND #define trcKERNEL_HOOKS_TASK_SUSPEND( SERVICE, pxTCB ) \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ) ); \ prvTraceSetTaskInstanceFinished( ( uint8_t ) TRACE_GET_TASK_NUMBER( pxTCB ) ); /* This macro will create an event to indicate that a task has called a wait/delay function */ #undef trcKERNEL_HOOKS_TASK_DELAY #define trcKERNEL_HOOKS_TASK_DELAY( SERVICE, pxTCB, xValue ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ { \ prvTraceStoreKernelCallWithNumericParamOnly( SERVICE, xValue ); \ prvTraceSetTaskInstanceFinished( ( uint8_t ) TRACE_GET_TASK_NUMBER( pxTCB ) ); \ } /* This macro will create an event to indicate that a task has gotten its priority changed */ #undef trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE #define trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE( SERVICE, pxTCB, uxNewPriority ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ { \ prvTraceStoreKernelCallWithParam( SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ), prvTraceGetPriorityProperty( TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ) ) ); \ prvTraceSetPriorityProperty( TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ), ( uint8_t ) uxNewPriority ); \ } /* This macro will create an event to indicate that the task has been resumed */ #undef trcKERNEL_HOOKS_TASK_RESUME #define trcKERNEL_HOOKS_TASK_RESUME( SERVICE, pxTCB ) \ if( TRACE_GET_OBJECT_FILTER( TASK, TRACE_GET_CURRENT_TASK() ) & CurrentFilterMask ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ) ); /* This macro will create an event to indicate that the task has been resumed from ISR */ #undef trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR #define trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR( SERVICE, pxTCB ) \ if( TRACE_GET_OBJECT_FILTER( TASK, pxTCB ) & CurrentFilterMask ) \ prvTraceStoreKernelCall( SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER( pxTCB ) ); #if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1 /** * @brief Dynamically enables ready events * * @param[in] flag Flag */ void prvTraceSetReadyEventsEnabled( uint32_t flag ); /** * @brief Stores a Task Ready event * * @param[in] handle Task handle */ void prvTraceStoreTaskReady( traceHandle handle ); #else #define prvTraceSetReadyEventsEnabled( status ) ( void ) status; #endif /** * @brief Stores a Low Power mode event * * @param[in] flag Flag */ void prvTraceStoreLowPower( uint32_t flag ); /** * @brief Stores a Task Switch event * * @param[in] task_handle Task */ void prvTraceStoreTaskswitch( traceHandle task_handle ); #if ( TRC_CFG_SCHEDULING_ONLY == 0 ) /** * @brief Stores a Kernel Service call event with an Object handle parameter * * @param[in] eventcode Event code * @param[in] objectClass Object class * @param[in] objectNumber Object handle */ void prvTraceStoreKernelCall( uint32_t eventcode, traceObjectClass objectClass, uint32_t objectNumber ); /** * @brief Stores a Kernel Service call event with only a numeric parameter * * @param[in] evtcode Event code * @param[in] param Parameter */ void prvTraceStoreKernelCallWithNumericParamOnly( uint32_t evtcode, uint32_t param ); /** * @brief Stores a Kernel Service call event with an Object handle and a numeric parameter * * @param[in] evtcode Event code * @param[in] objectClass Object class * @param[in] objectNumber Object handle * @param[in] param Parameter */ void prvTraceStoreKernelCallWithParam( uint32_t evtcode, traceObjectClass objectClass, uint32_t objectNumber, uint32_t param ); #else /* if ( TRC_CFG_SCHEDULING_ONLY == 0 ) */ #define prvTraceStoreKernelCall( eventcode, objectClass, byteParam ) {} #define prvTraceStoreKernelCallWithNumericParamOnly( evtcode, param ) {} #define prvTraceStoreKernelCallWithParam( evtcode, objectClass, objectNumber, param ) {} #endif /* if ( TRC_CFG_SCHEDULING_ONLY == 0 ) */ /** * @brief Flags a task instance as finished * * @param[in] handle Task handle */ void prvTraceSetTaskInstanceFinished( traceHandle handle ); /** * @brief Set priority * * @param[in] objectclass Object class * @param[in] id Object handle * @param[in] value Value */ void prvTraceSetPriorityProperty( uint8_t objectclass, traceHandle id, uint8_t value ); /** * @brief Get priority * * @param[in] objectclass Object class * @param[in] id Object handle * * @return uint8_t Value */ uint8_t prvTraceGetPriorityProperty( uint8_t objectclass, traceHandle id ); /** * @brief Set object state * * @param[in] objectclass Object class * @param[in] id Object handle * @param[in] value Value */ void prvTraceSetObjectState( uint8_t objectclass, traceHandle id, uint8_t value ); /** * @brief Mark object as used * * @param[in] objectclass Object class * @param[in] handle Object handle */ void prvMarkObjectAsUsed( traceObjectClass objectclass, traceHandle handle ); /** * @brief Stores the name of an object because it is being deleted * * @param[in] evtcode Event code * @param[in] handle Object handle * @param[in] objectclass Object class */ void prvTraceStoreObjectNameOnCloseEvent( uint8_t evtcode, traceHandle handle, traceObjectClass objectclass ); /** * @brief Stores the property of an object because it is being deleted * * @param[in] evtcode Event code * @param[in] handle Object handle * @param[in] objectclass Object class */ void prvTraceStoreObjectPropertiesOnCloseEvent( uint8_t evtcode, traceHandle handle, traceObjectClass objectclass ); /* Internal constants for task state */ #define TASK_STATE_INSTANCE_NOT_ACTIVE 0 #define TASK_STATE_INSTANCE_ACTIVE 1 #if ( TRC_CFG_INCLUDE_ISR_TRACING == 0 ) #undef vTraceSetISRProperties #define vTraceSetISRProperties( handle, name, priority ) ( void ) ( handle ), ( void ) ( name ), ( void ) ( priority ) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ #undef vTraceStoreISRBegin #define vTraceStoreISRBegin( x ) ( void ) ( x ) #undef vTraceStoreISREnd #define vTraceStoreISREnd( x ) ( void ) ( x ) #undef xTraceSetISRProperties #define xTraceSetISRProperties( name, priority ) ( ( void ) ( name ), ( void ) ( priority ), ( traceHandle ) 0 ) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ #endif /*(TRC_CFG_INCLUDE_ISR_TRACING == 0)*/ /** * @brief * * Returns a pointer to the recorder data structure. Use this together with * uiTraceGetTraceBufferSize if you wish to implement an own store/upload * solution, e.g., in case a debugger connection is not available for uploading * the data. * * @return void* Buffer pointer */ void * xTraceGetTraceBuffer( void ); /** * @brief * * Gets the size of the recorder data structure. For use together with * xTraceGetTraceBuffer if you wish to implement an own store/upload solution, * e.g., in case a debugger connection is not available for uploading the data. * * @return uint32_t Buffer size */ uint32_t uiTraceGetTraceBufferSize( void ); #if ( TRC_CFG_SCHEDULING_ONLY == 1 ) #undef TRC_CFG_INCLUDE_USER_EVENTS #define TRC_CFG_INCLUDE_USER_EVENTS 0 #endif /*(TRC_CFG_SCHEDULING_ONLY == 1)*/ #if ( ( TRC_CFG_INCLUDE_USER_EVENTS == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) ) && ( TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1 ) /** * @brief Register a channel and fixed format string for use with the separate User Event Buffer functions * * @param[in] channel Channel name handle * @param[in] formatStr Format string that will be used for all events on this channel * * @return traceUBChannel Channel handle */ traceUBChannel xTraceRegisterUBChannel( TraceStringHandle_t channel, TraceStringHandle_t formatStr ); /** * @brief Creates a User Event using the channel, previously set format string and data parameters * * @param[in] channel Channel * @param[in] ... */ void vTraceUBData( traceUBChannel channel, ... ); /** * @brief Creates a User Event using the channel and previously set string * * @param[in] channel Channel */ void vTraceUBEvent( traceUBChannel channel ); #else /* if ( ( TRC_CFG_INCLUDE_USER_EVENTS == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) ) && ( TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1 ) */ #define xTraceRegisterChannelFormat( eventLabel, formatStr ) ( ( void ) ( eventLabel ), ( void ) ( formatStr ), 0 ) #define vTraceUBData( label, ... ) ( void ) ( label ) #endif /*(TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)*/ #define NEventCodes 0x100 /* Our local critical sections for the recorder */ #define trcCRITICAL_SECTION_BEGIN() { TRACE_ENTER_CRITICAL_SECTION(); recorder_busy++; } #define trcCRITICAL_SECTION_END() { recorder_busy--; TRACE_EXIT_CRITICAL_SECTION(); } #if ( TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M ) #define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY TRACE_ALLOC_CRITICAL_SECTION #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END #else #define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY() {} #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++; #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--; #endif /** * @brief Object handle stack struct. * * This data-structure is used to provide a mechanism for 1-byte trace object * handles. This way, only 1 byte is necessary instead of 4 bytes (a pointer) * when storing a reference to an object. This allows for up to 255 objects of * each object class active at any given moment. There can be more "historic" * objects, that have been deleted - that number is only limited by the size of * the symbol table. * * Note that handle zero (0) is not used, it is a code for an invalid handle. * * This data structure keeps track of the FREE handles, not the handles in use. * This data structure contains one stack per object class. When a handle is * allocated to an object, the next free handle is popped from the stack. When * a handle is released (on object delete), it is pushed back on the stack. * Note that there is no initialization code that pushed the free handles * initially, that is not necessary due to the following optimization: * * The stack of handles (objectHandles) is initially all zeros. Since zero * is not a valid handle, that is a signal of additional handles needed. * If a zero is received when popping a new handle, it is replaced by the * index of the popped handle instead. */ typedef struct { uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ]; /**< For each object class, the index of the next handle to allocate */ uint16_t lowestIndexOfClass[ TRACE_NCLASSES ]; /**< The lowest index of this class (constant) */ uint16_t highestIndexOfClass[ TRACE_NCLASSES ]; /**< The highest index of this class (constant) */ uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ]; /**< The highest use count for this class (for statistics) */ traceHandle objectHandles[ TRACE_KERNEL_OBJECT_COUNT ]; /**< The free object handles - a set of stacks within this array */ } objectHandleStackType; extern objectHandleStackType objectHandleStacks; /** * @brief Object property table struct * * The Object Table contains name and other properties of the objects (tasks, * queues, mutexes, etc). The below data structures defines the properties of * each object class and are used to cast the byte buffer into a cleaner format. * * The values in the object table are continuously overwritten and always * represent the current state. If a property is changed during runtime, the OLD * value should be stored in the trace buffer, not the new value (since the new * value is found in the Object Property Table). * * For close events this mechanism is the old names are stored in the symbol * table), for "priority set" (the old priority is stored in the event data) * and for "isActive", where the value decides if the task switch event type * should be "new" or "resume". */ typedef struct { /* = NCLASSES */ uint32_t NumberOfObjectClasses; /**< */ uint32_t ObjectPropertyTableSizeInBytes; /**< */ /* This is used to calculate the index in the dynamic object table * (handle - 1 - nofStaticObjects = index)*/ #if ( TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1 ) traceHandle NumberOfObjectsPerClass[ 2 * ( ( TRACE_NCLASSES + 1 ) / 2 ) ]; /** */ #else traceHandle NumberOfObjectsPerClass[ 4 * ( ( TRACE_NCLASSES + 3 ) / 4 ) ]; /** */ #endif /* Allocation size rounded up to the closest multiple of 4 */ uint8_t NameLengthPerClass[ 4 * ( ( TRACE_NCLASSES + 3 ) / 4 ) ]; /**< */ /* Allocation size rounded up to the closest multiple of 2 */ uint8_t TotalPropertyBytesPerClass[ 4 * ( ( TRACE_NCLASSES + 3 ) / 4 ) ]; /**< */ /* */ uint16_t StartIndexOfClass[ 2 * ( ( TRACE_NCLASSES + 1 ) / 2 ) ]; /**< */ /* The actual handles issued, should be Initiated to all zeros */ uint8_t objbytes[ 4 * ( ( TRACE_OBJECT_TABLE_SIZE + 3 ) / 4 ) ]; /**< */ } ObjectPropertyTableType; /** * @brief Symbol table structure */ typedef struct { /* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */ uint32_t symTableSize; /**< */ /* Entry 0 is reserved. Any reference to entry 0 implies NULL*/ uint32_t nextFreeSymbolIndex; /**< */ /* Size rounded up to closest multiple of 4, to avoid alignment issues*/ uint8_t symbytes[ 4 * ( ( ( TRC_CFG_SYMBOL_TABLE_SIZE ) + 3 ) / 4 ) ]; /**< */ /* Used for lookups - Up to 64 linked lists within the symbol table * connecting all entries with the same 6 bit checksum. * This field holds the current list heads. Should be initiated to zeros */ uint16_t latestEntryOfChecksum[ 64 ]; /**< */ } symbolTableType; /******************************************************************************* * The data structures of the different events, all 4 bytes long ******************************************************************************/ typedef struct { uint8_t type; uint8_t objHandle; uint16_t dts; /* differential timestamp - time since last event */ } TSEvent, TREvent; typedef struct { uint8_t type; uint8_t dummy; uint16_t dts; /* differential timestamp - time since last event */ } LPEvent; typedef struct { uint8_t type; uint8_t objHandle; uint16_t dts; /* differential timestamp - time since last event */ } KernelCall; typedef struct { uint8_t type; uint8_t objHandle; uint8_t param; uint8_t dts; /* differential timestamp - time since last event */ } KernelCallWithParamAndHandle; typedef struct { uint8_t type; uint8_t dts; /* differential timestamp - time since last event */ uint16_t param; } KernelCallWithParam16; typedef struct { uint8_t type; uint8_t objHandle; /* the handle of the closed object */ uint16_t symbolIndex; /* the name of the closed object */ } ObjCloseNameEvent; typedef struct { uint8_t type; uint8_t arg1; uint8_t arg2; uint8_t arg3; } ObjClosePropEvent; typedef struct { uint8_t type; uint8_t unused1; uint8_t unused2; uint8_t dts; } TaskInstanceStatusEvent; typedef struct { uint8_t type; uint8_t dts; uint16_t payload; /* the name of the user event */ } UserEvent; typedef struct { uint8_t type; /* 8 bits extra for storing DTS, if it does not fit in ordinary event * (this one is always MSB if used) */ uint8_t xts_8; /* 16 bits extra for storing DTS, if it does not fit in ordinary event. */ uint16_t xts_16; } XTSEvent; typedef struct { uint8_t type; uint8_t xps_8; uint16_t xps_16; } XPSEvent; typedef struct { uint8_t type; uint8_t dts; uint16_t size; } MemEventSize; typedef struct { uint8_t type; uint8_t addr_high; uint16_t addr_low; } MemEventAddr; /******************************************************************************* * The separate user event buffer structure. Can be enabled in trcConfig.h. ******************************************************************************/ #if ( TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1 ) typedef struct { TraceStringHandle_t name; TraceStringHandle_t defaultFormat; } ChannelFormatPair; typedef struct { uint16_t bufferID; uint16_t version; uint32_t wraparoundCounter; uint32_t numberOfSlots; uint32_t nextSlotToWrite; uint8_t numberOfChannels; uint8_t padding1; uint8_t padding2; uint8_t padding3; ChannelFormatPair channels[ ( TRC_CFG_UB_CHANNELS ) + 1 ]; uint8_t channelBuffer[ ( ( TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE ) + 3 ) & 0xFFFFFFFC ]; /* 1 byte per slot, with padding for 4 byte alignment */ uint8_t dataBuffer[ ( TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE ) * 4 ]; /* 4 bytes per slot */ } UserEventBuffer; #endif /* (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) */ /******************************************************************************* * The main data structure, read by Tracealyzer from the RAM dump ******************************************************************************/ typedef struct { volatile uint8_t startmarker0; /* Volatile is important, see init code. */ volatile uint8_t startmarker1; volatile uint8_t startmarker2; volatile uint8_t startmarker3; volatile uint8_t startmarker4; volatile uint8_t startmarker5; volatile uint8_t startmarker6; volatile uint8_t startmarker7; volatile uint8_t startmarker8; volatile uint8_t startmarker9; volatile uint8_t startmarker10; volatile uint8_t startmarker11; /* Used to determine Kernel and Endianess */ uint16_t version; /* Currently 7 */ uint8_t minor_version; /* This should be 0 if lower IRQ priority values implies higher priority * levels, such as on ARM Cortex M. If the opposite scheme is used, i.e., * if higher IRQ priority values means higher priority, this should be 1. */ uint8_t irq_priority_order; /* sizeof(RecorderDataType) - just for control */ uint32_t filesize; /* Current number of events recorded */ uint32_t numEvents; /* The buffer size, in number of event records */ uint32_t maxEvents; /* The event buffer index, where to write the next event */ uint32_t nextFreeIndex; /* 1 if the buffer is full, 0 otherwise */ uint32_t bufferIsFull; /* The frequency of the clock/timer/counter used as time base */ uint32_t frequency; /* The absolute timestamp of the last stored event, in the native * timebase, modulo frequency! */ uint32_t absTimeLastEvent; /* The number of seconds in total - lasts for 136 years */ uint32_t absTimeLastEventSecond; /* 1 if the recorder has been started, 0 if not yet started or stopped. * This is a 32 bit variable due to alignment issues. */ uint32_t recorderActive; /* If > 0, tells the maximum time between two traced ISRs that execute * back-to-back. If the time between vTraceStoreISREnd and a directly * following vTraceISRBegin is above isrTailchainingThreshold, we assume a * return to the previous context in between the ISRs, otherwise we assume * the have executed back-to-back and don't show any fragment of the previous * context in between. */ uint32_t isrTailchainingThreshold; /* The maximum amount of heap memory that was allocated */ uint32_t heapMemMaxUsage; /* The amount of heap memory used */ uint32_t heapMemUsage; /* 0xF0F0F0F0 - for control only */ int32_t debugMarker0; /* Set to value of TRC_CFG_USE_16BIT_OBJECT_HANDLES */ uint32_t isUsing16bitHandles; /* The Object Property Table holds information about currently active * tasks, queues, and other recorded objects. This is updated on each * create call and includes object name and other properties. */ ObjectPropertyTableType ObjectPropertyTable; /* 0xF1F1F1F1 - for control only */ int32_t debugMarker1; /* The Symbol Table stores strings for User Events and is also used to * store names of deleted objects, which still may be in the trace but no * longer are available. */ symbolTableType SymbolTable; /* For inclusion of float support, and for endian detection of floats. * The value should be (float)1 or (uint32_t)0 */ #if ( TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1 ) float exampleFloatEncoding; #else uint32_t exampleFloatEncoding; #endif /* This is non-zero if an internal error occurred in the recorder, e.g., if * one of the Nxxx constants was too small. The systemInfo string will then * contain an error message that is displayed when attempting to view the * trace file. */ uint32_t internalErrorOccurred; /* 0xF2F2F2F2 - for control only */ int32_t debugMarker2; /* Error messages from the recorder. */ char systemInfo[ 80 ]; /* 0xF3F3F3F3 - for control only */ int32_t debugMarker3; /* The event data, in 4-byte records */ uint8_t eventData[ ( TRC_CFG_EVENT_BUFFER_SIZE ) * 4 ]; #if ( TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1 ) UserEventBuffer userEventBuffer; #endif /* This should always be 0 */ uint32_t endOfSecondaryBlocks; uint8_t endmarker0; uint8_t endmarker1; uint8_t endmarker2; uint8_t endmarker3; uint8_t endmarker4; uint8_t endmarker5; uint8_t endmarker6; uint8_t endmarker7; uint8_t endmarker8; uint8_t endmarker9; uint8_t endmarker10; uint8_t endmarker11; } RecorderDataType; extern RecorderDataType * RecorderDataPtr; /* Internal functions */ /** * @brief Signals a trace error * * @param[in] msg Message */ void prvTraceError( const char * msg ); /** * @brief * * Returns the current time based on the HWTC macros which provide a hardware * isolation layer towards the hardware timer/counter. * * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue * or the trace recorder library. Typically you should not need to change * the code of prvTracePortGetTimeStamp if using the HWTC macros. * * @param[out] puiTimestamp Timestamp */ void prvTracePortGetTimeStamp( uint32_t * puiTimestamp ); /** * @brief Reserve an object handle * * @param[in] objectclass Object class * * @return traceHandle */ traceHandle prvTraceGetObjectHandle( traceObjectClass objectclass ); /** * @brief Free an object handle * * @param[in] objectclass Object class * @param[in] handle Handle */ void prvTraceFreeObjectHandle( traceObjectClass objectclass, traceHandle handle ); /* Private function. Use the public functions in trcKernelPort.h */ /** * @brief Set the object name * * @param[in] objectclass Object class * @param[in] handle Handle * @param[in] name Name */ void prvTraceSetObjectName( traceObjectClass objectclass, traceHandle handle, const char * name ); /* Internal macros */ #define TRACE_PROPERTY_NAME_GET( objectclass, objecthandle ) \ ( const char * ) ( &RecorderDataPtr->ObjectPropertyTable.objbytes \ [ uiIndexOfObject( objecthandle, objectclass ) ] ) #define TRACE_PROPERTY_OBJECT_STATE( objectclass, handle ) \ RecorderDataPtr->ObjectPropertyTable.objbytes[ uiIndexOfObject( handle, objectclass ) \ + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ] ] #define TRACE_PROPERTY_ACTOR_PRIORITY( objectclass, handle ) \ RecorderDataPtr->ObjectPropertyTable.objbytes[ uiIndexOfObject( handle, objectclass ) \ + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ] + 1 ] /* DEBUG ASSERTS */ #if defined TRC_CFG_USE_TRACE_ASSERT && TRC_CFG_USE_TRACE_ASSERT != 0 #define TRACE_ASSERT( eval, msg, defRetVal ) \ if( !( eval ) ) \ { \ prvTraceError( "TRACE_ASSERT: " msg ); \ return defRetVal; \ } #else #define TRACE_ASSERT( eval, msg, defRetVal ) #endif typedef RecorderDataType TraceRecorderDataBuffer_t; #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/ #if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING ) #ifndef TRC_EXTERNAL_BUFFERS #define TRC_EXTERNAL_BUFFERS 0 #endif typedef struct TraceRecorderData { uint32_t uiSessionCounter; uint32_t uiRecorderEnabled; uint32_t uiTraceSystemState; TraceAssertBuffer_t xAssertBuffer; #if ( TRC_EXTERNAL_BUFFERS == 0 ) TraceHeaderBuffer_t xHeaderBuffer; TraceEntryTableBuffer_t xEntryTableBuffer; TraceTimestampBuffer_t xTimestampBuffer; #endif TraceStreamPortBuffer_t xStreamPortBuffer; TraceStaticBufferBuffer_t xStaticBufferBuffer; TraceEventDataBuffer_t xEventDataBuffer; TracePrintBuffer_t xPrintBuffer; TraceErrorBuffer_t xErrorBuffer; TraceISRInfoBuffer_t xISRInfoBuffer; TraceKernelPortDataBuffer_t xKernelPortBuffer; TraceTaskInfoBuffer_t xTaskInfoBuffer; TraceStackMonitorBuffer_t xStackMonitorBuffer; TraceDiagnosticsBuffer_t xDiagnosticsBuffer; } TraceRecorderData_t; extern TraceRecorderData_t * pxTraceRecorderData; extern uint32_t RecorderInitialized; #define TRC_RECORDER_DATA_BUFFER_SIZE ( sizeof( TraceRecorderData_t ) ) typedef struct TraceRecorderDataBuffer { uint8_t buffer[ ( TRC_RECORDER_DATA_BUFFER_SIZE ) ]; } TraceRecorderDataBuffer_t; /** * @brief Initializes the header data * * @param[in] pxBuffer Pointer to header buffer * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceHeaderInitialize( TraceHeaderBuffer_t * pxBuffer ); /** * @brief Query if recorder is enabled * * @retval 1 Recorder enabled * @retval 0 Recorder not enabled */ #define xTraceIsRecorderEnabled() ( xTraceIsRecorderInitialized() & pxTraceRecorderData->uiRecorderEnabled ) /** * @brief Query if recorder initialized * * @retval 1 Recorder initialized * @retval 0 Recorder not initialized */ #define xTraceIsRecorderInitialized() xTraceIsComponentInitialized( TRC_RECORDER_COMPONENT_CORE ) /** * @brief Flag component as initialized * * @param[in] uiComponentBit Component bit * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ #define xTraceSetComponentInitialized( uiComponentBit ) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2( RecorderInitialized |= ( uiComponentBit ), TRC_SUCCESS ) /** * @brief Query if component is initialized * * @param[in] uiComponentBit Component bit * * @retval 1 Component initialized * @retval 0 Component not initialized */ #define xTraceIsComponentInitialized( uiComponentBit ) ( ( RecorderInitialized & ( uiComponentBit ) ) ? 1 : 0 ) /** * @brief Set the trace state * * @param[in] uiState State * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ #define xTraceStateSet( uiState ) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2( pxTraceRecorderData->uiTraceSystemState = ( uiState ), TRC_SUCCESS ) /** * @brief Query the trace state * * @param[out] puiState State * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ #define xTraceStateGet( puiState ) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2( *( puiState ) = pxTraceRecorderData->uiTraceSystemState, TRC_SUCCESS ) /** * @brief Call this function periodically * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceTzCtrl( void ); /******************************************************************************/ /*** INTERNAL STREAMING FUNCTIONS *********************************************/ /******************************************************************************/ /** * @brief Stores an event without parameters * * @param[in] _eventID Event id */ #define prvTraceStoreEvent_None( _eventID ) \ { \ TraceEventHandle_t _xEventHandle = 0; \ if( xTraceEventBegin( _eventID, 0, &_xEventHandle ) == TRC_SUCCESS ) \ { \ xTraceEventEnd( _xEventHandle ); \ } \ } /** * @brief Stores an event with a handle parameter * * @param[in] _eventID Event id * @param[in] _handle Handle */ #define prvTraceStoreEvent_Handle( _eventID, _handle ) \ { \ TraceEventHandle_t _xEventHandle = 0; \ if( xTraceEventBegin( _eventID, sizeof( void * ), &_xEventHandle ) == TRC_SUCCESS ) \ { \ xTraceEventAddPointer( _xEventHandle, ( void * ) ( _handle ) ); \ xTraceEventEnd( _xEventHandle ); \ } \ } /** * @brief Stores an event with one 32-bit parameter * * @param[in] _eventID Event id * @param[in] _param1 Param */ #define prvTraceStoreEvent_Param( _eventID, _param1 ) \ { \ TraceEventHandle_t _xEventHandle = 0; \ if( xTraceEventBegin( _eventID, sizeof( uint32_t ), &_xEventHandle ) == TRC_SUCCESS ) \ { \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param1 ) ); \ xTraceEventEnd( _xEventHandle ); \ } \ } /** * @brief Stores an event with a handle and one 32-bit parameter * * @param[in] _eventID Event id * @param[in] _handle Handle * @param[in] _param1 Param */ #define prvTraceStoreEvent_HandleParam( _eventID, _handle, _param1 ) \ { \ TraceEventHandle_t _xEventHandle = 0; \ if( xTraceEventBegin( _eventID, sizeof( void * ) + sizeof( uint32_t ), &_xEventHandle ) == TRC_SUCCESS ) \ { \ xTraceEventAddPointer( _xEventHandle, ( void * ) ( _handle ) ); \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param1 ) ); \ xTraceEventEnd( _xEventHandle ); \ } \ } /** * @brief Stores an event with two 32-bit parameters * * @param[in] _eventID Event id * @param[in] _param1 Param 1 * @param[in] _param2 Param 2 */ #define prvTraceStoreEvent_ParamParam( _eventID, _param1, _param2 ) \ { \ TraceEventHandle_t _xEventHandle = 0; \ if( xTraceEventBegin( _eventID, sizeof( uint32_t ) + sizeof( uint32_t ), &_xEventHandle ) == TRC_SUCCESS ) \ { \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param1 ) ); \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param2 ) ); \ xTraceEventEnd( _xEventHandle ); \ } \ } /** * @brief Stores an event with a handle and two 32-bit parameters * * @param[in] _eventID Event id * @param[in] _handle Handle * @param[in] _param1 Param 1 * @param[in] _param2 Param 2 */ #define prvTraceStoreEvent_HandleParamParam( _eventID, _handle, _param1, _param2 ) \ { \ TraceEventHandle_t _xEventHandle = 0; \ if( xTraceEventBegin( _eventID, sizeof( void * ) + sizeof( uint32_t ) + sizeof( uint32_t ), &_xEventHandle ) == TRC_SUCCESS ) \ { \ xTraceEventAddPointer( _xEventHandle, ( void * ) ( _handle ) ); \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param1 ) ); \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param2 ) ); \ xTraceEventEnd( _xEventHandle ); \ } \ } /** * @brief Stores an event with three 32-bit parameters * * @param[in] _eventID Event id * @param[in] _param1 Param 1 * @param[in] _param2 Param 2 * @param[in] _param3 Param 3 */ #define prvTraceStoreEvent_ParamParamParam( _eventID, _param1, _param2, _param3 ) \ { \ TraceEventHandle_t _xEventHandle = 0; \ if( xTraceEventBegin( _eventID, sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint32_t ), &_xEventHandle ) == TRC_SUCCESS ) \ { \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param1 ) ); \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param2 ) ); \ xTraceEventAdd32( _xEventHandle, ( uint32_t ) ( _param3 ) ); \ xTraceEventEnd( _xEventHandle ); \ } \ } /** * @brief Snapshot mode only. Trace stop hook. * * @param[in] x */ #define vTraceSetStopHook( x ) ( void ) ( x ) /** * @brief Snapshot mode only. Initialize timestamps. */ #define vTraceInitTimestamps() #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ #if ( TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM ) /** * @brief Set the recorder data buffer * * @param[in] pxBuffer Pointer to the recorder data buffer * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceSetBuffer( TraceRecorderDataBuffer_t * pxBuffer ); #else #define xTraceSetBuffer( p ) ( TRC_SUCCESS ) #endif /** * @brief Retrieve the event buffer and event buffer size * * @param[out] ppvBuffer Pointer where event buffer pointer will be written * @param[out] puiSize Event buffer size * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceGetEventBuffer( void ** ppvBuffer, TraceUnsignedBaseType_t * puiSize ); #else /* when TRC_USE_TRACEALYZER_RECORDER == 0 */ #define xTraceInitialize() ( TRC_SUCCESS ) #define xTraceEnable( x ) ( ( void ) ( x ), TRC_SUCCESS ) #define xTraceDisable() ( TRC_SUCCESS ) #define xTraceStringRegister( x, y ) ( ( void ) ( x ), ( void ) y, TRC_SUCCESS ) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ #define xTracePrint( chn, ... ) ( ( void ) ( chn ), TRC_SUCCESS ) #define xTracePrintF( chn, fmt, ... ) ( ( void ) ( chn ), ( void ) ( fmt ), TRC_SUCCESS ) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ #define xTraceVPrintF( chn, formatStr, vl ) ( ( void ) ( chn ), ( void ) ( formatStr ), ( void ) ( vl ), TRC_SUCCESS ) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ #define xTraceTaskInstanceFinishedNow() #define xTraceTaskInstanceFinishedNext() #define vTraceStoreISRBegin( x ) ( void ) ( x ) #define vTraceStoreISREnd( x ) ( void ) ( x ) #define xTraceSetISRProperties( a, b ) ( ( void ) ( a ), ( void ) ( b ), ( traceHandle ) 0 ) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ #define xTraceRegisterChannelFormat( eventLabel, formatStr ) ( ( void ) ( eventLabel ), ( void ) ( formatStr ), 0 ) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ #define vTraceUBData( label, ... ) ( void ) ( label ) #define vTraceSetFilterGroup( x ) ( void ) ( x ) #define vTraceSetFilterMask( x ) ( void ) ( x ) #define prvTraceSetReadyEventsEnabled( status ) ( void ) ( status ) #define vTraceExcludeTask( handle ) ( void ) ( handle ) #define vTraceConsoleChannelPrintF( fmt, ... ) ( void ) ( fmt ) #ifndef TRC_ALLOC_CUSTOM_BUFFER #define TRC_ALLOC_CUSTOM_BUFFER( bufname ) #endif #define xTraceIsRecorderEnabled() ( 0 ) #define xTraceIsRecorderInitialized() ( 0 ) #define xTraceSetBuffer( p ) ( TRC_SUCCESS ) #define xTraceGetEventBuffer( p ) ( TRC_FAIL ) #define vTraceSetStopHook( x ) ( void ) ( x ) #define TraceRecorderDataBuffer_t uint32_t #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ /** * @deprecated Backwards compatibility. Use xTraceInitialize instead. */ #define vTraceInitialize ( void ) xTraceInitialize /** * @deprecated Backwards compatibility. Use xTraceEnable instead. */ #define vTraceEnable ( void ) xTraceEnable /** * @deprecated Backwards compatibility. Use xTraceDisable instead. */ #define vTraceStop ( void ) xTraceDisable /** * @deprecated Backwards compatibility. Use xTraceTaskInstanceFinishedNow instead. */ #define vTraceInstanceFinishedNow ( void ) xTraceTaskInstanceFinishedNow /** * @deprecated Backwards compatibility. Use xTraceTaskInstanceFinishedNext instead. */ #define vTraceInstanceFinishedNext ( void ) xTraceTaskInstanceFinishedNext /** * @deprecated Backwards compatibility. Use xTracePrintF instead. */ #define vTracePrintF ( void ) xTracePrintF /** * @deprecated Backwards compatibility. Use xTraceVPrintF instead. */ #define vTraceVPrintF ( void ) xTraceVPrintF /** * @deprecated Backwards compatibility. Use xTracePrint instead. */ #define vTracePrint ( void ) xTracePrint /** * @deprecated Backwards compatibility. Use xTraceSetBuffer instead. */ #define vTraceSetRecorderDataBuffer( pxBuffer ) xTraceSetBuffer( ( TraceRecorderDataBuffer_t * ) ( pxBuffer ) ) #ifdef __cplusplus } #endif #endif /* TRC_RECORDER_H */