/* * Trace Recorder for Tracealyzer v4.6.6 * 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) */ #undef TraceISRHandle_t #define TraceISRHandle_t traceHandle #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 */ #undef traceHandle #define traceHandle TraceISRHandle_t /* 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 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ /* These includes offer functionality for Streaming mode only, but they are included here in order to avoid compilation errors */ #include #include #include #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) */ /** * @internal Deprecated - Registers an ISR */ traceHandle xTraceSetISRProperties(const char* szName, uint8_t uiPriority); /** * @brief * * Registers an ISR. * * Example: * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt * ... * TraceISRHandle_t Timer1Handle; * xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle); * * @param[in] szName ISR name * @param[in] uiPriority ISR priority * @param[in] pxISRHandle * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceISRRegister(const char* szName, uint32_t uiPriority, TraceISRHandle_t* pxISRHandle); /** * @brief * * Registers the beginning of an Interrupt Service Routine, using a TraceISRHandle_t * provided by xTraceISRRegister. * * Example: * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt * ... * TraceISRHandle_t Timer1Handle; * xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle); * ... * void ISR_handler() * { * xTraceISRBegin(Timer1Handle); * ... * xTraceISREnd(0); * } * * @param[in] xHandle Handle for the previously registered ISR * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceISRBegin(TraceISRHandle_t xHandle); #define vTraceStoreISRBegin(__handle) (void)xTraceISRBegin((TraceISRHandle_t)(__handle)) /** * @brief * * Registers the end of an Interrupt Service Routine. * * The parameter pendingISR indicates if the interrupt has requested a * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the * interrupt is assumed to return to the previous context. * * Example: * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt * ... * TraceISRHandle_t Timer1Handle; * xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle); * ... * void ISR_handler() * { * xTraceISRBegin(Timer1Handle); * ... * xTraceISREnd(0); * } * * @param[in] pendingISR Flag that indicates whether an ISR is pending * * @retval TRC_FAIL Failure * @retval TRC_SUCCESS Success */ traceResult xTraceISREnd(int pendingISR); #define vTraceStoreISREnd(__pendingISR) (void)xTraceISREnd(__pendingISR) /** * @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 #define prvTraceStoreKernelCall(eventcode, objectClass, byteParam) {} #define prvTraceStoreKernelCallWithNumericParamOnly(evtcode, param) {} #define prvTraceStoreKernelCallWithParam(evtcode, objectClass, objectNumber, param) {} #endif /** * @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 #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 internalErrorOccured; /* 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 */