]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcUser.c
+ New feature added: Task notifications.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace / trcUser.c
index 114ac1ec7310c6c203af0058b0f91c590320c8e5..57c53ffbca848973f108a4a20d364ffebeb757c2 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.4.1 Recorder Library\r
+ * Tracealyzer v2.7.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcUser.c\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
  *\r
- * Copyright Percepio AB, 2013.\r
+ * Tabs are used for indent in this file (1 tab = 4 spaces)\r
+ *\r
+ * Copyright Percepio AB, 2014.\r
  * www.percepio.com\r
  ******************************************************************************/\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
 \r
 #include "trcUser.h"\r
 \r
@@ -47,14 +51,14 @@ TRACE_STOP_HOOK vTraceStopHookPtr = (TRACE_STOP_HOOK)0;
 \r
 extern uint8_t inExcludedTask;\r
 extern uint8_t nISRactive;\r
-extern uint8_t handle_of_last_logged_task;\r
+extern objectHandleType handle_of_last_logged_task;\r
 extern uint32_t dts_min;\r
 extern uint32_t hwtc_count_max_after_tick;\r
 extern uint32_t hwtc_count_sum_after_tick;\r
 extern uint32_t hwtc_count_sum_after_tick_counter;\r
 extern char* traceErrorMessage;\r
 \r
-/*** private functions *******************************************************/\r
+/*** Private functions *******************************************************/\r
 void vTracePrintF_Helper(traceLabel eventLabel, const char* formatStr, va_list vl);\r
 \r
 #if (USE_SEPARATE_USER_EVENT_BUFFER == 1)\r
@@ -62,8 +66,8 @@ void vTraceChannelPrintF_Helper(UserEventChannel channelPair, va_list vl);
 static void prvTraceUserEventHelper1(UserEventChannel channel, traceLabel eventLabel, traceLabel formatLabel, va_list vl);\r
 static void prvTraceUserEventHelper2(UserEventChannel channel, uint32_t* data, uint32_t noOfSlots);\r
 #endif\r
-/*****************************************************************************/\r
 \r
+static void prvTraceTaskInstanceFinish(int8_t direct);\r
 \r
 \r
 /*******************************************************************************\r
@@ -91,6 +95,16 @@ void vTraceSetRecorderData(void* pRecorderData)
 }\r
 #endif\r
 \r
+/*******************************************************************************\r
+ * vTraceSetStopHook\r
+ *\r
+ * Sets a function to be called when the recorder is stopped.\r
+ ******************************************************************************/\r
+void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction)\r
+{\r
+       vTraceStopHookPtr = stopHookFunction;\r
+}\r
+\r
 /*******************************************************************************\r
  * vTraceClear\r
  *\r
@@ -99,14 +113,21 @@ void vTraceSetRecorderData(void* pRecorderData)
  ******************************************************************************/\r
 void vTraceClear(void)\r
 {\r
-    trcCRITICAL_SECTION_BEGIN();\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+       trcCRITICAL_SECTION_BEGIN();\r
 \r
-    RecorderDataPtr->absTimeLastEvent = 0;\r
-    RecorderDataPtr->nextFreeIndex = 0;\r
-    RecorderDataPtr->numEvents = 0;\r
-    RecorderDataPtr->bufferIsFull = 0;\r
+       RecorderDataPtr->absTimeLastEventSecond = 0;\r
 \r
-    trcCRITICAL_SECTION_END();\r
+       RecorderDataPtr->absTimeLastEvent = 0;\r
+       RecorderDataPtr->nextFreeIndex = 0;\r
+       RecorderDataPtr->numEvents = 0;\r
+       RecorderDataPtr->bufferIsFull = 0;\r
+       traceErrorMessage = NULL;\r
+       RecorderDataPtr->internalErrorOccured = 0;\r
+\r
+       memset(RecorderDataPtr->eventData, 0, RecorderDataPtr->maxEvents * 4);\r
+\r
+       trcCRITICAL_SECTION_END();\r
 \r
 }\r
 \r
@@ -125,17 +146,21 @@ void vTraceClear(void)
 \r
 uint32_t uiTraceStart(void)\r
 {\r
-       objectHandleType handle = 0;\r
+       objectHandleType handle;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+\r
+       handle = 0;\r
 \r
        if (RecorderDataPtr == NULL)\r
        {\r
                vTraceError("RecorderDataPtr is NULL. Call vTraceInitTraceData() before starting trace.");\r
                return 0;\r
        }\r
-    if (traceErrorMessage == NULL)\r
-    {\r
-        trcCRITICAL_SECTION_BEGIN();\r
-        RecorderDataPtr->recorderActive = 1;\r
+\r
+       if (traceErrorMessage == NULL)\r
+       {\r
+               trcCRITICAL_SECTION_BEGIN();\r
+               RecorderDataPtr->recorderActive = 1;\r
 \r
                handle = TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK());\r
                if (handle == 0)\r
@@ -149,11 +174,11 @@ uint32_t uiTraceStart(void)
                        vTraceSetPriorityProperty(TRACE_CLASS_TASK, handle, 0);\r
                }\r
 \r
-        vTraceStoreTaskswitch(handle); /* Register the currently running task */\r
-        trcCRITICAL_SECTION_END();\r
-    }\r
+               vTraceStoreTaskswitch(handle); /* Register the currently running task */\r
+               trcCRITICAL_SECTION_END();\r
+       }\r
 \r
-    return RecorderDataPtr->recorderActive;\r
+       return RecorderDataPtr->recorderActive;\r
 }\r
 \r
 /*******************************************************************************\r
@@ -168,7 +193,7 @@ uint32_t uiTraceStart(void)
  ******************************************************************************/\r
 void vTraceStart(void)\r
 {\r
-    (void)uiTraceStart();\r
+       (void)uiTraceStart();\r
 }\r
 \r
 /*******************************************************************************\r
@@ -179,11 +204,11 @@ void vTraceStart(void)
  ******************************************************************************/\r
 void vTraceStop(void)\r
 {\r
-    RecorderDataPtr->recorderActive = 0;\r
-       \r
+       RecorderDataPtr->recorderActive = 0;\r
+\r
        if (vTraceStopHookPtr != (TRACE_STOP_HOOK)0)\r
        {\r
-               (*vTraceStopHookPtr)();                      /* Call an application level call back function. */\r
+               (*vTraceStopHookPtr)();                 /* An application call-back function. */\r
        }\r
 }\r
 \r
@@ -191,7 +216,6 @@ void vTraceStop(void)
  * xTraceGetLastError\r
  *\r
  * Gives the last error message, if any. NULL if no error message is stored.\r
- * The message is cleared on read.\r
  * Any error message is also presented when opening a trace file.\r
  ******************************************************************************/\r
 char* xTraceGetLastError(void)\r
@@ -199,6 +223,21 @@ char* xTraceGetLastError(void)
        return traceErrorMessage;\r
 }\r
 \r
+/*******************************************************************************\r
+* vTraceClearError\r
+*\r
+* Removes any previous error message generated by recorder calling vTraceError.\r
+* By calling this function, it may be possible to start/restart the trace\r
+* despite errors in the recorder, but there is no guarantee that the trace\r
+* recorder will work correctly in that case, depending on the type of error.\r
+******************************************************************************/\r
+void vTraceClearError(int resetErrorMessage)\r
+{\r
+       ( void ) resetErrorMessage;\r
+       traceErrorMessage = NULL;\r
+       RecorderDataPtr->internalErrorOccured = 0;\r
+}\r
+\r
 /*******************************************************************************\r
  * vTraceGetTraceBuffer\r
  *\r
@@ -209,7 +248,7 @@ char* xTraceGetLastError(void)
  ******************************************************************************/\r
 void* vTraceGetTraceBuffer(void)\r
 {\r
-    return RecorderDataPtr;\r
+       return RecorderDataPtr;\r
 }\r
 \r
 /*******************************************************************************\r
@@ -221,23 +260,101 @@ void* vTraceGetTraceBuffer(void)
  ******************************************************************************/\r
 uint32_t uiTraceGetTraceBufferSize(void)\r
 {\r
-    return sizeof(RecorderDataType);\r
+       return sizeof(RecorderDataType);\r
 }\r
 \r
 /******************************************************************************\r
- * vTraceTaskInstanceIsFinished\r
+ * prvTraceTaskInstanceFinish.\r
  *\r
- * This defines an explicit Instance Finish Event for the current task. It tells\r
- * the recorder that the current instance of this task is finished at the \r
- * context-switch. This function should be called right before the API function \r
- * call considered to be the Instance Finish Event.\r
+ * Private common function for the vTraceTaskInstanceFinishXXX functions.\r
+ * \r
  *****************************************************************************/\r
-void vTraceTaskInstanceIsFinished()\r
+void prvTraceTaskInstanceFinish(int8_t direct)\r
 {\r
-    if (handle_of_last_logged_task)\r
-    {\r
-               TRACE_PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle_of_last_logged_task) = 0;\r
-    }\r
+       TaskInstanceStatusEvent* tis;\r
+       uint8_t dts45;\r
+\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+\r
+       trcCRITICAL_SECTION_BEGIN();\r
+       if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
+       {\r
+               dts45 = (uint8_t)prvTraceGetDTS(0xFF);\r
+               tis = (TaskInstanceStatusEvent*) xTraceNextFreeEventBufferSlot();\r
+               if (tis != NULL)\r
+               {\r
+                       if (direct == 0)\r
+                               tis->type = TASK_INSTANCE_FINISHED_NEXT_KSE;\r
+                       else\r
+                               tis->type = TASK_INSTANCE_FINISHED_DIRECT;\r
+\r
+                       tis->dts = dts45;\r
+                       prvTraceUpdateCounters();\r
+               }\r
+       }\r
+       trcCRITICAL_SECTION_END();\r
+}\r
+\r
+/******************************************************************************\r
+ * vTraceTaskInstanceFinish(void)\r
+ *\r
+ * Marks the current task instance as finished on the next kernel call.\r
+ *\r
+ * If that kernel call is blocking, the instance ends after the blocking event\r
+ * and the corresponding return event is then the start of the next instance.\r
+ * If the kernel call is not blocking, the viewer instead splits the current\r
+ * fragment right before the kernel call, which makes this call the first event\r
+ * of the next instance.\r
+ *\r
+ * See also USE_IMPLICIT_IFE_RULES in trcConfig.h\r
+ *\r
+ * Example:\r
+ *\r
+ *             while(1)\r
+ *             {\r
+ *                     xQueueReceive(CommandQueue, &command, timeoutDuration);\r
+ *                     processCommand(command);\r
+ *          vTraceInstanceFinish();\r
+ *             }\r
+ *\r
+ * Note: This is only supported in Tracealyzer tools v2.7 or later\r
+ *\r
+ *****************************************************************************/\r
+void vTraceTaskInstanceFinish(void)\r
+{\r
+    prvTraceTaskInstanceFinish(0);\r
+}\r
+\r
+/******************************************************************************\r
+ * vTraceTaskInstanceFinishDirect(void)\r
+ *\r
+ * Marks the current task instance as finished at this very instant.\r
+ * This makes the viewer to splits the current fragment at this point and begin\r
+ * a new actor instance.\r
+ *\r
+ * See also USE_IMPLICIT_IFE_RULES in trcConfig.h\r
+ *\r
+ * Example:\r
+ *\r
+ *             This example will generate two instances for each loop iteration.\r
+ *             The first instance ends at vTraceInstanceFinishDirect(), while the second\r
+ *      instance ends at the next xQueueReceive call.\r
+ *\r
+ *             while (1)\r
+ *             {\r
+ *          xQueueReceive(CommandQueue, &command, timeoutDuration);\r
+ *                     ProcessCommand(command);\r
+ *                     vTraceInstanceFinishDirect();\r
+ *                     DoSometingElse();\r
+ *          vTraceInstanceFinish();\r
+ *      }\r
+ *\r
+ * Note: This is only supported in Tracealyzer tools v2.7 or later\r
+ *\r
+ *****************************************************************************/\r
+void vTraceTaskInstanceFinishDirect(void)\r
+{\r
+       prvTraceTaskInstanceFinish(1);\r
 }\r
 \r
 /*******************************************************************************\r
@@ -258,17 +375,17 @@ static uint8_t isrstack[MAX_ISR_NESTING];
  * started.\r
  *\r
  * Example:\r
- *     #define ID_ISR_TIMER1 1       // lowest valid ID is 1\r
- *     #define PRIO_OF_ISR_TIMER1 3  // the hardware priority of the interrupt\r
- *     ...\r
- *     vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);\r
- *     ...\r
- *     void ISR_handler()\r
- *     {\r
- *         vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
- *         ...\r
- *         vTraceStoreISREnd();\r
- *     }\r
+ *      #define ID_ISR_TIMER1 1                // lowest valid ID is 1\r
+ *      #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt\r
+ *      ...\r
+ *      vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);\r
+ *      ...\r
+ *      void ISR_handler()\r
+ *      {\r
+ *              vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
+ *              ...\r
+ *              vTraceStoreISREnd(0);\r
+ *      }\r
  *\r
  * NOTE: To safely record ISRs, you need to make sure that all traced\r
  * interrupts actually are disabled by trcCRITICAL_SECTION_BEGIN(). However,\r
@@ -280,183 +397,290 @@ void vTraceSetISRProperties(objectHandleType handle, const char* name, char prio
 {\r
        TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceSetISRProperties: Invalid value for handle", );\r
        TRACE_ASSERT(name != NULL, "vTraceSetISRProperties: name == NULL", );\r
-       TRACE_ASSERT(priority >= 0, "vTraceSetISRProperties: Invalid value for priority", );\r
 \r
-    vTraceSetObjectName(TRACE_CLASS_ISR, handle, name);\r
-    vTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority);\r
+       vTraceSetObjectName(TRACE_CLASS_ISR, handle, name);\r
+       vTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority);\r
 }\r
 \r
+#if (SELECTED_PORT == PORT_ARM_CortexM)\r
+/******************************************************************************\r
+ * (Advanced...)\r
+ *\r
+ * ISR_TAILCHAINING_THRESHOLD (For Cortex-M devices only)\r
+ *\r
+ * ARM Cortex-M devices may execute ISRs back-to-back (tail-chained) without\r
+ * resuming the previous context in between. Since this is decided in\r
+ * hardware, we can only detect this indirectly, in the following manner:\r
+ *\r
+ * When entering vTraceStoreISRBegin, we check the number of CPU cycles since\r
+ * the last return of vTraceStoreISREnd. If less or equal to the constant\r
+ * ISR_TAILCHAINING_THRESHOLD it is assumed that the ISRs executed back-to-back\r
+ * (tail-chained). In that case, the previously stored RESUME event\r
+ * (pointed to by ptrLastISRExitEvent) is then deleted to avoid showing a\r
+ * fragment of the previous context in between the ISR events. The delete is\r
+ * made by replacing the event code with a XTS16L event, that serves to keep\r
+ * the differential timestamp from the earlier event.\r
+ *\r
+ * The value of ISR_TAILCHAINING_THRESHOLD depends on the interrupt latency of\r
+ * the processor, on the compiler and on the compiler settings, but should be\r
+ * around 70 cycles. The default value is 66 cycles, which should be correct when\r
+ * using GCC with optimizations disabled (-O0) and Cortex-M3/M4.\r
+ *\r
+ * To measure this value, see MEASURE_ISR_TAILCHAINING_THRESHOLD below.\r
+ *\r
+ * If this value set too low, tail-chained ISRs will incorrectly be shown\r
+ * separated, with a short fragment of the previous task or ISR in between.\r
+ * If this value is set too high, you get the opposite effect - separate ISRs\r
+ * will appear to execute tail-chained and will appear to have higher execution\r
+ * time and response time (maximum ISR_TAILCHAINING_THRESHOLD cycles more).\r
+ *\r
+ * Read the blog post explaining this on our website:\r
+ * http://percepio.com/2014/05/06/sw-based-exc-tracing-arm-cortex-m/\r
+ *\r
+ *****************************************************************************/\r
+#define ISR_TAILCHAINING_THRESHOLD 66\r
+\r
+uint8_t* ptrLastISRExitEvent = NULL;\r
+uint32_t DWTCycleCountAtLastISRExit = 0;\r
+\r
+/******************************************************************************\r
+ * (Advanced...)\r
+ *\r
+ * MEASURE_ISR_TAILCHAINING_THRESHOLD (For Cortex-M devices only)\r
+ *\r
+ * Allows for calibrating the value of ISR_TAILCHAINING_THRESHOLD (see above).\r
+ *\r
+ * This is intended to measure the minimum number of clock cycles from the end\r
+ * of vTraceStoreISREnd to the beginning of the following vTraceStoreISRBegin.\r
+ * For this purpose, we assume a test setup using the SysTick interrupt, which\r
+ * is available on most Cortex-M devices and typically used by the RTOS kernel.\r
+ * To do the measurement, follow these steps:\r
+ *\r
+ * 1. Make sure MEASURE_ISR_TAILCHAINING_THRESHOLD is enabled (defined as 1)\r
+ *\r
+ * 2. Temporarily replace your SysTick handler with the following:\r
+ *\r
+ *     void xPortSysTickHandler( void )\r
+ *     {\r
+ *             vTraceStoreISRBegin(1);\r
+ *             vTraceStoreISREnd(0);\r
+ *     }\r
+ *\r
+ * 3. To make sure that the ISRs execute back-to-back, increase the OS tick\r
+ *     frequency to a very high level so that the OS tick interrupt execute\r
+ *     continuously with no application tasks in between, e.g. 10 MHz.\r
+ *\r
+ * 4. Put a breakpoint in the highest priority task and make sure it is not\r
+ *     reached. This means that the SysTick handler is executing at maximum rate\r
+ *     and thereby tail-chained, where the interrupt latency is 6 cycles.\r
+ *\r
+ * 5. Let the system run without breakpoints and inspect the value of\r
+ *     threshold_low_watermark. This is the minimum total latency observed.\r
+ *     The hardware latency is 6 clock cycles due to the tail-chaining, so the\r
+ *     software latency (SL) is then SL = threshold_low_watermark - 6.\r
+ *\r
+ * The threshold value ISR_TAILCHAINING_THRESHOLD should be SL + 2 * HL, where\r
+ * HL is the normal hardware interrupt latency, i.e., the number of CPU\r
+ * cycles to enter or exit the exception handler for an exception in task\r
+ * context. The HL value is 12-16 depending on core, as shown below.\r
+ *\r
+ * Values for ISR_TAILCHAINING_THRESHOLD, assuming SL = 42\r
+ *     Cortex-M3 and M4 (HL = 12):     66 cycles\r
+ *     Cortex-M0 (HL = 16):            74 cycles\r
+ *     Cortex-M0+ (HL = 15):           72 cycles\r
+ *\r
+ * If the ISR_TAILCHAINING_THRESHOLD value is set too low, some tail-chained\r
+ * ISRs be shown separated, with a short fragment of the previous context\r
+ * in between. On the other hand, if the value is set too high, ISRs that \r
+ * actually are separated may appear to execute back-to-back (tail-chained).\r
+ *\r
+ * Read the blog post explaining this on our website:\r
+ * http://percepio.com/2014/05/06/sw-based-exc-tracing-arm-cortex-m/\r
+ *\r
+ *****************************************************************************/\r
+#define MEASURE_ISR_TAILCHAINING_THRESHOLD 1\r
+\r
+#if (MEASURE_ISR_TAILCHAINING_THRESHOLD == 1)\r
+volatile uint32_t threshold_low_watermark = 2000000000;\r
+#endif\r
+\r
+#endif\r
+\r
 /*******************************************************************************\r
  * vTraceStoreISRBegin\r
  *\r
  * Registers the beginning of an Interrupt Service Routine.\r
  *\r
  * Example:\r
- *     #define ID_ISR_TIMER1 1       // lowest valid ID is 1\r
- *     #define PRIO_OF_ISR_TIMER1 3  // the hardware priority of the interrupt\r
- *     ...\r
- *     vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);\r
- *     ...\r
- *     void ISR_handler()\r
- *     {\r
- *         vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
- *         ...\r
- *         vTraceStoreISREnd();\r
- *     }\r
- *\r
- * NOTE: You need to make sure that any traced interrupts actually are\r
- * disabled by trcCRITICAL_SECTION_BEGIN().\r
- * If an invalid call to vTraceStoreISRBegin is detected (i.e., that preempted\r
- * a critical section of the recorder) this will generate a recorder error\r
- * using vTraceError.\r
+ *      #define ID_ISR_TIMER1 1                // lowest valid ID is 1\r
+ *      #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt\r
+ *      ...\r
+ *      vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);\r
+ *      ...\r
+ *      void ISR_handler()\r
+ *      {\r
+ *              vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
+ *              ...\r
+ *              vTraceStoreISREnd(0);\r
+ *      }\r
+ *\r
  ******************************************************************************/\r
 void vTraceStoreISRBegin(objectHandleType handle)\r
 {\r
-    uint16_t dts4;\r
-    TSEvent* ts = NULL;\r
-\r
-    TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", );\r
-\r
-    if (recorder_busy)\r
-    {\r
-      vTraceError("Illegal call to vTraceStoreISRBegin, recorder busy!");\r
-      return;\r
-    }\r
-    if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
-    {\r
-        trcCRITICAL_SECTION_BEGIN();\r
-        dts4 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
-\r
-        if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
-        {\r
-\r
-            if (nISRactive < MAX_ISR_NESTING)\r
-            {\r
-                isrstack[nISRactive] = handle;\r
-                nISRactive++;\r
-                ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
-                if (ts != NULL)\r
-                {\r
-                    ts->type = TS_ISR_BEGIN;\r
-                    ts->dts = dts4;\r
-                    ts->objHandle = handle;\r
-                    prvTraceUpdateCounters();\r
-                }\r
-            }\r
-            else\r
-            {\r
-                /* This should not occur unless something is very wrong */\r
-                vTraceError("Too many nested interrupts!");\r
-            }\r
-        }\r
-        trcCRITICAL_SECTION_END();\r
-    }\r
-}\r
+       uint16_t dts4;\r
+       #if (SELECTED_PORT == PORT_ARM_CortexM)\r
+       uint32_t CPUCyclesSinceLastISRExit = REG_DWT_CYCCNT - DWTCycleCountAtLastISRExit;\r
+       #endif\r
+       TSEvent* ts;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
 \r
+       ts = NULL;\r
 \r
 #if (SELECTED_PORT == PORT_ARM_CortexM)\r
+       if (DWTCycleCountAtLastISRExit > 0)\r
+       {\r
+               #if (MEASURE_ISR_TAILCHAINING_THRESHOLD == 1)\r
+               /* Allows for verifying the value of ISR_TAILCHAINING_THRESHOLD */\r
+               if (CPUCyclesSinceLastISRExit < threshold_low_watermark)\r
+               {\r
+                       threshold_low_watermark = CPUCyclesSinceLastISRExit;\r
+               }\r
+               #endif\r
 \r
-static int tailchain_irq_pending(void);\r
+               if (CPUCyclesSinceLastISRExit <= ISR_TAILCHAINING_THRESHOLD)\r
+               {\r
+                       /* This is judged to be a case of ISR tail-chaining since the\r
+                       number of cycles since the last vTraceStoreISREnd is shorter or equal to\r
+                       the threshold (ISR_TAILCHAINING_THRESHOLD) */\r
 \r
-/*******************************************************************************\r
- * tailchain_irq_pending\r
- *\r
- * For Cortex-M chips only. Returns 1 if an interrupt is pending, by checking\r
- * the 8 NVIC IRQ pend registers at 0xE000E200 to 0xE000E21C. Returns 0 if no\r
- * interrupt is pending. This is used to predict tailchaining of ISRs.\r
- ******************************************************************************/\r
-static int tailchain_irq_pending(void)\r
-{\r
-  uint32_t* pend_reg = ((uint32_t*)0xE000E200);\r
-  int i;\r
-\r
-  for (i=0; i<8; i++)\r
-  {\r
-    if (pend_reg[i] != 0)\r
-    {\r
-      return 1;\r
-    }\r
-  }\r
-  return 0;\r
-}\r
+                       if (ptrLastISRExitEvent != NULL)\r
+                       {\r
+                               /* Overwrite the last ISR exit event with a "neutral" event that only\r
+                                       accounts for the time passed */\r
+                               *ptrLastISRExitEvent = XTS16L;\r
+                       }\r
+               }\r
 \r
+       }\r
 #endif\r
 \r
+       if (recorder_busy)\r
+       {\r
+        vTraceError("Illegal call to vTraceStoreISRBegin, recorder busy!");\r
+        return;\r
+       }\r
+       trcCRITICAL_SECTION_BEGIN();\r
+       if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
+       {\r
+\r
+               TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", );\r
+\r
+               dts4 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
+\r
+               if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
+               {\r
+                       if (nISRactive < MAX_ISR_NESTING)\r
+                       {\r
+                               uint8_t hnd8 = prvTraceGet8BitHandle(handle);\r
+                               isrstack[nISRactive] = handle;\r
+                               nISRactive++;\r
+                               ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
+                               if (ts != NULL)\r
+                               {\r
+                                       ts->type = TS_ISR_BEGIN;\r
+                                       ts->dts = dts4;\r
+                                       ts->objHandle = hnd8;\r
+                                       prvTraceUpdateCounters();\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /* This should not occur unless something is very wrong */\r
+                               vTraceError("Too many nested interrupts!");\r
+                       }\r
+               }\r
+       }\r
+       trcCRITICAL_SECTION_END();\r
+}\r
+\r
 /*******************************************************************************\r
  * vTraceStoreISREnd\r
  *\r
  * Registers the end of an Interrupt Service Routine.\r
  *\r
+ * The parameter pendingISR indicates if the interrupt has requested a\r
+ * task-switch (= 1) or if the interrupt returns to the earlier context (= 0)\r
+ *\r
  * Example:\r
- *     #define ID_ISR_TIMER1 1       // lowest valid ID is 1\r
- *     #define PRIO_OF_ISR_TIMER1 3  // the hardware priority of the interrupt\r
- *     ...\r
- *     vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);\r
- *     ...\r
- *     void ISR_handler()\r
- *     {\r
- *         vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
- *         ...\r
- *         vTraceStoreISREnd();\r
- *     }\r
- *\r
- * NOTE: You need to make sure that any traced interrupts actually are\r
- * disabled by trcCRITICAL_SECTION_BEGIN().\r
- * If an invalid call to vTraceStoreISREnd is detected (i.e., that preempted\r
- * a critical section of the recorder) this will generate a recorder error\r
- * using vTraceError.\r
+ *\r
+ *      #define ID_ISR_TIMER1 1                // lowest valid ID is 1\r
+ *      #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt\r
+ *      ...\r
+ *      vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);\r
+ *      ...\r
+ *      void ISR_handler()\r
+ *      {\r
+ *              vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
+ *              ...\r
+ *              vTraceStoreISREnd(0);\r
+ *      }\r
+ *\r
  ******************************************************************************/\r
-void vTraceStoreISREnd(void)\r
+void vTraceStoreISREnd(int pendingISR)\r
 {\r
-    TSEvent* ts;\r
-    uint16_t dts5;\r
-\r
-    if (recorder_busy)\r
-    {\r
-      vTraceError("Illegal call to vTraceStoreISREnd, recorder busy!");\r
-      return;\r
-    }\r
-\r
-    if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
-    {\r
-        #if (SELECTED_PORT == PORT_ARM_CortexM)\r
-        if (tailchain_irq_pending() > 0)\r
-        {\r
-            nISRactive--; /* If an IRQ strikes exactly here, the resulting\r
-            ISR tailchaining is not detected. The trace instead shows a very\r
-            short fragment of the earlier preempted task/ISR, and then the new\r
-            ISR begins. */\r
-            return;\r
-        }\r
-        #endif\r
-\r
-        trcCRITICAL_SECTION_BEGIN();\r
-        dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
-\r
-        if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
-        {\r
-            ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
-            if (ts != NULL)\r
-            {\r
-                if (nISRactive > 1)\r
-                {\r
-                    /* return to another isr */\r
-                    ts->type = TS_ISR_RESUME;\r
-                    ts->objHandle = isrstack[nISRactive];\r
-                }\r
-                else\r
-                {\r
-                    /* return to task */\r
-                    ts->type = TS_TASK_RESUME;\r
-                    ts->objHandle = handle_of_last_logged_task;\r
-                }\r
-                ts->dts = dts5;\r
-                nISRactive--;\r
-                prvTraceUpdateCounters();\r
-            }\r
-        }\r
-        trcCRITICAL_SECTION_END();\r
-    }\r
+       TSEvent* ts;\r
+       uint16_t dts5;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+\r
+       if (recorder_busy)\r
+       {\r
+               vTraceError("Illegal call to vTraceStoreISREnd, recorder busy!");\r
+               return;\r
+       }\r
+\r
+       trcCRITICAL_SECTION_BEGIN();\r
+       if (pendingISR == 0)\r
+       {\r
+               if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
+               {\r
+                       uint8_t hnd8, type;\r
+                       dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
+\r
+                       if (nISRactive > 1)\r
+                       {\r
+                               /* return to another isr */\r
+                               type = TS_ISR_RESUME;\r
+                               hnd8 = prvTraceGet8BitHandle(isrstack[nISRactive]);\r
+                       }\r
+                       else\r
+                       {\r
+                               /* return to task */\r
+                               type = TS_TASK_RESUME;\r
+                               hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);\r
+                       }\r
+\r
+                       ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
+                       if (ts != NULL)\r
+                       {\r
+                               ts->type = type;\r
+                               ts->objHandle = hnd8;\r
+                               ts->dts = dts5;\r
+                               prvTraceUpdateCounters();\r
+                       }\r
+\r
+                       #if (SELECTED_PORT == PORT_ARM_CortexM)\r
+                       /* Remember the last ISR exit event, as the event needs to be modified in case of a following ISR entry (if tail-chained ISRs) */\r
+                       ptrLastISRExitEvent = (uint8_t*)ts;\r
+                       #endif\r
+               }\r
+       }\r
+       nISRactive--;\r
+\r
+       #if (SELECTED_PORT == PORT_ARM_CortexM)\r
+       DWTCycleCountAtLastISRExit = REG_DWT_CYCCNT;\r
+       #endif\r
+\r
+       trcCRITICAL_SECTION_END();\r
 }\r
 \r
 #else\r
@@ -464,21 +688,21 @@ void vTraceStoreISREnd(void)
 /* ISR tracing is turned off */\r
 void vTraceIncreaseISRActive(void)\r
 {\r
-    if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
-        nISRactive++;\r
+       if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
+               nISRactive++;\r
 }\r
 \r
 void vTraceDecreaseISRActive(void)\r
 {\r
-    if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
-        nISRactive--;\r
+       if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
+               nISRactive--;\r
 }\r
 #endif\r
 \r
 \r
-/*******************************************************************************\r
- * User Event functions\r
- ******************************************************************************/\r
+/********************************************************************************/\r
+/* User Event functions                                                                                                                        */\r
+/********************************************************************************/\r
 \r
 #if (INCLUDE_USER_EVENTS == 1)\r
 \r
@@ -488,19 +712,19 @@ static uint8_t writeInt8(void * buffer, uint8_t i, uint8_t value)
 {\r
        TRACE_ASSERT(buffer != NULL, "writeInt8: buffer == NULL", 0);\r
 \r
-    if (i >= MAX_ARG_SIZE)\r
-    {\r
-        return 255;\r
-    }\r
+       if (i >= MAX_ARG_SIZE)\r
+       {\r
+               return 255;\r
+       }\r
 \r
-    ((uint8_t*)buffer)[i] = value;\r
+       ((uint8_t*)buffer)[i] = value;\r
 \r
        if (i + 1 > MAX_ARG_SIZE)\r
        {\r
                return 255;\r
        }\r
 \r
-    return i + 1;\r
+       return i + 1;\r
 }\r
 \r
 /*** Locally used in vTracePrintF ***/\r
@@ -508,26 +732,26 @@ static uint8_t writeInt16(void * buffer, uint8_t i, uint16_t value)
 {\r
        TRACE_ASSERT(buffer != NULL, "writeInt16: buffer == NULL", 0);\r
 \r
-    /* Align to multiple of 2 */\r
-    while ((i % 2) != 0)\r
-    {\r
+       /* Align to multiple of 2 */\r
+       while ((i % 2) != 0)\r
+       {\r
                if (i >= MAX_ARG_SIZE)\r
                {\r
                        return 255;\r
                }\r
 \r
-        ((uint8_t*)buffer)[i] = 0;\r
-        i++;\r
-    }\r
+               ((uint8_t*)buffer)[i] = 0;\r
+               i++;\r
+       }\r
 \r
-    if (i + 2 > MAX_ARG_SIZE)\r
-    {\r
-        return 255;\r
-    }\r
+       if (i + 2 > MAX_ARG_SIZE)\r
+       {\r
+               return 255;\r
+       }\r
 \r
-    ((uint16_t*)buffer)[i/2] = value;\r
+       ((uint16_t*)buffer)[i/2] = value;\r
 \r
-    return i + 2;\r
+       return i + 2;\r
 }\r
 \r
 /*** Locally used in vTracePrintF ***/\r
@@ -535,26 +759,26 @@ static uint8_t writeInt32(void * buffer, uint8_t i, uint32_t value)
 {\r
        TRACE_ASSERT(buffer != NULL, "writeInt32: buffer == NULL", 0);\r
 \r
-    /* A 32 bit value should begin at an even 4-byte address */\r
-    while ((i % 4) != 0)\r
-    {\r
+       /* A 32 bit value should begin at an even 4-byte address */\r
+       while ((i % 4) != 0)\r
+       {\r
                if (i >= MAX_ARG_SIZE)\r
                {\r
                        return 255;\r
                }\r
 \r
-        ((uint8_t*)buffer)[i] = 0;\r
-        i++;\r
-    }\r
+               ((uint8_t*)buffer)[i] = 0;\r
+               i++;\r
+       }\r
 \r
-    if (i + 4 > MAX_ARG_SIZE)\r
-    {\r
-        return 255;\r
-    }\r
+       if (i + 4 > MAX_ARG_SIZE)\r
+       {\r
+               return 255;\r
+       }\r
 \r
-    ((uint32_t*)buffer)[i/4] = value;\r
+       ((uint32_t*)buffer)[i/4] = value;\r
 \r
-    return i + 4;\r
+       return i + 4;\r
 }\r
 \r
 #if (INCLUDE_FLOAT_SUPPORT)\r
@@ -564,57 +788,60 @@ static uint8_t writeFloat(void * buffer, uint8_t i, float value)
 {\r
        TRACE_ASSERT(buffer != NULL, "writeFloat: buffer == NULL", 0);\r
 \r
-    /* A 32 bit value should begin at an even 4-byte address */\r
-    while ((i % 4) != 0)\r
-    {\r
+       /* A 32 bit value should begin at an even 4-byte address */\r
+       while ((i % 4) != 0)\r
+       {\r
                if (i >= MAX_ARG_SIZE)\r
                {\r
                        return 255;\r
                }\r
 \r
-        ((uint8_t*)buffer)[i] = 0;\r
-        i++;\r
-    }\r
+               ((uint8_t*)buffer)[i] = 0;\r
+               i++;\r
+       }\r
 \r
-    if (i + 4 > MAX_ARG_SIZE)\r
-    {\r
-        return 255;\r
-    }\r
+       if (i + 4 > MAX_ARG_SIZE)\r
+       {\r
+               return 255;\r
+       }\r
 \r
-    ((float*)buffer)[i/4] = value;\r
+       ((float*)buffer)[i/4] = value;\r
 \r
-    return i + 4;\r
+       return i + 4;\r
 }\r
 \r
 /*** Locally used in vTracePrintF ***/\r
 static uint8_t writeDouble(void * buffer, uint8_t i, double value)\r
 {\r
+       uint32_t * dest;\r
+       uint32_t * src = (uint32_t*)&value;\r
+\r
        TRACE_ASSERT(buffer != NULL, "writeDouble: buffer == NULL", 0);\r
 \r
-    uint32_t * dest = buffer;\r
-    uint32_t * src = (void*)&value;\r
-    /* The double is written as two 32 bit values, and should begin at an even\r
-    4-byte address (to avoid having to align with 8 byte) */\r
-    while (i % 4 != 0)\r
-    {\r
+       /* The double is written as two 32 bit values, and should begin at an even\r
+       4-byte address (to avoid having to align with 8 byte) */\r
+       while (i % 4 != 0)\r
+       {\r
                if (i >= MAX_ARG_SIZE)\r
                {\r
                        return 255;\r
                }\r
 \r
-        ((uint8_t*)buffer)[i] = 0;\r
-        i++;\r
-    }\r
+               ((uint8_t*)buffer)[i] = 0;\r
+               i++;\r
+       }\r
+\r
+       if (i + 8 > MAX_ARG_SIZE)\r
+       {\r
+               return 255;\r
+       }\r
 \r
-    if (i + 8 > MAX_ARG_SIZE)\r
-    {\r
-        return 255;\r
-    }\r
+       dest = &(((uint32_t *)buffer)[i/4]);\r
 \r
-    dest[i/4+0] = src[0];\r
-    dest[i/4+1] = src[1];\r
+       dest[0] = src[0];\r
+       dest[1] = src[1];\r
 \r
-    return i + 8;\r
+       return i + 8;\r
 }\r
 \r
 #endif\r
@@ -631,40 +858,40 @@ static uint8_t prvTraceUserEventFormat(const char* formatStr, va_list vl, uint8_
        uint8_t i = byteOffset;\r
 \r
        while (formatStr[formatStrIndex] != '\0')\r
-    {\r
-        if (formatStr[formatStrIndex] == '%')\r
-        {\r
-            argCounter++;\r
+       {\r
+               if (formatStr[formatStrIndex] == '%')\r
+               {\r
+                       argCounter++;\r
 \r
-            if (argCounter > 15)\r
-            {\r
-                vTraceError("vTracePrintF - Too many arguments, max 15 allowed!");\r
-                return 0;\r
-            }\r
+                       if (argCounter > 15)\r
+                       {\r
+                               vTraceError("vTracePrintF - Too many arguments, max 15 allowed!");\r
+                               return 0;\r
+                       }\r
 \r
-/*******************************************************************************\r
-* These below code writes raw data (primitive datatypes) in the event buffer,\r
-* instead of the normal event structs (where byte 0 is event type).\r
-* These data entries must never be interpreted as real event data, as the type\r
-* field would be misleading since used for payload data.\r
-*\r
-* The correctness of this encoding depends on two mechanisms:\r
-*\r
-* 1. An initial USER_EVENT, which type code tells the number of 32-bit data\r
-* entires that follows. (code - USER_EVENT = number of data entries).\r
-* Note that a data entry corresponds to the slots that normally corresponds to\r
-* one (1) event, i.e., 32 bits. vTracePrintF may encode several pieces of data\r
-* in one data entry, e.g., two 16-bit values or four 8-bit values, one 16-bit\r
-* value followed by two 8-bit values, etc.\r
-*\r
-* 2. A two-phase commit procedure, where the USER_EVENT and data entries are\r
-* written to a local buffer at first, and when all checks are OK then copied to\r
-* the main event buffer using a fast memcpy. The event code is finalized as the\r
-* very last step. Before that step, the event code indicates an unfinished\r
-* event, which causes it to be ignored and stop the loading of the file (since\r
-* an unfinished event is the last event in the trace).\r
-*******************************************************************************/\r
-            formatStrIndex++;\r
+                       /*******************************************************************************\r
+                       * These below code writes raw data (primitive datatypes) in the event buffer,\r
+                       * instead of the normal event structs (where byte 0 is event type).\r
+                       * These data entries must never be interpreted as real event data, as the type\r
+                       * field would be misleading since used for payload data.\r
+                       *\r
+                       * The correctness of this encoding depends on two mechanisms:\r
+                       *\r
+                       * 1. An initial USER_EVENT, which type code tells the number of 32-bit data\r
+                       * entires that follows. (code - USER_EVENT = number of data entries).\r
+                       * Note that a data entry corresponds to the slots that normally corresponds to\r
+                       * one (1) event, i.e., 32 bits. vTracePrintF may encode several pieces of data\r
+                       * in one data entry, e.g., two 16-bit values or four 8-bit values, one 16-bit\r
+                       * value followed by two 8-bit values, etc.\r
+                       *\r
+                       * 2. A two-phase commit procedure, where the USER_EVENT and data entries are\r
+                       * written to a local buffer at first, and when all checks are OK then copied to\r
+                       * the main event buffer using a fast memcpy. The event code is finalized as the\r
+                       * very last step. Before that step, the event code indicates an unfinished\r
+                       * event, which causes it to be ignored and stop the loading of the file (since\r
+                       * an unfinished event is the last event in the trace).\r
+                       *******************************************************************************/\r
+                       formatStrIndex++;\r
 \r
                        while ((formatStr[formatStrIndex] >= '0' && formatStr[formatStrIndex] <= '9') || formatStr[formatStrIndex] == '#' || formatStr[formatStrIndex] == '.')\r
                                formatStrIndex++;\r
@@ -673,105 +900,107 @@ static uint8_t prvTraceUserEventFormat(const char* formatStr, va_list vl, uint8_
                        {\r
                                switch (formatStr[formatStrIndex])\r
                                {\r
-                               case 'd':    i = writeInt32(buffer,\r
+                                       case 'd':       i = writeInt32( buffer,\r
                                                                                                i,\r
                                                                                                (uint32_t)va_arg(vl, uint32_t));\r
                                                                break;\r
-                               case 'x':\r
-                               case 'X':\r
-                               case 'u':    i = writeInt32(buffer,\r
+                                       case 'x':\r
+                                       case 'X':\r
+                                       case 'u':       i = writeInt32( buffer,\r
                                                                                                i,\r
                                                                                                (uint32_t)va_arg(vl, uint32_t));\r
                                                                break;\r
-                               case 's':    i = writeInt16(buffer,\r
+                                       case 's':       i = writeInt16( buffer,\r
                                                                                                i,\r
                                                                                                (uint16_t)xTraceOpenLabel((char*)va_arg(vl, char*)));\r
                                                                break;\r
 \r
 #if (INCLUDE_FLOAT_SUPPORT)\r
-                                                               /* Yes, "double" as type also in the float\r
-                                                               case. This since "float" is promoted into "double"\r
-                                                               by the va_arg stuff. */\r
-                               case 'f':    i = writeFloat(buffer,\r
+                                       /* Yes, "double" as type also in the float\r
+                                       case. This since "float" is promoted into "double"\r
+                                       by the va_arg stuff. */\r
+                                       case 'f':       i = writeFloat( buffer,\r
                                                                                                i,\r
                                                                                                (float)va_arg(vl, double));\r
                                                                break;\r
 #else\r
-       /* No support for floats, but attempt to store a float user event\r
-       avoid a possible crash due to float reference. Instead store the\r
-       data on uint_32 format (will not be displayed anyway). This is just\r
-       to keep va_arg and i consistent. */\r
+                                       /* No support for floats, but attempt to store a float user event\r
+                                       avoid a possible crash due to float reference. Instead store the\r
+                                       data on uint_32 format (will not be displayed anyway). This is just\r
+                                       to keep va_arg and i consistent. */\r
 \r
-                               case 'f':    i = writeInt32(buffer,\r
+                                       case 'f':       i = writeInt32( buffer,\r
                                                                                                i,\r
                                                                                                (uint32_t)va_arg(vl, double));\r
                                                                break;\r
 #endif\r
-                               case 'l':\r
-                                       formatStrIndex++;\r
-                                       switch (formatStr[formatStrIndex])\r
-                                       {\r
+                                       case 'l':\r
+                                                               formatStrIndex++;\r
+                                                               switch (formatStr[formatStrIndex])\r
+                                                               {\r
 #if (INCLUDE_FLOAT_SUPPORT)\r
-                                       case 'f':     i = writeDouble(buffer,\r
-                                                                                                               i,\r
-                                                                                                               (double)va_arg(vl, double));\r
-                                                               break;\r
+                                                                       case 'f':       i = writeDouble(buffer,\r
+                                                                                                                               i,\r
+                                                                                                                               (double)va_arg(vl, double));\r
+                                                                                               break;\r
 #else\r
-       /* No support for floats, but attempt to store a float user event\r
-       avoid a possible crash due to float reference. Instead store the\r
-       data on uint_32 format (will not be displayed anyway). This is just\r
-       to keep va_arg and i consistent. */\r
-                                       case 'f':    i = writeInt32(buffer, /* In this case, the value will not be shown anyway */\r
-                                                                                                       i,\r
-                                                                                                       (uint32_t)va_arg(vl, double));\r
-                                                                       i = writeInt32(buffer, /* Do it twice, to write in total 8 bytes */\r
-                                                                                                       i,\r
-                                                                                                       (uint32_t)va_arg(vl, double));\r
-                                                               break;\r
+                                                                       /* No support for floats, but attempt to store a float user event\r
+                                                                       avoid a possible crash due to float reference. Instead store the\r
+                                                                       data on uint_32 format (will not be displayed anyway). This is just\r
+                                                                       to keep va_arg and i consistent. */\r
+                                                                       case 'f':       i = writeInt32( buffer, /* In this case, the value will not be shown anyway */\r
+                                                                                                                               i,\r
+                                                                                                                               (uint32_t)va_arg(vl, double));\r
+\r
+                                                                                               i = writeInt32( buffer, /* Do it twice, to write in total 8 bytes */\r
+                                                                                                                               i,\r
+                                                                                                                               (uint32_t)va_arg(vl, double));\r
+                                                                               break;\r
 #endif\r
 \r
-                                       }\r
-                                       break;\r
-                               case 'h':\r
-                                       formatStrIndex++;\r
-                                       switch (formatStr[formatStrIndex])\r
-                                       {\r
-                                       case 'd':    i = writeInt16(buffer,\r
-                                                                                                       i,\r
-                                                                                                       (uint16_t)va_arg(vl, uint32_t));\r
-                                                                       break;\r
-                                       case 'u':    i = writeInt16(buffer,\r
-                                                                                                       i,\r
-                                                                                                       (uint16_t)va_arg(vl, uint32_t));\r
-                                                                       break;\r
-                                       }\r
-                                       break;\r
-                               case 'b':\r
-                                       formatStrIndex++;\r
-                                       switch (formatStr[formatStrIndex])\r
-                                       {\r
-                                       case 'd':    i = writeInt8(buffer,\r
-                                                                                                       i,\r
-                                                                                                       (uint8_t)va_arg(vl, uint32_t));\r
-                                                                       break;\r
-                                       case 'u':    i = writeInt8(buffer,\r
-                                                                                                       i,\r
-                                                                                                       (uint8_t)va_arg(vl, uint32_t));\r
-                                                                       break;\r
-                                       }\r
-                                       break;\r
+                                                               }\r
+                                                               break;\r
+                                       case 'h':\r
+                                                               formatStrIndex++;\r
+                                                               switch (formatStr[formatStrIndex])\r
+                                                               {\r
+                                                                       case 'd':       i = writeInt16( buffer,\r
+                                                                                                                               i,\r
+                                                                                                                               (uint16_t)va_arg(vl, uint32_t));\r
+                                                                                               break;\r
+                                                                       case 'u':       i = writeInt16( buffer,\r
+                                                                                                                               i,\r
+                                                                                                                               (uint16_t)va_arg(vl, uint32_t));\r
+                                                                                               break;\r
+                                                               }\r
+                                                               break;\r
+                                       case 'b':\r
+                                                               formatStrIndex++;\r
+                                                               switch (formatStr[formatStrIndex])\r
+                                                               {\r
+                                                                       case 'd':       i = writeInt8(  buffer,\r
+                                                                                                                               i,\r
+                                                                                                                               (uint8_t)va_arg(vl, uint32_t));\r
+                                                                                               break;\r
+\r
+                                                                       case 'u':       i = writeInt8(  buffer,\r
+                                                                                                                               i,\r
+                                                                                                                               (uint8_t)va_arg(vl, uint32_t));\r
+                                                                                               break;\r
+                                                               }\r
+                                                               break;\r
                                }\r
                        }\r
                        else\r
                                break;\r
-        }\r
-        formatStrIndex++;\r
-        if (i == 255)\r
-        {\r
-            vTraceError("vTracePrintF - Too large arguments, max 32 byte allowed!");\r
-            return 0;\r
-        }\r
-    }\r
+               }\r
+               formatStrIndex++;\r
+               if (i == 255)\r
+               {\r
+                       vTraceError("vTracePrintF - Too large arguments, max 32 byte allowed!");\r
+                       return 0;\r
+               }\r
+       }\r
        return (i+3)/4;\r
 }\r
 \r
@@ -786,7 +1015,8 @@ static void prvTraceClearChannelBuffer(uint32_t count)
 {\r
        uint32_t slots;\r
 \r
-       TRACE_ASSERT(USER_EVENT_BUFFER_SIZE >= count, "prvTraceClearChannelBuffer: USER_EVENT_BUFFER_SIZE is too small to handle this event.", );\r
+       TRACE_ASSERT(USER_EVENT_BUFFER_SIZE >= count,\r
+               "prvTraceClearChannelBuffer: USER_EVENT_BUFFER_SIZE is too small to handle this event.", );\r
 \r
        /* Check if we're close to the end of the buffer */\r
        if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > USER_EVENT_BUFFER_SIZE)\r
@@ -806,8 +1036,10 @@ static void prvTraceClearChannelBuffer(uint32_t count)
  ******************************************************************************/\r
 static void prvTraceCopyToDataBuffer(uint32_t* data, uint32_t count)\r
 {\r
-       TRACE_ASSERT(data != NULL, "prvTraceCopyToDataBuffer: data == NULL.", );\r
-       TRACE_ASSERT(count <= USER_EVENT_BUFFER_SIZE, "prvTraceCopyToDataBuffer: USER_EVENT_BUFFER_SIZE is too small to handle this event.", );\r
+       TRACE_ASSERT(data != NULL,\r
+               "prvTraceCopyToDataBuffer: data == NULL.", );\r
+       TRACE_ASSERT(count <= USER_EVENT_BUFFER_SIZE,\r
+               "prvTraceCopyToDataBuffer: USER_EVENT_BUFFER_SIZE is too small to handle this event.", );\r
 \r
        uint32_t slots;\r
        /* Check if we're close to the end of the buffer */\r
@@ -826,7 +1058,8 @@ static void prvTraceCopyToDataBuffer(uint32_t* data, uint32_t count)
 /*******************************************************************************\r
  * prvTraceUserEventHelper1\r
  *\r
- * Calls on prvTraceUserEventFormat() to do the actual formatting, then goes on to the next helper function.\r
+ * Calls on prvTraceUserEventFormat() to do the actual formatting, then goes on\r
+ * to the next helper function.\r
  ******************************************************************************/\r
 static void prvTraceUserEventHelper1(UserEventChannel channel, traceLabel eventLabel, traceLabel formatLabel, va_list vl)\r
 {\r
@@ -864,7 +1097,10 @@ static void prvTraceUserEventHelper2(UserEventChannel channel, uint32_t* data, u
        vTracePortGetTimeStamp(data);\r
 \r
        if (*data < old_timestamp)\r
+       {\r
                RecorderDataPtr->userEventBuffer.wraparoundCounter++;\r
+       }\r
+\r
        old_timestamp = *data;\r
 \r
        /* Start by erasing any information in the channel buffer */\r
@@ -877,9 +1113,14 @@ static void prvTraceUserEventHelper2(UserEventChannel channel, uint32_t* data, u
 \r
        /* Write to the channel buffer to indicate that this user event is ready to be used */\r
        if (channel != 0)\r
+       {\r
                RecorderDataPtr->userEventBuffer.channelBuffer[old_nextSlotToWrite] = channel;\r
+       }\r
        else\r
-               RecorderDataPtr->userEventBuffer.channelBuffer[old_nextSlotToWrite] = (UserEventChannel)0xFF;   /* 0xFF indicates that this is not a normal channel id */\r
+       {\r
+               /* 0xFF indicates that this is not a normal channel id */\r
+               RecorderDataPtr->userEventBuffer.channelBuffer[old_nextSlotToWrite] = (UserEventChannel)0xFF;\r
+       }\r
        trcCRITICAL_SECTION_END();\r
 }\r
 \r
@@ -888,7 +1129,7 @@ static void prvTraceUserEventHelper2(UserEventChannel channel, uint32_t* data, u
  *\r
  * Attempts to create a pair of the channel and format string.\r
  *\r
- * Note: This is only available if USE_SEPARATE_USER_EVENT_BUFFER is enabled in \r
+ * Note: This is only available if USE_SEPARATE_USER_EVENT_BUFFER is enabled in\r
  * trcConfig.h\r
  ******************************************************************************/\r
 UserEventChannel xTraceRegisterChannelFormat(traceLabel channel, traceLabel formatStr)\r
@@ -932,11 +1173,13 @@ UserEventChannel xTraceRegisterChannelFormat(traceLabel channel, traceLabel form
  ******************************************************************************/\r
 void vTraceChannelPrintF(UserEventChannel channelPair, ...)\r
 {\r
+#if (TRACE_SCHEDULING_ONLY == 0)\r
        va_list vl;\r
 \r
        va_start(vl, channelPair);\r
        vTraceChannelPrintF_Helper(channelPair, vl);\r
        va_end(vl);\r
+#endif /* TRACE_SCHEDULING_ONLY */\r
 }\r
 \r
 void vTraceChannelPrintF_Helper(UserEventChannel channelPair, va_list vl)\r
@@ -960,16 +1203,18 @@ void vTraceChannelPrintF_Helper(UserEventChannel channelPair, va_list vl)
  ******************************************************************************/\r
 void vTraceChannelUserEvent(UserEventChannel channelPair)\r
 {\r
+#if (TRACE_SCHEDULING_ONLY == 0)\r
        uint32_t data[(3 + MAX_ARG_SIZE) / 4];\r
 \r
        TRACE_ASSERT(channelPair != 0, "vTraceChannelPrintF: channelPair == 0", );\r
        TRACE_ASSERT(channelPair <= CHANNEL_FORMAT_PAIRS, "vTraceChannelPrintF: ", );\r
 \r
        prvTraceUserEventHelper2(channelPair, data, 1); /* Only need one slot for timestamp */\r
+#endif /* TRACE_SCHEDULING_ONLY */\r
 }\r
 #endif /* USE_SEPARATE_USER_EVENT_BUFFER == 1 */\r
 \r
- /******************************************************************************\r
+/******************************************************************************\r
  * vTracePrintF\r
  *\r
  * Advanced user events (Professional Edition only)\r
@@ -982,17 +1227,17 @@ void vTraceChannelUserEvent(UserEventChannel channelPair)
  * User Event labels are created using xTraceOpenLabel.\r
  * Example:\r
  *\r
- *     traceLabel adc_uechannel = xTraceOpenLabel("ADC User Events");\r
- *     ...\r
- *     vTracePrint(adc_uechannel,\r
- *                 "ADC channel %d: %lf volts",\r
- *                 ch, (double)adc_reading/(double)scale);\r
+ *      traceLabel adc_uechannel = xTraceOpenLabel("ADC User Events");\r
+ *      ...\r
+ *      vTracePrint(adc_uechannel,\r
+ *                              "ADC channel %d: %lf volts",\r
+ *                              ch, (double)adc_reading/(double)scale);\r
  *\r
  * This can be combined into one line, if desired, but this is slower:\r
  *\r
- *     vTracePrint(xTraceOpenLabel("ADC User Events"),\r
- *                 "ADC channel %d: %lf volts",\r
- *                 ch, (double)adc_reading/(double)scale);\r
+ *      vTracePrint(xTraceOpenLabel("ADC User Events"),\r
+ *                              "ADC channel %d: %lf volts",\r
+ *                              ch, (double)adc_reading/(double)scale);\r
  *\r
  * Calling xTraceOpenLabel multiple times will not create duplicate entries, but\r
  * it is of course faster to just do it once, and then keep the handle for later\r
@@ -1000,157 +1245,151 @@ void vTraceChannelUserEvent(UserEventChannel channelPair)
  * better to use vTraceUserEvent - it is faster.\r
  *\r
  * Format specifiers supported:\r
- *  %d - 32 bit signed integer\r
- *  %u - 32 bit unsigned integer\r
- *  %f - 32 bit float\r
- *  %s - string (is copied to the recorder symbol table)\r
- *  %hd - 16 bit signed integer\r
- *  %hu - 16 bit unsigned integer\r
- *  %bd - 8 bit signed integer\r
- *  %bu - 8 bit unsigned integer\r
- *  %lf - double-precision float\r
+ * %d - 32 bit signed integer\r
+ * %u - 32 bit unsigned integer\r
+ * %f - 32 bit float\r
+ * %s - string (is copied to the recorder symbol table)\r
+ * %hd - 16 bit signed integer\r
+ * %hu - 16 bit unsigned integer\r
+ * %bd - 8 bit signed integer\r
+ * %bu - 8 bit unsigned integer\r
+ * %lf - double-precision float (Note! See below...)\r
  *\r
  * Up to 15 data arguments are allowed, with a total size of maximum 32 byte.\r
  * In case this is exceeded, the user event is changed into an error message.\r
  *\r
  * The data is stored in trace buffer, and is packed to allow storing multiple\r
  * smaller data entries in the same 4-byte record, e.g., four 8-bit values.\r
- * A string requires two bytes, as the symbol table is limited to 64K. Storing a\r
- * double (%lf) uses two records, so this is quite costly. Use float (%f) unless\r
- * the higher precision is really necessary.\r
+ * A string requires two bytes, as the symbol table is limited to 64K. Storing\r
+ * a double (%lf) uses two records, so this is quite costly. Use float (%f)\r
+ * unless the higher precision is really necessary.\r
+ *\r
+ * Note that the double-precision float (%lf) assumes a 64 bit double\r
+ * representation. This does not seem to be the case on e.g. PIC24 and PIC32.\r
+ * Before using a %lf argument on a 16-bit MCU, please verify that\r
+ * "sizeof(double)" actually gives 8 as expected. If not, use %f instead.\r
  ******************************************************************************/\r
 \r
 void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...)\r
 {\r
+#if (TRACE_SCHEDULING_ONLY == 0)\r
        va_list vl;\r
 \r
        va_start(vl, formatStr);\r
        vTracePrintF_Helper(eventLabel, formatStr, vl);\r
        va_end(vl);\r
+#endif /* TRACE_SCHEDULING_ONLY */\r
 }\r
 \r
 void vTracePrintF_Helper(traceLabel eventLabel, const char* formatStr, va_list vl)\r
 {\r
 #if (USE_SEPARATE_USER_EVENT_BUFFER == 0)\r
        uint32_t noOfSlots;\r
-    UserEvent* ue1;\r
-    uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];\r
-\r
-    /**************************************************************************\r
-    * The array tempDataBuffer is a local buffer used in a two-phase commit of\r
-    * the event data, since a vTracePrintF may span over multiple slots in the\r
-    * buffer.\r
-    * This buffer can be made larger, of course, but remember the risk for\r
-    * stack overflow. Note: This should be a LOCAL buffer, must not be made\r
-    * global. That would cause data corruption when two calls to vTracePrintF\r
-    * from different tasks overlaps (interrupts are only disabled in a small\r
-    * part of this function, otherwise enabled)\r
-    ***************************************************************************/\r
+       UserEvent* ue1;\r
+       uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+\r
+       /**************************************************************************\r
+       * The array tempDataBuffer is a local buffer used in a two-phase commit of\r
+       * the event data, since a vTracePrintF may span over multiple slots in the\r
+       * buffer.\r
+       * This buffer can be made larger, of course, but remember the risk for\r
+       * stack overflow. Note: This should be a LOCAL buffer, must not be made\r
+       * global. That would cause data corruption when two calls to vTracePrintF\r
+       * from different tasks overlaps (interrupts are only disabled in a small\r
+       * part of this function, otherwise enabled)\r
+       ***************************************************************************/\r
 \r
        TRACE_ASSERT(formatStr != NULL, "vTracePrintF: formatStr == NULL", );\r
 \r
-    if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
-    {\r
-        /* First, write the "primary" user event entry in the local buffer, but\r
-        let the event type be "EVENT_BEING_WRITTEN" for now...*/\r
-\r
-        ue1 = (UserEvent*)(&tempDataBuffer[0]);\r
-        ue1->type = EVENT_BEING_WRITTEN;      /* Update this as the last step */\r
-\r
-        noOfSlots = prvTraceUserEventFormat(formatStr, vl, (uint8_t*)tempDataBuffer, 4);\r
-\r
-        /* Store the format string, with a reference to the channel symbol */\r
-        ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel);\r
-\r
-        trcCRITICAL_SECTION_BEGIN();\r
-\r
-        ue1->dts = (uint8_t)prvTraceGetDTS(0xFF);\r
-        if (! RecorderDataPtr->recorderActive)\r
-        {\r
-\r
-            /* Abort, since an XTS event (created by prvTraceGetDTS) filled the\r
-            buffer, and the recorder stopped since not circular buffer. */\r
-            trcCRITICAL_SECTION_END();\r
-\r
-            return;\r
-        }\r
+       trcCRITICAL_SECTION_BEGIN();\r
 \r
-        /* If the data does not fit in the remaining main buffer, wrap around to\r
-        0 if allowed, otherwise stop the recorder and quit). */\r
-        if (RecorderDataPtr->nextFreeIndex + noOfSlots > RecorderDataPtr->maxEvents)\r
-        {\r
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
-            (void)memset(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],\r
-                   0,\r
-                   (RecorderDataPtr->maxEvents - RecorderDataPtr->nextFreeIndex)*4);\r
-            RecorderDataPtr->nextFreeIndex = 0;\r
-            RecorderDataPtr->bufferIsFull = 1;\r
-#else\r
-            /* Abort and stop recorder, since the event data will not fit in the\r
-            buffer and not circular buffer in this case... */\r
-            trcCRITICAL_SECTION_END();\r
-            vTraceStop();\r
+       if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
+       {\r
+               /* First, write the "primary" user event entry in the local buffer, but\r
+               let the event type be "EVENT_BEING_WRITTEN" for now...*/\r
 \r
+               ue1 = (UserEvent*)(&tempDataBuffer[0]);\r
 \r
-            return;\r
-#endif\r
-        }\r
-\r
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
-        /* Check that the buffer to be overwritten does not contain any user\r
-        events that would be partially overwritten. If so, they must be "killed"\r
-        by replacing the user event and following data with NULL events (i.e.,\r
-        using a memset to zero).*/\r
-        prvCheckDataToBeOverwrittenForMultiEntryEvents((uint8_t)noOfSlots);\r
-#endif\r
-        /* Copy the local buffer to the main buffer */\r
-        (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],\r
-               tempDataBuffer,\r
-               noOfSlots * 4);\r
+               ue1->type = EVENT_BEING_WRITTEN;         /* Update this as the last step */\r
 \r
-        /* Update the event type, i.e., number of data entries following the\r
-        main USER_EVENT entry (Note: important that this is after the memcpy,\r
-        but within the critical section!)*/\r
-        RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4] =\r
-          (uint8_t) ( USER_EVENT + noOfSlots - 1 );\r
+               noOfSlots = prvTraceUserEventFormat(formatStr, vl, (uint8_t*)tempDataBuffer, 4);\r
 \r
-        /* Update the main buffer event index (already checked that it fits in\r
-        the buffer, so no need to check for wrapping)*/\r
+               /* Store the format string, with a reference to the channel symbol */\r
+               ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel);\r
 \r
-        RecorderDataPtr->nextFreeIndex += noOfSlots;\r
-        RecorderDataPtr->numEvents += noOfSlots;\r
+               ue1->dts = (uint8_t)prvTraceGetDTS(0xFF);\r
 \r
+                /* prvTraceGetDTS might stop the recorder in some cases... */\r
+               if (RecorderDataPtr->recorderActive)\r
+               {\r
 \r
+                       /* If the data does not fit in the remaining main buffer, wrap around to\r
+                       0 if allowed, otherwise stop the recorder and quit). */\r
+                       if (RecorderDataPtr->nextFreeIndex + noOfSlots > RecorderDataPtr->maxEvents)\r
+                       {\r
+                               #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
+                               (void)memset(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],\r
+                                               0,\r
+                                               (RecorderDataPtr->maxEvents - RecorderDataPtr->nextFreeIndex)*4);\r
+                               RecorderDataPtr->nextFreeIndex = 0;\r
+                               RecorderDataPtr->bufferIsFull = 1;\r
+                               #else\r
+\r
+                               /* Stop recorder, since the event data will not fit in the\r
+                               buffer and not circular buffer in this case... */\r
+                               vTraceStop();\r
+                               #endif\r
+                       }\r
 \r
-               if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)\r
-               {\r
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
-                       /* We have reached the end, but this is a ring buffer. Start from the beginning again. */\r
-                       RecorderDataPtr->bufferIsFull = 1;\r
-                       RecorderDataPtr->nextFreeIndex = 0;\r
-#else\r
-                       /* We have reached the end so we stop. */\r
-                       vTraceStop();\r
-#endif\r
-               }\r
+                       /* Check if recorder has been stopped (i.e., vTraceStop above) */\r
+                       if (RecorderDataPtr->recorderActive)\r
+                       {\r
+                               /* Check that the buffer to be overwritten does not contain any user\r
+                               events that would be partially overwritten. If so, they must be "killed"\r
+                               by replacing the user event and following data with NULL events (i.e.,\r
+                               using a memset to zero).*/\r
+                               #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
+                               prvCheckDataToBeOverwrittenForMultiEntryEvents((uint8_t)noOfSlots);\r
+                               #endif\r
+                               /* Copy the local buffer to the main buffer */\r
+                               (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],\r
+                                               tempDataBuffer,\r
+                                               noOfSlots * 4);\r
+\r
+                               /* Update the event type, i.e., number of data entries following the\r
+                               main USER_EVENT entry (Note: important that this is after the memcpy,\r
+                               but within the critical section!)*/\r
+                               RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4] =\r
+                                (uint8_t) ( USER_EVENT + noOfSlots - 1 );\r
+\r
+                               /* Update the main buffer event index (already checked that it fits in\r
+                               the buffer, so no need to check for wrapping)*/\r
+\r
+                               RecorderDataPtr->nextFreeIndex += noOfSlots;\r
+                               RecorderDataPtr->numEvents += noOfSlots;\r
+\r
+                               if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)\r
+                               {\r
+                                       #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
+                                       /* We have reached the end, but this is a ring buffer. Start from the beginning again. */\r
+                                       RecorderDataPtr->bufferIsFull = 1;\r
+                                       RecorderDataPtr->nextFreeIndex = 0;\r
+                                       #else\r
+                                       /* We have reached the end so we stop. */\r
+                                       vTraceStop();\r
+                                       #endif\r
+                               }\r
+                       }\r
 \r
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
-               /* Make sure the next entry is cleared correctly */\r
-               prvCheckDataToBeOverwrittenForMultiEntryEvents(1);\r
-#endif\r
+                       #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
+                       /* Make sure the next entry is cleared correctly */\r
+                       prvCheckDataToBeOverwrittenForMultiEntryEvents(1);\r
+                       #endif\r
 \r
-#ifdef STOP_AFTER_N_EVENTS\r
-#if (STOP_AFTER_N_EVENTS > -1)\r
-               /* Check if we have reached the desired number of events */\r
-               if (RecorderDataPtr->numEvents >= STOP_AFTER_N_EVENTS)\r
-               {\r
-                       vTraceStop();\r
                }\r
-#endif\r
-#endif\r
-\r
-        trcCRITICAL_SECTION_END();\r
-    }\r
+       }\r
+       trcCRITICAL_SECTION_END();\r
 \r
 #elif (USE_SEPARATE_USER_EVENT_BUFFER == 1)\r
        /* Use the separate user event buffer */\r
@@ -1158,10 +1397,10 @@ void vTracePrintF_Helper(traceLabel eventLabel, const char* formatStr, va_list v
        UserEventChannel channel;\r
 \r
        if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
-    {\r
-           formatLabel = xTraceOpenLabel(formatStr);\r
+       {\r
+               formatLabel = xTraceOpenLabel(formatStr);\r
 \r
-           channel = xTraceRegisterChannelFormat(eventLabel, formatLabel);\r
+               channel = xTraceRegisterChannelFormat(eventLabel, formatLabel);\r
 \r
                prvTraceUserEventHelper1(channel, eventLabel, formatLabel, vl);\r
        }\r
@@ -1178,36 +1417,33 @@ void vTracePrintF_Helper(traceLabel eventLabel, const char* formatStr, va_list v
  ******************************************************************************/\r
 void vTraceUserEvent(traceLabel eventLabel)\r
 {\r
+#if (TRACE_SCHEDULING_ONLY == 0)\r
 #if (USE_SEPARATE_USER_EVENT_BUFFER == 0)\r
-    UserEvent* ue;\r
-    uint8_t dts1;\r
+       UserEvent* ue;\r
+       uint8_t dts1;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
 \r
        TRACE_ASSERT(eventLabel > 0, "vTraceUserEvent: Invalid value for eventLabel", );\r
 \r
-    if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
-    {\r
-        trcCRITICAL_SECTION_BEGIN();\r
-\r
-        dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
-\r
-        if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
-        {\r
-            ue = (UserEvent*) xTraceNextFreeEventBufferSlot();\r
-            if (ue != NULL)\r
-            {\r
-                ue->dts = dts1;\r
-                ue->type = USER_EVENT;\r
-                ue->payload = eventLabel;\r
-                prvTraceUpdateCounters();\r
-            }\r
-        }\r
-        trcCRITICAL_SECTION_END();\r
-    }\r
+       trcCRITICAL_SECTION_BEGIN();\r
+       if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
+       {\r
+               dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
+               ue = (UserEvent*) xTraceNextFreeEventBufferSlot();\r
+               if (ue != NULL)\r
+               {\r
+                       ue->dts = dts1;\r
+                       ue->type = USER_EVENT;\r
+                       ue->payload = eventLabel;\r
+                       prvTraceUpdateCounters();\r
+               }\r
+       }\r
+       trcCRITICAL_SECTION_END();\r
+\r
 #elif (USE_SEPARATE_USER_EVENT_BUFFER == 1)\r
        UserEventChannel channel;\r
        uint32_t noOfSlots = 1;\r
        uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];\r
-\r
        if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
        {\r
                channel = xTraceRegisterChannelFormat(0, eventLabel);\r
@@ -1223,6 +1459,7 @@ void vTraceUserEvent(traceLabel eventLabel)
                prvTraceUserEventHelper2(channel, tempDataBuffer, noOfSlots);\r
        }\r
 #endif\r
+#endif /* TRACE_SCHEDULING_ONLY */\r
 }\r
 \r
 /*******************************************************************************\r
@@ -1235,7 +1472,7 @@ void vTraceUserEvent(traceLabel eventLabel)
  * When logging a user event, a numeric handle (reference) to this string is\r
  * used to identify the event. This is obtained by calling\r
  *\r
- *     xTraceOpenLabel()\r
+ *      xTraceOpenLabel()\r
  *\r
  * which adds the string to the symbol table (if not already present)\r
  * and returns the corresponding handle.\r
@@ -1245,15 +1482,15 @@ void vTraceUserEvent(traceLabel eventLabel)
  * 1. The handle is looked up every time, when storing the user event.\r
  *\r
  * Example:\r
- *     vTraceUserEvent(xTraceOpenLabel("MyUserEvent"));\r
+ *      vTraceUserEvent(xTraceOpenLabel("MyUserEvent"));\r
  *\r
  * 2. The label is registered just once, with the handle stored in an\r
- *  application variable - much like using a file handle.\r
+ * application variable - much like using a file handle.\r
  *\r
  * Example:\r
- *     myEventHandle = xTraceOpenLabel("MyUserEvent");\r
- *     ...\r
- *     vTraceUserEvent(myEventHandle);\r
+ *      myEventHandle = xTraceOpenLabel("MyUserEvent");\r
+ *      ...\r
+ *      vTraceUserEvent(myEventHandle);\r
  *\r
  * The second option is faster since no lookup is required on each event, and\r
  * therefore recommended for user events that are frequently\r
@@ -1264,9 +1501,9 @@ traceLabel xTraceOpenLabel(const char* label)
 {\r
        TRACE_ASSERT(label != NULL, "xTraceOpenLabel: label == NULL", (traceLabel)0);\r
 \r
-    return prvTraceOpenSymbol(label, 0);\r
+       return prvTraceOpenSymbol(label, 0);\r
 }\r
 \r
 #endif\r
 \r
-#endif
\ No newline at end of file
+#endif\r