summaryrefslogtreecommitdiff
path: root/FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/trcKernelPort.c')
-rw-r--r--FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/trcKernelPort.c833
1 files changed, 833 insertions, 0 deletions
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/trcKernelPort.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
new file mode 100644
index 000000000..d41b52687
--- /dev/null
+++ b/FreeRTOS-Labs/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
@@ -0,0 +1,833 @@
+/*******************************************************************************
+ * Trace Recorder Library for Tracealyzer v4.1.5
+ * Percepio AB, www.percepio.com
+ *
+ * trcKernelPort.c
+ *
+ * The FreeRTOS-specific parts of the trace recorder
+ *
+ * Terms of Use
+ * This file is part of the trace recorder library (RECORDER), which is the
+ * intellectual property of Percepio AB (PERCEPIO) and provided under a
+ * license as follows.
+ * The RECORDER may be used free of charge for the purpose of recording data
+ * intended for analysis in PERCEPIO products. It may not be used or modified
+ * for other purposes without explicit permission from PERCEPIO.
+ * You may distribute the RECORDER in its original source code form, assuming
+ * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
+ * allowed to distribute the RECORDER with minor modifications intended for
+ * configuration or porting of the RECORDER, e.g., to allow using it on a
+ * specific processor, processor family or with a specific communication
+ * interface. Any such modifications should be documented directly below
+ * this comment block.
+ *
+ * Disclaimer
+ * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
+ * as to its use or performance. PERCEPIO does not and cannot warrant the
+ * performance or results you may obtain by using the RECORDER or documentation.
+ * PERCEPIO make no warranties, express or implied, as to noninfringement of
+ * third party rights, merchantability, or fitness for any particular purpose.
+ * In no event will PERCEPIO, its technology partners, or distributors be liable
+ * to you for any consequential, incidental or special damages, including any
+ * lost profits or lost savings, even if a representative of PERCEPIO has been
+ * advised of the possibility of such damages, or for any claim by any third
+ * party. Some jurisdictions do not allow the exclusion or limitation of
+ * incidental, consequential or special damages, or the exclusion of implied
+ * warranties or limitations on how long an implied warranty may last, so the
+ * above limitations may not apply to you.
+ *
+ * Tabs are used for indent in this file (1 tab = 4 spaces)
+ *
+ * Copyright Percepio AB, 2018.
+ * www.percepio.com
+ ******************************************************************************/
+
+#include "FreeRTOS.h"
+
+#if (!defined(TRC_USE_TRACEALYZER_RECORDER) && configUSE_TRACE_FACILITY == 1)
+#error Trace Recorder: You need to include trcRecorder.h at the end of your FreeRTOSConfig.h!
+#endif
+
+#if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1)
+
+#ifndef TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
+ /* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS is missing in trcConfig.h. */
+#error "TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS must be defined in trcConfig.h."
+#endif
+
+#ifndef TRC_CFG_INCLUDE_TIMER_EVENTS
+ /* TRC_CFG_INCLUDE_TIMER_EVENTS is missing in trcConfig.h. */
+#error "TRC_CFG_INCLUDE_TIMER_EVENTS must be defined in trcConfig.h."
+#endif
+
+#ifndef TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
+ /* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS is missing in trcConfig.h. */
+#error "TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS must be defined in trcConfig.h."
+#endif
+
+#ifndef TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS
+ /* TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS is missing in trcConfig.h. Define this as 1 if using FreeRTOS v10 or later and like to trace stream buffer or message buffer events, otherwise 0. */
+#error "TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be defined in trcConfig.h."
+#endif
+
+#if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))
+ /*
+ The below error message is to alert you on the following issue:
+
+ The hardware port selected in trcConfig.h uses the operating system timer for the
+ timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt.
+
+ When using "tickless idle" mode, the recorder needs an independent time source in
+ order to correctly record the durations of the idle times. Otherwise, the trace may appear
+ to have a different length than in reality, and the reported CPU load is also affected.
+
+ You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
+ macro in your trcConfig.h file. But then the time scale may be incorrect during
+ tickless idle periods.
+
+ To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT
+ in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros
+ accordingly, using a free running counter or an independent periodic interrupt timer.
+ See trcHardwarePort.h for details.
+
+ For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the
+ DWT cycle counter for timestamping in these cases.
+ */
+
+ #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
+ #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.
+ #endif
+#endif /* (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)) */
+
+#include "task.h"
+#include "queue.h"
+
+#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
+/* If the project does not include the FreeRTOS timers, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
+#include "timers.h"
+#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
+
+#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
+/* If the project does not include the FreeRTOS event groups, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
+#include "event_groups.h"
+#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
+
+#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
+/* If the project does not include the FreeRTOS stream buffers, TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be set to 0 */
+#include "stream_buffer.h"
+#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
+
+uint32_t prvTraceGetQueueNumber(void* handle);
+
+#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)
+
+extern unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue );
+extern void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber );
+extern unsigned char ucQueueGetQueueType( xQueueHandle pxQueue );
+
+uint32_t prvTraceGetQueueNumber(void* handle)
+{
+ return (uint32_t)ucQueueGetQueueNumber(handle);
+}
+#else
+uint32_t prvTraceGetQueueNumber(void* handle)
+{
+ return (uint32_t)uxQueueGetQueueNumber(handle);
+}
+#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X) */
+
+uint8_t prvTraceGetQueueType(void* handle)
+{
+ // This is either declared in header file in FreeRTOS 8 and later, or as extern above
+ return ucQueueGetQueueType(handle);
+}
+
+/* Tasks */
+uint16_t prvTraceGetTaskNumberLow16(void* handle)
+{
+ return TRACE_GET_LOW16(uxTaskGetTaskNumber(handle));
+}
+
+uint16_t prvTraceGetTaskNumberHigh16(void* handle)
+{
+ return TRACE_GET_HIGH16(uxTaskGetTaskNumber(handle));
+}
+
+void prvTraceSetTaskNumberLow16(void* handle, uint16_t value)
+{
+ vTaskSetTaskNumber(handle, TRACE_SET_LOW16(uxTaskGetTaskNumber(handle), value));
+}
+
+void prvTraceSetTaskNumberHigh16(void* handle, uint16_t value)
+{
+ vTaskSetTaskNumber(handle, TRACE_SET_HIGH16(uxTaskGetTaskNumber(handle), value));
+}
+
+uint16_t prvTraceGetQueueNumberLow16(void* handle)
+{
+ return TRACE_GET_LOW16(prvTraceGetQueueNumber(handle));
+}
+
+uint16_t prvTraceGetQueueNumberHigh16(void* handle)
+{
+ return TRACE_GET_HIGH16(prvTraceGetQueueNumber(handle));
+}
+
+void prvTraceSetQueueNumberLow16(void* handle, uint16_t value)
+{
+ vQueueSetQueueNumber(handle, TRACE_SET_LOW16(prvTraceGetQueueNumber(handle), value));
+}
+
+void prvTraceSetQueueNumberHigh16(void* handle, uint16_t value)
+{
+ vQueueSetQueueNumber(handle, TRACE_SET_HIGH16(prvTraceGetQueueNumber(handle), value));
+}
+
+#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
+
+uint16_t prvTraceGetTimerNumberLow16(void* handle)
+{
+ return TRACE_GET_LOW16(uxTimerGetTimerNumber(handle));
+}
+
+uint16_t prvTraceGetTimerNumberHigh16(void* handle)
+{
+ return TRACE_GET_HIGH16(uxTimerGetTimerNumber(handle));
+}
+
+void prvTraceSetTimerNumberLow16(void* handle, uint16_t value)
+{
+ vTimerSetTimerNumber(handle, TRACE_SET_LOW16(uxTimerGetTimerNumber(handle), value));
+}
+
+void prvTraceSetTimerNumberHigh16(void* handle, uint16_t value)
+{
+ vTimerSetTimerNumber(handle, TRACE_SET_HIGH16(uxTimerGetTimerNumber(handle), value));
+}
+#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
+
+#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
+
+uint16_t prvTraceGetEventGroupNumberLow16(void* handle)
+{
+ return TRACE_GET_LOW16(uxEventGroupGetNumber(handle));
+}
+
+uint16_t prvTraceGetEventGroupNumberHigh16(void* handle)
+{
+ return TRACE_GET_HIGH16(uxEventGroupGetNumber(handle));
+}
+
+void prvTraceSetEventGroupNumberLow16(void* handle, uint16_t value)
+{
+ vEventGroupSetNumber(handle, TRACE_SET_LOW16(uxEventGroupGetNumber(handle), value));
+}
+
+void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value)
+{
+ vEventGroupSetNumber(handle, TRACE_SET_HIGH16(uxEventGroupGetNumber(handle), value));
+}
+#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
+
+#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
+
+uint16_t prvTraceGetStreamBufferNumberLow16(void* handle)
+{
+ return TRACE_GET_LOW16(uxStreamBufferGetStreamBufferNumber(handle));
+}
+
+uint16_t prvTraceGetStreamBufferNumberHigh16(void* handle)
+{
+ return TRACE_GET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle));
+}
+
+void prvTraceSetStreamBufferNumberLow16(void* handle, uint16_t value)
+{
+ vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_LOW16(uxStreamBufferGetStreamBufferNumber(handle), value));
+}
+
+void prvTraceSetStreamBufferNumberHigh16(void* handle, uint16_t value)
+{
+ vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle), value));
+}
+#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
+
+#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
+
+static void* pCurrentTCB = NULL;
+#if (defined(configENABLE_BACKWARD_COMPATIBILITY) && configENABLE_BACKWARD_COMPATIBILITY == 0)
+/* We're explicitly not using compatibility mode */
+static TaskHandle_t HandleTzCtrl = NULL; /* TzCtrl task TCB */
+#else
+/* We're using compatibility mode, or we're running an old kernel */
+static xTaskHandle HandleTzCtrl = NULL; /* TzCtrl task TCB */
+#endif
+
+#if defined(configSUPPORT_STATIC_ALLOCATION)
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE];
+static StaticTask_t tcbTzCtrl;
+#endif
+#endif
+
+/* Monitored by TzCtrl task, that give warnings as User Events */
+extern volatile uint32_t NoRoomForSymbol;
+extern volatile uint32_t NoRoomForObjectData;
+extern volatile uint32_t LongestSymbolName;
+extern volatile uint32_t MaxBytesTruncated;
+
+/* Keeps track of previous values, to only react on changes. */
+static uint32_t NoRoomForSymbol_last = 0;
+static uint32_t NoRoomForObjectData_last = 0;
+static uint32_t LongestSymbolName_last = 0;
+static uint32_t MaxBytesTruncated_last = 0;
+
+/* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */
+traceString trcWarningChannel;
+
+#define TRC_PORT_MALLOC(size) pvPortMalloc(size)
+
+TRC_STREAM_PORT_ALLOCATE_FIELDS()
+
+/* Called by TzCtrl task periodically (Normally every 100 ms) */
+static void prvCheckRecorderStatus(void);
+
+extern void prvTraceWarning(int errCode);
+
+/* The TzCtrl task - receives commands from Tracealyzer (start/stop) */
+static portTASK_FUNCTION( TzCtrl, pvParameters );
+
+/*******************************************************************************
+ * vTraceEnable
+ *
+ * Function that enables the tracing and creates the control task. It will halt
+ * execution until a Start command has been received if haltUntilStart is true.
+ *
+ ******************************************************************************/
+void vTraceEnable(int startOption)
+{
+ int32_t bytes = 0;
+ int32_t status;
+ extern uint32_t RecorderEnabled;
+ TracealyzerCommandType msg;
+
+ /* Only do this first time...*/
+ if (HandleTzCtrl == NULL)
+ {
+ TRC_STREAM_PORT_INIT();
+
+ /* Note: Requires that TRC_CFG_INCLUDE_USER_EVENTS is 1. */
+ trcWarningChannel = xTraceRegisterString("Warnings from Recorder");
+
+ /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
+ #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
+ HandleTzCtrl = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
+ #else
+ xTaskCreate( TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );
+ #endif
+
+ if (HandleTzCtrl == NULL)
+ {
+ prvTraceError(PSF_ERROR_TZCTRLTASK_NOT_CREATED);
+ }
+ }
+
+ if (startOption == TRC_START_AWAIT_HOST)
+ {
+ /* We keep trying to read commands until the recorder has been started */
+ do
+ {
+ bytes = 0;
+
+ status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);
+
+ if (status != 0)
+ {
+ prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);
+ }
+
+ if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))
+ {
+ if (prvIsValidCommand(&msg))
+ {
+ if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1)
+ {
+ /* On start, init and reset the timestamping */
+ TRC_PORT_SPECIFIC_INIT();
+ }
+
+ prvProcessCommand(&msg);
+ }
+ }
+ }
+ while (RecorderEnabled == 0);
+ }
+ else if (startOption == TRC_START)
+ {
+ /* We start streaming directly - this assumes that the interface is ready! */
+ TRC_PORT_SPECIFIC_INIT();
+
+ msg.cmdCode = CMD_SET_ACTIVE;
+ msg.param1 = 1;
+ prvProcessCommand(&msg);
+ }
+ else
+ {
+ /* On TRC_INIT */
+ TRC_PORT_SPECIFIC_INIT();
+ }
+}
+
+#if (TRC_CFG_SCHEDULING_ONLY == 0)
+/*******************************************************************************
+ * vTraceSetQueueName(void* object, const char* name)
+ *
+ * Parameter object: pointer to the Queue that shall be named
+ * Parameter name: the name to set (const string literal)
+ *
+ * Sets a name for Queue objects for display in Tracealyzer.
+ ******************************************************************************/
+void vTraceSetQueueName(void* object, const char* name)
+{
+ vTraceStoreKernelObjectName(object, name);
+}
+
+/*******************************************************************************
+ * vTraceSetSemaphoreName(void* object, const char* name)
+ *
+ * Parameter object: pointer to the Semaphore that shall be named
+ * Parameter name: the name to set (const string literal)
+ *
+ * Sets a name for Semaphore objects for display in Tracealyzer.
+ ******************************************************************************/
+void vTraceSetSemaphoreName(void* object, const char* name)
+{
+ vTraceStoreKernelObjectName(object, name);
+}
+
+/*******************************************************************************
+ * vTraceSetMutexName(void* object, const char* name)
+ *
+ * Parameter object: pointer to the Mutex that shall be named
+ * Parameter name: the name to set (const string literal)
+ *
+ * Sets a name for Mutex objects for display in Tracealyzer.
+ ******************************************************************************/
+void vTraceSetMutexName(void* object, const char* name)
+{
+ vTraceStoreKernelObjectName(object, name);
+}
+
+#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
+/*******************************************************************************
+* vTraceSetEventGroupName(void* object, const char* name)
+*
+* Parameter object: pointer to the vTraceSetEventGroupName that shall be named
+* Parameter name: the name to set (const string literal)
+*
+* Sets a name for EventGroup objects for display in Tracealyzer.
+******************************************************************************/
+void vTraceSetEventGroupName(void* object, const char* name)
+{
+ vTraceStoreKernelObjectName(object, name);
+}
+#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
+
+#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
+/*******************************************************************************
+* vTraceSetStreamBufferName(void* object, const char* name)
+*
+* Parameter object: pointer to the StreamBuffer that shall be named
+* Parameter name: the name to set (const string literal)
+*
+* Sets a name for StreamBuffer objects for display in Tracealyzer.
+******************************************************************************/
+void vTraceSetStreamBufferName(void* object, const char* name)
+{
+ vTraceStoreKernelObjectName(object, name);
+}
+
+/*******************************************************************************
+* vTraceSetMessageBufferName(void* object, const char* name)
+*
+* Parameter object: pointer to the MessageBuffer that shall be named
+* Parameter name: the name to set (const string literal)
+*
+* Sets a name for MessageBuffer objects for display in Tracealyzer.
+******************************************************************************/
+void vTraceSetMessageBufferName(void* object, const char* name)
+{
+ vTraceStoreKernelObjectName(object, name);
+}
+#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
+
+#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
+
+/*******************************************************************************
+ * prvGetCurrentTaskHandle
+ *
+ * Function that returns the handle to the currently executing task.
+ *
+ ******************************************************************************/
+void* prvTraceGetCurrentTaskHandle(void)
+{
+ return xTaskGetCurrentTaskHandle();
+}
+
+/*******************************************************************************
+ * prvIsNewTCB
+ *
+ * Tells if this task is already executing, or if there has been a task-switch.
+ * Assumed to be called within a trace hook in kernel context.
+ ******************************************************************************/
+uint32_t prvIsNewTCB(void* pNewTCB)
+{
+ if (pCurrentTCB != pNewTCB)
+ {
+ pCurrentTCB = pNewTCB;
+ return 1;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ * prvTraceIsSchedulerSuspended
+ *
+ * Returns true if the RTOS scheduler currently is disabled, thus preventing any
+ * task-switches from occurring. Only called from vTraceStoreISREnd.
+ ******************************************************************************/
+unsigned char prvTraceIsSchedulerSuspended(void)
+{
+ /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
+ INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
+ FreeRTOSConfig.h for this function to be available. */
+
+ return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
+}
+
+
+/*******************************************************************************
+ * prvCheckRecorderStatus
+ *
+ * Called by TzCtrl task periodically (every 100 ms - seems reasonable).
+ * Checks a number of diagnostic variables and give warnings as user events,
+ * in most cases including a suggested solution.
+ ******************************************************************************/
+static void prvCheckRecorderStatus(void)
+{
+ if (NoRoomForSymbol > NoRoomForSymbol_last)
+ {
+ if (NoRoomForSymbol > 0)
+ {
+ prvTraceWarning(PSF_WARNING_SYMBOL_TABLE_SLOTS);
+ }
+ NoRoomForSymbol_last = NoRoomForSymbol;
+ }
+
+ if (NoRoomForObjectData > NoRoomForObjectData_last)
+ {
+ if (NoRoomForObjectData > 0)
+ {
+ prvTraceWarning(PSF_WARNING_OBJECT_DATA_SLOTS);
+ }
+ NoRoomForObjectData_last = NoRoomForObjectData;
+ }
+
+ if (LongestSymbolName > LongestSymbolName_last)
+ {
+ if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH))
+ {
+ prvTraceWarning(PSF_WARNING_SYMBOL_MAX_LENGTH);
+ }
+ LongestSymbolName_last = LongestSymbolName;
+ }
+
+ if (MaxBytesTruncated > MaxBytesTruncated_last)
+ {
+ if (MaxBytesTruncated > 0)
+ {
+ prvTraceWarning(PSF_WARNING_STRING_TOO_LONG);
+ }
+ MaxBytesTruncated_last = MaxBytesTruncated;
+ }
+}
+
+/*******************************************************************************
+ * TzCtrl
+ *
+ * Task for sending the trace data from the internal buffer to the stream
+ * interface (assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) and for
+ * receiving commands from Tracealyzer. Also does some diagnostics.
+ ******************************************************************************/
+static portTASK_FUNCTION( TzCtrl, pvParameters )
+{
+ TracealyzerCommandType msg;
+ int32_t bytes = 0;
+ int32_t status = 0;
+ (void)pvParameters;
+
+ while (1)
+ {
+ do
+ {
+ /* Listen for new commands */
+ bytes = 0;
+ status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);
+
+ if (status != 0)
+ {
+ prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);
+ }
+
+ if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))
+ {
+ if (prvIsValidCommand(&msg))
+ {
+ prvProcessCommand(&msg); /* Start or Stop currently... */
+ }
+ }
+
+/* If the internal buffer is disabled, the COMMIT macro instead sends the data directly
+ from the "event functions" (using TRC_STREAM_PORT_WRITE_DATA). */
+#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
+ /* If there is a buffer page, this sends it to the streaming interface using TRC_STREAM_PORT_WRITE_DATA. */
+ bytes = prvPagedEventBufferTransfer();
+#endif
+
+ /* If there was data sent or received (bytes != 0), loop around and repeat, if there is more data to send or receive.
+ Otherwise, step out of this loop and sleep for a while. */
+
+ } while (bytes != 0);
+
+ prvCheckRecorderStatus();
+
+ vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);
+ }
+}
+
+#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
+
+
+#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
+
+/* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */
+int uiInEventGroupSetBitsFromISR = 0;
+
+/******************************************************************************
+ * TraceQueueClassTable
+ * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).
+ * Has one entry for each QueueType, gives TRACE_CLASS ID.
+ ******************************************************************************/
+traceObjectClass TraceQueueClassTable[5] = {
+ TRACE_CLASS_QUEUE,
+ TRACE_CLASS_MUTEX,
+ TRACE_CLASS_SEMAPHORE,
+ TRACE_CLASS_SEMAPHORE,
+ TRACE_CLASS_MUTEX
+};
+
+#if (TRC_CFG_SCHEDULING_ONLY == 0)
+/*******************************************************************************
+ * vTraceSetQueueName(void* object, const char* name)
+ *
+ * Parameter object: pointer to the Queue that shall be named
+ * Parameter name: the name to set (const string literal)
+ *
+ * Sets a name for Queue objects for display in Tracealyzer.
+ ******************************************************************************/
+void vTraceSetQueueName(void* object, const char* name)
+{
+ prvTraceSetObjectName(TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
+}
+
+/*******************************************************************************
+ * vTraceSetSemaphoreName(void* object, const char* name)
+ *
+ * Parameter object: pointer to the Semaphore that shall be named
+ * Parameter name: the name to set (const string literal)
+ *
+ * Sets a name for Semaphore objects for display in Tracealyzer.
+ ******************************************************************************/
+void vTraceSetSemaphoreName(void* object, const char* name)
+{
+ prvTraceSetObjectName(TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
+}
+
+/*******************************************************************************
+ * vTraceSetMutexName(void* object, const char* name)
+ *
+ * Parameter object: pointer to the Mutex that shall be named
+ * Parameter name: the name to set (const string literal)
+ *
+ * Sets a name for Semaphore objects for display in Tracealyzer.
+ ******************************************************************************/
+void vTraceSetMutexName(void* object, const char* name)
+{
+ prvTraceSetObjectName(TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
+}
+
+#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
+/*******************************************************************************
+* vTraceSetEventGroupName(void* object, const char* name)
+*
+* Parameter object: pointer to the EventGroup that shall be named
+* Parameter name: the name to set (const string literal)
+*
+* Sets a name for EventGroup objects for display in Tracealyzer.
+******************************************************************************/
+void vTraceSetEventGroupName(void* object, const char* name)
+{
+ prvTraceSetObjectName(TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER(EVENTGROUP, object), name);
+}
+#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
+
+#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
+/*******************************************************************************
+* vTraceSetStreamBufferName(void* object, const char* name)
+*
+* Parameter object: pointer to the StreamBuffer that shall be named
+* Parameter name: the name to set (const string literal)
+*
+* Sets a name for StreamBuffer objects for display in Tracealyzer.
+******************************************************************************/
+void vTraceSetStreamBufferName(void* object, const char* name)
+{
+ prvTraceSetObjectName(TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name);
+}
+
+/*******************************************************************************
+* vTraceSetMessageBufferName(void* object, const char* name)
+*
+* Parameter object: pointer to the MessageBuffer that shall be named
+* Parameter name: the name to set (const string literal)
+*
+* Sets a name for MessageBuffer objects for display in Tracealyzer.
+******************************************************************************/
+void vTraceSetMessageBufferName(void* object, const char* name)
+{
+ prvTraceSetObjectName(TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name);
+}
+#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
+
+#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
+
+void* prvTraceGetCurrentTaskHandle()
+{
+ return xTaskGetCurrentTaskHandle();
+}
+
+/* Initialization of the object property table */
+void vTraceInitObjectPropertyTable()
+{
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = TRC_CFG_NQUEUE;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = TRC_CFG_NSEMAPHORE;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = TRC_CFG_NMUTEX;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = TRC_CFG_NTASK;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[7] = TRC_CFG_NSTREAMBUFFER;
+ RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[8] = TRC_CFG_NMESSAGEBUFFER;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = TRC_CFG_NAME_LEN_TASK;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[7] = TRC_CFG_NAME_LEN_STREAMBUFFER;
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[8] = TRC_CFG_NAME_LEN_MESSAGEBUFFER;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[7] = PropertyTableSizeStreamBuffer;
+ RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[8] = PropertyTableSizeMessageBuffer;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[5] = StartIndexTimer;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[7] = StartIndexStreamBuffer;
+ RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[8] = StartIndexMessageBuffer;
+ RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;
+}
+
+/* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */
+void vTraceInitObjectHandleStack()
+{
+ objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;
+ objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = (TRC_CFG_NQUEUE);
+ objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE);
+ objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX);
+ objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK);
+ objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR);
+ objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER);
+ objectHandleStacks.indexOfNextAvailableHandle[7] = objectHandleStacks.lowestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP);
+ objectHandleStacks.indexOfNextAvailableHandle[8] = objectHandleStacks.lowestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER);
+
+ objectHandleStacks.highestIndexOfClass[0] = (TRC_CFG_NQUEUE) - 1;
+ objectHandleStacks.highestIndexOfClass[1] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) - 1;
+ objectHandleStacks.highestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) - 1;
+ objectHandleStacks.highestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) - 1;
+ objectHandleStacks.highestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) - 1;
+ objectHandleStacks.highestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) - 1;
+ objectHandleStacks.highestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) - 1;
+ objectHandleStacks.highestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) - 1;
+ objectHandleStacks.highestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER) - 1;
+}
+
+/* Returns the "Not enough handles" error message for this object class */
+const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
+{
+ switch(objectclass)
+ {
+ case TRACE_CLASS_TASK:
+ return "Not enough TASK handles - increase TRC_CFG_NTASK in trcSnapshotConfig.h";
+ case TRACE_CLASS_ISR:
+ return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h";
+ case TRACE_CLASS_SEMAPHORE:
+ return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h";
+ case TRACE_CLASS_MUTEX:
+ return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h";
+ case TRACE_CLASS_QUEUE:
+ return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h";
+ case TRACE_CLASS_TIMER:
+ return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h";
+ case TRACE_CLASS_EVENTGROUP:
+ return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h";
+ case TRACE_CLASS_STREAMBUFFER:
+ return "Not enough STREAMBUFFER handles - increase TRC_CFG_NSTREAMBUFFER in trcSnapshotConfig.h";
+ case TRACE_CLASS_MESSAGEBUFFER:
+ return "Not enough MESSAGEBUFFER handles - increase TRC_CFG_NMESSAGEBUFFER in trcSnapshotConfig.h";
+ default:
+ return "pszTraceGetErrorHandles: Invalid objectclass!";
+ }
+}
+
+/*******************************************************************************
+ * prvTraceIsSchedulerSuspended
+ *
+ * Returns true if the RTOS scheduler currently is disabled, thus preventing any
+ * task-switches from occurring. Only called from vTraceStoreISREnd.
+ ******************************************************************************/
+#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
+unsigned char prvTraceIsSchedulerSuspended(void)
+{
+ /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
+ INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
+ FreeRTOSConfig.h for this function to be available. */
+
+ return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
+}
+#endif
+
+#endif /* Snapshot mode */
+
+#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/