/*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
* Percepio AB, www.percepio.com\r
*\r
* trcUser.c\r
* Copyright Percepio AB, 2013.\r
* www.percepio.com\r
******************************************************************************/\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
\r
#include "trcUser.h"\r
\r
\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
******************************************************************************/\r
void vTraceClear(void)\r
{\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
+ traceErrorMessage = NULL;\r
+ RecorderDataPtr->internalErrorOccured = 0;\r
\r
trcCRITICAL_SECTION_END();\r
\r
\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
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
+#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 measuring 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();\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. A tick frequency of \r
+ * 1 MHz (1.000.000) should be sufficient.\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 actor. If \r
+ * the value is set too high, separate ISRs will appear to execute tail-chained\r
+ * and for too long time.\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
* 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
******************************************************************************/\r
void vTraceStoreISRBegin(objectHandleType handle)\r
{\r
uint16_t dts4;\r
- TSEvent* ts = NULL;\r
+ #if (SELECTED_PORT == PORT_ARM_CortexM)\r
+ uint32_t CPUCyclesSinceLastISRExit = DWT_CYCLE_COUNTER - DWTCycleCountAtLastISRExit;\r
+ #endif \r
+ TSEvent* ts;\r
+ TRACE_SR_ALLOC_CRITICAL_SECTION();\r
\r
- TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", );\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
+ 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
+ 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
- trcCRITICAL_SECTION_BEGIN();\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
-\r
if (nISRactive < MAX_ISR_NESTING)\r
{\r
+ uint8_t hnd8 = prvTraceGet8BitHandle(handle);\r
isrstack[nISRactive] = handle;\r
nISRactive++;\r
ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
{\r
ts->type = TS_ISR_BEGIN;\r
ts->dts = dts4;\r
- ts->objHandle = handle;\r
+ ts->objHandle = hnd8;\r
prvTraceUpdateCounters();\r
}\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
-\r
-\r
-#if (SELECTED_PORT == PORT_ARM_CortexM)\r
-\r
-static int tailchain_irq_pending(void);\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
- }\r
- return 0;\r
+ trcCRITICAL_SECTION_END();\r
}\r
\r
-#endif\r
-\r
/*******************************************************************************\r
* vTraceStoreISREnd\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
void vTraceStoreISREnd(void)\r
{\r
- TSEvent* ts;\r
- uint16_t dts5;\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
+ 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
+ trcCRITICAL_SECTION_BEGIN();\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
+ { \r
+ dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
\r
- trcCRITICAL_SECTION_BEGIN();\r
- dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
+ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
+ {\r
+ uint8_t hnd8, type;\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
+ 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
+\r
+ if (ts != NULL)\r
+ {\r
+ ts->type = type;\r
+ ts->objHandle = hnd8;\r
+ ts->dts = dts5;\r
+ nISRactive--;\r
+ prvTraceUpdateCounters();\r
+ }\r
+ \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
+ DWTCycleCountAtLastISRExit = DWT_CYCLE_COUNTER;\r
+ #endif \r
+ }\r
+ trcCRITICAL_SECTION_END();\r
}\r
\r
#else\r
{\r
TRACE_ASSERT(buffer != NULL, "writeDouble: buffer == NULL", 0);\r
\r
- uint32_t * dest = buffer;\r
+ uint32_t * dest; \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
{\r
return 255;\r
}\r
+ \r
+ dest = &(((uint32_t *)buffer)[i]);\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
}\r
uint32_t noOfSlots;\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
\r
TRACE_ASSERT(formatStr != NULL, "vTracePrintF: formatStr == NULL", );\r
\r
+ trcCRITICAL_SECTION_BEGIN();\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
+ \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
+ ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel); \r
\r
ue1->dts = (uint8_t)prvTraceGetDTS(0xFF);\r
- if (! RecorderDataPtr->recorderActive)\r
+ \r
+ /* prvTraceGetDTS might stop the recorder in some cases... */\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
-\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
-\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
-\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
-\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
-#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
+ /* 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
+ /* 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
+ #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
+ }\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
+ \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
#if (USE_SEPARATE_USER_EVENT_BUFFER == 0)\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
+ trcCRITICAL_SECTION_BEGIN(); \r
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
- {\r
- trcCRITICAL_SECTION_BEGIN();\r
-\r
+ { \r
dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
\r
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
ue->payload = eventLabel;\r
prvTraceUpdateCounters();\r
}\r
- }\r
- trcCRITICAL_SECTION_END();\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
+ uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4]; \r
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
{\r
channel = xTraceRegisterChannelFormat(0, eventLabel);\r
}\r
\r
prvTraceUserEventHelper2(channel, tempDataBuffer, noOfSlots);\r
- }\r
+ } \r
#endif\r
}\r
\r