]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
Update to the latest trace recorder library.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace / trcKernelPort.c
index 722e553419ca0263133db21ea3ed7f9af92613bb..96e568a1a231fe406ba5be81fd035fe60bab2d8d 100644 (file)
 /*******************************************************************************\r
- * Tracealyzer v2.7.7 Recorder Library\r
+ * Trace Recorder Library for Tracealyzer v3.1.2\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcKernelPort.c\r
  *\r
- * Kernel-specific functionality for FreeRTOS, used by the recorder library.\r
+ * The FreeRTOS-specific parts of the trace recorder\r
  *\r
  * Terms of Use\r
- * This software is copyright Percepio AB. The recorder library is free for\r
- * use together with Percepio products. You may distribute the recorder library\r
- * in its original form, including modifications in trcHardwarePort.c/.h\r
- * given that these modification are clearly marked as your own modifications\r
- * and documented in the initial comment section of these source files.\r
- * This software is the intellectual property of Percepio AB and may not be\r
- * sold or in other ways commercially redistributed without explicit written\r
- * permission by Percepio AB.\r
+ * This file is part of the trace recorder library (RECORDER), which is the\r
+ * intellectual property of Percepio AB (PERCEPIO) and provided under a\r
+ * license as follows.\r
+ * The RECORDER may be used free of charge for the purpose of recording data\r
+ * intended for analysis in PERCEPIO products. It may not be used or modified\r
+ * for other purposes without explicit permission from PERCEPIO.\r
+ * You may distribute the RECORDER in its original source code form, assuming\r
+ * this text (terms of use, disclaimer, copyright notice) is unchanged. You are\r
+ * allowed to distribute the RECORDER with minor modifications intended for\r
+ * configuration or porting of the RECORDER, e.g., to allow using it on a\r
+ * specific processor, processor family or with a specific communication\r
+ * interface. Any such modifications should be documented directly below\r
+ * this comment block.\r
  *\r
  * Disclaimer\r
- * The trace tool and recorder library is being delivered to you AS IS and\r
- * Percepio AB makes no warranty as to its use or performance. Percepio AB does\r
- * not and cannot warrant the performance or results you may obtain by using the\r
- * software or documentation. Percepio AB make no warranties, express or\r
- * implied, as to noninfringement of third party rights, merchantability, or\r
- * fitness for any particular purpose. In no event will Percepio AB, its\r
- * technology partners, or distributors be liable to you for any consequential,\r
- * incidental or special damages, including any lost profits or lost savings,\r
- * even if a representative of Percepio AB has been advised of the possibility\r
- * of such damages, or for any claim by any third party. Some jurisdictions do\r
- * not allow the exclusion or limitation of incidental, consequential or special\r
- * damages, or the exclusion of implied warranties or limitations on how long an\r
- * implied warranty may last, so the above limitations may not apply to you.\r
+ * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty\r
+ * as to its use or performance. PERCEPIO does not and cannot warrant the\r
+ * performance or results you may obtain by using the RECORDER or documentation.\r
+ * PERCEPIO make no warranties, express or implied, as to noninfringement of\r
+ * third party rights, merchantability, or fitness for any particular purpose.\r
+ * In no event will PERCEPIO, its technology partners, or distributors be liable\r
+ * to you for any consequential, incidental or special damages, including any\r
+ * lost profits or lost savings, even if a representative of PERCEPIO has been\r
+ * advised of the possibility of such damages, or for any claim by any third\r
+ * party. Some jurisdictions do not allow the exclusion or limitation of\r
+ * incidental, consequential or special damages, or the exclusion of implied\r
+ * warranties or limitations on how long an implied warranty may last, so the\r
+ * above limitations may not apply to you.\r
  *\r
  * Tabs are used for indent in this file (1 tab = 4 spaces)\r
  *\r
- * Copyright Percepio AB, 2012-2015.\r
+ * Copyright Percepio AB, 2017.\r
  * www.percepio.com\r
  ******************************************************************************/\r
 \r
-#include "trcKernelPort.h"\r
+#include "FreeRTOS.h"\r
 \r
-#if (USE_TRACEALYZER_RECORDER == 1)\r
+#if (!defined(TRC_USE_TRACEALYZER_RECORDER) && configUSE_TRACE_FACILITY == 1)\r
+#error Trace Recorder: You need to include trcRecorder.h at the end of your FreeRTOSConfig.h!\r
+#endif\r
+\r
+#if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1)\r
+\r
+#if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))\r
+       /*\r
+               The below error message is to alert you on the following issue:\r
+\r
+               The hardware port selected in trcConfig.h uses the operating system timer for the\r
+               timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt.\r
+\r
+               When using tickless idle, the recorder needs an independent time source in order to\r
+               correctly record the durations of the idle times. Otherwise, the trace may appear\r
+               to have a different length than in reality, and the reported CPU load is also affected.\r
+\r
+               You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING\r
+               macro in your trcConfig.h file. But then the time scale may be incorrect during\r
+               tickless idle periods.\r
 \r
-#include <stdint.h>\r
+               To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT\r
+               in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros\r
+               accordingly, using a free running counter or an independent periodic interrupt timer.\r
+               See trcHardwarePort.h for details.\r
+\r
+               For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the\r
+               DWT cycle counter for timestamping in these cases.\r
+       */\r
+\r
+       #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING\r
+       #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.\r
+       #endif\r
+#endif\r
 \r
 #include "task.h"\r
+#include "queue.h"\r
 \r
-/* For classes implemented as FreeRTOS Queues:\r
-This translates queue.type to the corresponding trace object class. */\r
-traceObjectClass TraceObjectClassTable[5] = {\r
-       TRACE_CLASS_QUEUE,\r
-       TRACE_CLASS_MUTEX,\r
-       TRACE_CLASS_SEMAPHORE,\r
-       TRACE_CLASS_SEMAPHORE,\r
-       TRACE_CLASS_MUTEX\r
-};\r
+#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)\r
 \r
-int uiInEventGroupSetBitsFromISR = 0;\r
+static void* pCurrentTCB = NULL;\r
+#if (defined(configENABLE_BACKWARD_COMPATIBILITY) && configENABLE_BACKWARD_COMPATIBILITY == 0)\r
+/* We're explicitly not using compatibility mode */\r
+static TaskHandle_t HandleTzCtrl = NULL;       /* TzCtrl task TCB */\r
+#else\r
+/* We're using compatibility mode, or we're running an old kernel */\r
+static xTaskHandle HandleTzCtrl = NULL;       /* TzCtrl task TCB */\r
+#endif\r
+\r
+#if (configSUPPORT_STATIC_ALLOCATION == 1)\r
+static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE];\r
+static StaticTask_t tcbTzCtrl;\r
+#endif\r
+\r
+/* Monitored by TzCtrl task, that give warnings as User Events */\r
+extern volatile uint32_t NoRoomForSymbol;\r
+extern volatile uint32_t NoRoomForObjectData;\r
+extern volatile uint32_t LongestSymbolName;\r
+extern volatile uint32_t MaxBytesTruncated;\r
+\r
+/* Keeps track of previous values, to only react on changes. */\r
+static uint32_t NoRoomForSymbol_last = 0;\r
+static uint32_t NoRoomForObjectData_last = 0;\r
+static uint32_t LongestSymbolName_last = 0;\r
+static uint32_t MaxBytesTruncated_last = 0;\r
 \r
-extern unsigned char ucQueueGetQueueType(void*);\r
+/* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */\r
+traceString trcWarningChannel;\r
 \r
-#if (FREERTOS_VERSION < FREERTOS_VERSION_8_0_OR_LATER)\r
+#define TRC_PORT_MALLOC(size) pvPortMalloc(size)\r
 \r
-extern portBASE_TYPE ucQueueGetQueueNumber(void*);\r
+TRC_STREAM_PORT_ALLOCATE_FIELDS()\r
 \r
-objectHandleType prvTraceGetObjectNumber(void* handle)\r
+/* Called by TzCtrl task periodically (Normally every 100 ms) */\r
+static void prvCheckRecorderStatus(void);\r
+\r
+/* The TzCtrl task - receives commands from Tracealyzer (start/stop) */\r
+static portTASK_FUNCTION( TzCtrl, pvParameters );\r
+\r
+/*******************************************************************************\r
+ * vTraceEnable\r
+ *\r
+ * Function that enables the tracing and creates the control task. It will halt\r
+ * execution until a Start command has been received if haltUntilStart is true.\r
+ *\r
+ ******************************************************************************/\r
+void vTraceEnable(int startOption)\r
 {\r
-       return (objectHandleType) ucQueueGetQueueNumber(handle);\r
-}\r
+       int bytes = 0;\r
+       extern uint32_t RecorderEnabled;\r
+       TracealyzerCommandType msg;\r
+\r
+       if (HandleTzCtrl != NULL)\r
+               return; /* Seems we already initiated */\r
+\r
+       TRC_STREAM_PORT_INIT();\r
+\r
+       if (startOption == TRC_START_AWAIT_HOST)\r
+       {\r
+               /* We keep trying to read commands until the recorder has been started */\r
+               do\r
+               {\r
+                       bytes = 0;\r
+                       TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);\r
 \r
+                       if (bytes == sizeof(TracealyzerCommandType))\r
+                       {\r
+                               if (prvIsValidCommand(&msg))\r
+                               {\r
+                                       if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1)\r
+                                       {\r
+                                               /* On start, init and reset the timestamping */\r
+                                               TRC_PORT_SPECIFIC_INIT();\r
+                                       }\r
+\r
+                                       prvProcessCommand(&msg);\r
+                               }\r
+                       }\r
+               }\r
+               while (RecorderEnabled == 0);\r
+       }\r
+       else if (startOption == TRC_START)\r
+       {\r
+               /* We start streaming directly - this assumes that the interface is ready! */\r
+               TRC_PORT_SPECIFIC_INIT();\r
+\r
+               msg.cmdCode = CMD_SET_ACTIVE;\r
+               msg.param1 = 1;\r
+               prvProcessCommand(&msg);\r
+       }\r
+       else\r
+       {\r
+               /* On TRC_INIT */\r
+               TRC_PORT_SPECIFIC_INIT();\r
+       }\r
+\r
+       trcWarningChannel = xTraceRegisterString("Warnings from Recorder");\r
+\r
+       /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */\r
+#if (configSUPPORT_STATIC_ALLOCATION == 1)\r
+       HandleTzCtrl = xTaskCreateStatic(TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);\r
+       (void)HandleTzCtrl;\r
 #else\r
+       xTaskCreate( TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );\r
+#endif\r
+}\r
 \r
-extern portBASE_TYPE uxQueueGetQueueNumber(void*);\r
+/*******************************************************************************\r
+ * prvTraceOnBegin\r
+ *\r
+ * Called on trace begin.\r
+ ******************************************************************************/\r
+void prvTraceOnBegin()\r
+{\r
+       TRC_STREAM_PORT_ON_TRACE_BEGIN();\r
+}\r
 \r
-objectHandleType prvTraceGetObjectNumber(void* handle)\r
+/*******************************************************************************\r
+ * prvTraceOnEnd\r
+ *\r
+ * Called on trace end.\r
+ ******************************************************************************/\r
+void prvTraceOnEnd()\r
 {\r
-       return (objectHandleType) uxQueueGetQueueNumber(handle);\r
+       TRC_STREAM_PORT_ON_TRACE_END();\r
 }\r
 \r
-#endif\r
+/*******************************************************************************\r
+ * vTraceSetQueueName(void* object, const char* name)\r
+ *\r
+ * Parameter object: pointer to the Queue that shall be named\r
+ * Parameter name: the name to set (const string literal)\r
+ *\r
+ * Sets a name for Queue objects for display in Tracealyzer.\r
+ ******************************************************************************/\r
+void vTraceSetQueueName(void* object, const char* name)\r
+{\r
+       vTraceStoreKernelObjectName(object, name);\r
+}\r
 \r
-unsigned char prvTraceGetObjectType(void* handle)\r
+/*******************************************************************************\r
+ * vTraceSetSemaphoreName(void* object, const char* name)\r
+ *\r
+ * Parameter object: pointer to the Semaphore that shall be named\r
+ * Parameter name: the name to set (const string literal)\r
+ *\r
+ * Sets a name for Semaphore objects for display in Tracealyzer.\r
+ ******************************************************************************/\r
+void vTraceSetSemaphoreName(void* object, const char* name)\r
 {\r
-       return ucQueueGetQueueType(handle);\r
+       vTraceStoreKernelObjectName(object, name);\r
 }\r
 \r
-objectHandleType prvTraceGetTaskNumber(void* handle)\r
+/*******************************************************************************\r
+ * vTraceSetMutexName(void* object, const char* name)\r
+ *\r
+ * Parameter object: pointer to the Mutex that shall be named\r
+ * Parameter name: the name to set (const string literal)\r
+ *\r
+ * Sets a name for Semaphore objects for display in Tracealyzer.\r
+ ******************************************************************************/\r
+void vTraceSetMutexName(void* object, const char* name)\r
 {\r
-       return (objectHandleType)uxTaskGetTaskNumber(handle);\r
+       vTraceStoreKernelObjectName(object, name);\r
 }\r
 \r
-unsigned char prvTraceIsSchedulerActive()\r
+/*******************************************************************************\r
+ * prvGetCurrentTaskHandle\r
+ *\r
+ * Function that returns the handle to the currently executing task.\r
+ *\r
+ ******************************************************************************/\r
+void* prvTraceGetCurrentTaskHandle(void)\r
+{\r
+       return xTaskGetCurrentTaskHandle();\r
+}\r
+\r
+/*******************************************************************************\r
+ * prvIsNewTCB\r
+ *\r
+ * Tells if this task is already executing, or if there has been a task-switch.\r
+ * Assumed to be called within a trace hook in kernel context.\r
+ ******************************************************************************/\r
+uint32_t prvIsNewTCB(void* pNewTCB)\r
 {\r
-       return xTaskGetSchedulerState() == taskSCHEDULER_RUNNING;\r
+       if (pCurrentTCB != pNewTCB)\r
+       {\r
+               pCurrentTCB = pNewTCB;\r
+               return 1;\r
+       }\r
+       return 0;\r
 }\r
 \r
+/*******************************************************************************\r
+ * prvTraceIsSchedulerSuspended\r
+ *\r
+ * Returns true if the RTOS scheduler currently is disabled, thus preventing any\r
+ * task-switches from occurring. Only called from vTraceStoreISREnd.\r
+ ******************************************************************************/\r
 unsigned char prvTraceIsSchedulerSuspended()\r
 {\r
+    /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,\r
+       INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in\r
+       FreeRTOSConfig.h for this function to be available. */\r
+\r
        return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;\r
 }\r
 \r
-unsigned char prvTraceIsSchedulerStarted()\r
+\r
+/*******************************************************************************\r
+ * prvCheckRecorderStatus\r
+ *\r
+ * Called by TzCtrl task periodically (every 100 ms - seems reasonable).\r
+ * Checks a number of diagnostic variables and give warnings as user events,\r
+ * in most cases including a suggested solution.\r
+ ******************************************************************************/\r
+static void prvCheckRecorderStatus(void)\r
 {\r
-       return xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;\r
+       if (NoRoomForSymbol > NoRoomForSymbol_last)\r
+       {\r
+               vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_TABLE_SLOTS too small. Add %d slots.",\r
+                       NoRoomForSymbol);\r
+\r
+               NoRoomForSymbol_last = NoRoomForSymbol;\r
+       }\r
+\r
+       if (NoRoomForObjectData > NoRoomForObjectData_last)\r
+       {\r
+               vTracePrintF(trcWarningChannel, "TRC_CFG_OBJECT_DATA_SLOTS too small. Add %d slots.",\r
+                       NoRoomForObjectData);\r
+\r
+               NoRoomForObjectData_last = NoRoomForObjectData;\r
+       }\r
+\r
+       if (LongestSymbolName > LongestSymbolName_last)\r
+       {\r
+               if (LongestSymbolName > TRC_CFG_SYMBOL_MAX_LENGTH)\r
+               {\r
+                       vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_MAX_LENGTH too small. Add %d chars.",\r
+                               LongestSymbolName);\r
+               }\r
+               LongestSymbolName_last = LongestSymbolName;\r
+       }\r
+\r
+       if (MaxBytesTruncated > MaxBytesTruncated_last)\r
+       {\r
+               /* Some string event generated a too long string that was truncated.\r
+               This may happen for the following functions:\r
+               - vTracePrintF\r
+               - vTracePrintF\r
+               - vTraceStoreKernelObjectName\r
+               - vTraceStoreUserEventChannelName\r
+               - vTraceSetISRProperties\r
+\r
+               A PSF event may store maximum 60 bytes payload, including data arguments\r
+               and string characters. For User Events, also the User Event Channel ptr\r
+               must be squeezed in, if a channel is specified. */\r
+\r
+               vTracePrintF(trcWarningChannel, "String event too long, up to %d bytes truncated.",\r
+                       MaxBytesTruncated);\r
+\r
+               MaxBytesTruncated_last = MaxBytesTruncated;\r
+       }\r
+}\r
+\r
+/*******************************************************************************\r
+ * TzCtrl\r
+ *\r
+ * Task for receiving commands from Tracealyzer and for recorder diagnostics.\r
+ *\r
+ ******************************************************************************/\r
+static portTASK_FUNCTION( TzCtrl, pvParameters )\r
+{\r
+       TracealyzerCommandType msg;\r
+       int bytes = 0;\r
+\r
+       (void)pvParameters;\r
+\r
+       while (1)\r
+       {\r
+               do\r
+               {\r
+                       /* Listen for new commands */\r
+                       bytes = 0;\r
+                       TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);\r
+                       if (bytes == sizeof(TracealyzerCommandType))\r
+                       {\r
+                               if (prvIsValidCommand(&msg))\r
+                               {\r
+                                       prvProcessCommand(&msg); /* Start or Stop currently... */\r
+                               }\r
+                       }\r
+\r
+                       /* Send periodic data */\r
+                       bytes = 0;\r
+                       TRC_STREAM_PORT_PERIODIC_SEND_DATA(&bytes);\r
+                       /* If there was data sent (bytes != 0), immediately loop around and do all this again. Otherwise, step out of this loop and sleep for a while. */\r
+               }\r
+               while (bytes != 0);\r
+\r
+               prvCheckRecorderStatus();\r
+               vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);    /* 10ms */\r
+       }\r
+}\r
+\r
+#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/\r
+\r
+\r
+#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)\r
+\r
+/* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */\r
+int uiInEventGroupSetBitsFromISR = 0;\r
+\r
+/******************************************************************************\r
+ * TraceObjectClassTable\r
+ * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).\r
+ * Has one entry for each QueueType, gives TRACE_CLASS ID.\r
+ ******************************************************************************/\r
+traceObjectClass TraceObjectClassTable[5] = {\r
+       TRACE_CLASS_QUEUE,\r
+       TRACE_CLASS_MUTEX,\r
+       TRACE_CLASS_SEMAPHORE,\r
+       TRACE_CLASS_SEMAPHORE,\r
+       TRACE_CLASS_MUTEX\r
+};\r
+\r
+/*******************************************************************************\r
+ * vTraceSetQueueName(void* object, const char* name)\r
+ *\r
+ * Parameter object: pointer to the Queue that shall be named\r
+ * Parameter name: the name to set (const string literal)\r
+ *\r
+ * Sets a name for Queue objects for display in Tracealyzer.\r
+ ******************************************************************************/\r
+void vTraceSetQueueName(void* object, const char* name)\r
+{\r
+       prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);\r
+}\r
+\r
+/*******************************************************************************\r
+ * vTraceSetSemaphoreName(void* object, const char* name)\r
+ *\r
+ * Parameter object: pointer to the Semaphore that shall be named\r
+ * Parameter name: the name to set (const string literal)\r
+ *\r
+ * Sets a name for Semaphore objects for display in Tracealyzer.\r
+ ******************************************************************************/\r
+void vTraceSetSemaphoreName(void* object, const char* name)\r
+{\r
+       prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);\r
+}\r
+\r
+/*******************************************************************************\r
+ * vTraceSetMutexName(void* object, const char* name)\r
+ *\r
+ * Parameter object: pointer to the Mutex that shall be named\r
+ * Parameter name: the name to set (const string literal)\r
+ *\r
+ * Sets a name for Semaphore objects for display in Tracealyzer.\r
+ ******************************************************************************/\r
+void vTraceSetMutexName(void* object, const char* name)\r
+{\r
+       prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);\r
 }\r
 \r
 void* prvTraceGetCurrentTaskHandle()\r
@@ -109,24 +454,46 @@ void* prvTraceGetCurrentTaskHandle()
        return xTaskGetCurrentTaskHandle();\r
 }\r
 \r
+#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)\r
+traceHandle prvTraceGetObjectNumber(void* handle)\r
+{\r
+       return (traceHandle) ucQueueGetQueueNumber(handle);\r
+}\r
+#else /* For FreeRTOS v8 and later */\r
+traceHandle prvTraceGetObjectNumber(void* handle)\r
+{\r
+       return (traceHandle) uxQueueGetQueueNumber(handle);\r
+}\r
+#endif\r
+\r
+uint8_t prvTraceGetObjectType(void* handle)\r
+{\r
+       return ucQueueGetQueueType(handle);\r
+}\r
+\r
+traceHandle prvTraceGetTaskNumber(void* handle)\r
+{\r
+       return (traceHandle)uxTaskGetTaskNumber(handle);\r
+}\r
+\r
 /* Initialization of the object property table */\r
 void vTraceInitObjectPropertyTable()\r
 {\r
        RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES;\r
-       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = NQueue;\r
-       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = NSemaphore;\r
-       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = NMutex;\r
-       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = NTask;\r
-       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = NISR;\r
-       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = NTimer;\r
-       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = NEventGroup;\r
-       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = NameLenQueue;\r
-       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = NameLenSemaphore;\r
-       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = NameLenMutex;\r
-       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = NameLenTask;\r
-       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = NameLenISR;\r
-       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = NameLenTimer;\r
-       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = NameLenEventGroup;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = TRC_CFG_NQUEUE;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = TRC_CFG_NSEMAPHORE;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = TRC_CFG_NMUTEX;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = TRC_CFG_NTASK;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = TRC_CFG_NAME_LEN_TASK;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP;\r
        RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;\r
        RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;\r
        RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;\r
@@ -144,24 +511,24 @@ void vTraceInitObjectPropertyTable()
        RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;\r
 }\r
 \r
-/* Initialization of the handle mechanism, see e.g, xTraceGetObjectHandle */\r
+/* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */\r
 void vTraceInitObjectHandleStack()\r
 {\r
        objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;\r
-       objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = NQueue;\r
-       objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = NQueue + NSemaphore;\r
-       objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = NQueue + NSemaphore + NMutex;\r
-       objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask;\r
-       objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR;\r
-       objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer;\r
-\r
-       objectHandleStacks.highestIndexOfClass[0] = NQueue - 1;\r
-       objectHandleStacks.highestIndexOfClass[1] = NQueue + NSemaphore - 1;\r
-       objectHandleStacks.highestIndexOfClass[2] = NQueue + NSemaphore + NMutex - 1;\r
-       objectHandleStacks.highestIndexOfClass[3] = NQueue + NSemaphore + NMutex + NTask - 1;\r
-       objectHandleStacks.highestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask + NISR - 1;\r
-       objectHandleStacks.highestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer - 1;\r
-       objectHandleStacks.highestIndexOfClass[6] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer + NEventGroup - 1;\r
+       objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = TRC_CFG_NQUEUE;\r
+       objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE;\r
+       objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX;\r
+       objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK;\r
+       objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR;\r
+       objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR + TRC_CFG_NTIMER;\r
+\r
+       objectHandleStacks.highestIndexOfClass[0] = TRC_CFG_NQUEUE - 1;\r
+       objectHandleStacks.highestIndexOfClass[1] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE - 1;\r
+       objectHandleStacks.highestIndexOfClass[2] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX - 1;\r
+       objectHandleStacks.highestIndexOfClass[3] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK - 1;\r
+       objectHandleStacks.highestIndexOfClass[4] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR - 1;\r
+       objectHandleStacks.highestIndexOfClass[5] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR + TRC_CFG_NTIMER - 1;\r
+       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;\r
 }\r
 \r
 /* Returns the "Not enough handles" error message for this object class */\r
@@ -170,50 +537,69 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
        switch(objectclass)\r
        {\r
        case TRACE_CLASS_TASK:\r
-               return "Not enough TASK handles - increase NTask in trcConfig.h";\r
+               return "Not enough TASK handles - increase TRC_CFG_NTASK in trcSnapshotConfig.h";\r
        case TRACE_CLASS_ISR:\r
-               return "Not enough ISR handles - increase NISR in trcConfig.h";\r
+               return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h";\r
        case TRACE_CLASS_SEMAPHORE:\r
-               return "Not enough SEMAPHORE handles - increase NSemaphore in trcConfig.h";\r
+               return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h";\r
        case TRACE_CLASS_MUTEX:\r
-               return "Not enough MUTEX handles - increase NMutex in trcConfig.h";\r
+               return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h";\r
        case TRACE_CLASS_QUEUE:\r
-               return "Not enough QUEUE handles - increase NQueue in trcConfig.h";\r
+               return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h";\r
        case TRACE_CLASS_TIMER:\r
-               return "Not enough TIMER handles - increase NTimer in trcConfig.h";\r
+               return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h";\r
        case TRACE_CLASS_EVENTGROUP:\r
-               return "Not enough EVENTGROUP handles - increase NEventGroup in trcConfig.h";\r
+               return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h";\r
        default:\r
                return "pszTraceGetErrorHandles: Invalid objectclass!";\r
        }\r
 }\r
 \r
 /* Returns the exclude state of the object */\r
-uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, objectHandleType handle)\r
+uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, traceHandle handle)\r
 {\r
-       TRACE_ASSERT(objectclass < TRACE_NCLASSES, "prvTraceIsObjectExcluded: objectclass >= TRACE_NCLASSES", 1);\r
-       TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceIsObjectExcluded: Invalid value for handle", 1);\r
+       TRACE_ASSERT(objectclass < TRACE_NCLASSES, "prvIsObjectExcluded: objectclass >= TRACE_NCLASSES", 1);\r
+       TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "prvIsObjectExcluded: Invalid value for handle", 1);\r
 \r
        switch(objectclass)\r
        {\r
        case TRACE_CLASS_TASK:\r
-               return TRACE_GET_TASK_FLAG_ISEXCLUDED(handle);\r
+               return (uint8_t) TRACE_GET_TASK_FLAG_ISEXCLUDED(handle);\r
        case TRACE_CLASS_SEMAPHORE:\r
-               return TRACE_GET_SEMAPHORE_FLAG_ISEXCLUDED(handle);\r
+               return (uint8_t) TRACE_GET_SEMAPHORE_FLAG_ISEXCLUDED(handle);\r
        case TRACE_CLASS_MUTEX:\r
-               return TRACE_GET_MUTEX_FLAG_ISEXCLUDED(handle);\r
+               return (uint8_t) TRACE_GET_MUTEX_FLAG_ISEXCLUDED(handle);\r
        case TRACE_CLASS_QUEUE:\r
-               return TRACE_GET_QUEUE_FLAG_ISEXCLUDED(handle);\r
+               return (uint8_t) TRACE_GET_QUEUE_FLAG_ISEXCLUDED(handle);\r
        case TRACE_CLASS_TIMER:\r
-               return TRACE_GET_TIMER_FLAG_ISEXCLUDED(handle);\r
+               return (uint8_t) TRACE_GET_TIMER_FLAG_ISEXCLUDED(handle);\r
        case TRACE_CLASS_EVENTGROUP:\r
-               return TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(handle);\r
+               return (uint8_t) TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(handle);\r
        }\r
 \r
-       vTraceError("Invalid object class ID in uiTraceIsObjectExcluded!");\r
+       prvTraceError("Invalid object class ID in prvIsObjectExcluded!");\r
 \r
        /* Must never reach */\r
        return 1;\r
 }\r
 \r
-#endif
\ No newline at end of file
+/*******************************************************************************\r
+ * prvTraceIsSchedulerSuspended\r
+ *\r
+ * Returns true if the RTOS scheduler currently is disabled, thus preventing any\r
+ * task-switches from occurring. Only called from vTraceStoreISREnd.\r
+ ******************************************************************************/\r
+#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)\r
+unsigned char prvTraceIsSchedulerSuspended()\r
+{\r
+    /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,\r
+       INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in\r
+       FreeRTOSConfig.h for this function to be available. */\r
+\r
+       return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;\r
+}\r
+#endif\r
+\r
+#endif /* Snapshot mode */\r
+\r
+#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/\r