/*******************************************************************************\r
- * Trace Recorder Library for Tracealyzer v3.1.2\r
+ * Trace Recorder Library for Tracealyzer v4.1.1\r
* Percepio AB, www.percepio.com\r
*\r
* trcSnapshotRecorder.c\r
*\r
* Tabs are used for indent in this file (1 tab = 4 spaces)\r
*\r
- * Copyright Percepio AB, 2017.\r
+ * Copyright Percepio AB, 2018.\r
* www.percepio.com\r
******************************************************************************/\r
\r
#if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1\r
static int readyEventsEnabled = 1;\r
#endif /*!defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1*/\r
+\r
/*******************************************************************************\r
* uiTraceTickCount\r
*\r
uint32_t uiTraceTickCount = 0;\r
\r
uint32_t trace_disable_timestamp = 0;\r
+\r
static uint32_t last_timestamp = 0;\r
+\r
/* Flag that shows if inside a critical section of the recorder */\r
volatile int recorder_busy = 0;\r
\r
/* The last error message of the recorder. NULL if no error message. */\r
const char* traceErrorMessage = NULL;\r
\r
-\r
int8_t nISRactive = 0;\r
-traceHandle handle_of_last_logged_task = 0;\r
-uint8_t inExcludedTask = 0;\r
\r
-extern uint8_t inExcludedTask;\r
-extern int8_t nISRactive;\r
-extern traceHandle handle_of_last_logged_task;\r
+traceHandle handle_of_last_logged_task = 0;\r
\r
/* Called when the recorder is stopped, set by vTraceSetStopHook. */\r
TRACE_STOP_HOOK vTraceStopHookPtr = (TRACE_STOP_HOOK)0;\r
\r
+uint16_t CurrentFilterMask = 0xFFFF;\r
+\r
+uint16_t CurrentFilterGroup = FilterGroup0;\r
+\r
+extern int8_t nISRactive;\r
+\r
+extern traceHandle handle_of_last_logged_task;\r
+\r
/*************** Private Functions *******************************************/\r
static void prvStrncpy(char* dst, const char* src, uint32_t maxLength);\r
static uint8_t prvTraceGetObjectState(uint8_t objectclass, traceHandle id); \r
static traceString prvTraceOpenSymbol(const char* name, traceString userEventChannel);\r
static void prvTraceUpdateCounters(void);\r
\r
+void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_size);\r
+\r
#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)\r
static void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nEntries);\r
#endif\r
\r
\r
#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)\r
- /* Current heap usage. Always updated. */\r
- static uint32_t heapMemUsage = 0;\r
+static uint32_t heapMemUsage = 0;\r
#endif\r
\r
#if (TRC_CFG_SCHEDULING_ONLY == 0)\r
* vTraceSetStopHook\r
*\r
* Sets a function to be called when the recorder is stopped. This can be used\r
- * to save the trace to a file system, if available. \r
+ * to save the trace to a file system, if available. This is only implemented\r
+ * for snapshot mode.\r
******************************************************************************/\r
void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction)\r
{\r
\r
if (RecorderDataPtr == NULL)\r
{\r
- prvTraceError("RecorderDataPtr is NULL. Call vTraceInitTraceData() before starting trace.");\r
+ TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized. Use vTraceEnable() instead!", 0);\r
return 0;\r
}\r
\r
******************************************************************************/\r
void vTraceStop(void)\r
{\r
- RecorderDataPtr->recorderActive = 0;\r
+ if (RecorderDataPtr != NULL)\r
+ {\r
+ RecorderDataPtr->recorderActive = 0;\r
+ }\r
\r
if (vTraceStopHookPtr != (TRACE_STOP_HOOK)0)\r
{\r
}\r
}\r
\r
+/*******************************************************************************\r
+* xTraceIsRecordingEnabled\r
+* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0.\r
+******************************************************************************/\r
+int xTraceIsRecordingEnabled(void)\r
+{\r
+ if (RecorderDataPtr != NULL)\r
+ {\r
+ return (int)RecorderDataPtr->recorderActive;\r
+ }\r
+ else\r
+ {\r
+ return 0;\r
+ }\r
+}\r
+\r
/*******************************************************************************\r
* xTraceGetLastError\r
*\r
* prvTraceTaskInstanceFinish\r
*\r
* Private common function for the vTraceTaskInstanceFinishXXX functions.\r
- * \r
*****************************************************************************/\r
static void prvTraceTaskInstanceFinish(int8_t direct)\r
{\r
TRACE_ALLOC_CRITICAL_SECTION();\r
\r
trcCRITICAL_SECTION_BEGIN();\r
- if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
{\r
dts45 = (uint8_t)prvTraceGetDTS(0xFF);\r
tis = (TaskInstanceStatusEvent*) prvTraceNextFreeEventBufferSlot();\r
* processCommand(command);\r
* vTraceInstanceFinishedNext();\r
* }\r
- *\r
- * Note: This is only supported in Tracealyzer tools v2.7 or later\r
- *\r
*****************************************************************************/\r
void vTraceInstanceFinishedNext(void)\r
{\r
* DoSometingElse();\r
* vTraceInstanceFinishedNext();\r
* }\r
- *\r
- * Note: This is only supported in Tracealyzer tools v2.7 or later\r
- *\r
*****************************************************************************/\r
void vTraceInstanceFinishedNow(void)\r
{\r
* ...\r
* vTraceStoreISREnd(0);\r
* }\r
- *\r
******************************************************************************/\r
traceHandle xTraceSetISRProperties(const char* name, uint8_t priority)\r
{\r
- static traceHandle handle = 0;\r
- handle++;\r
+ static traceHandle handle = 0; \r
+ TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);\r
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "xTraceSetISRProperties: Invalid value for handle", 0);\r
TRACE_ASSERT(name != NULL, "xTraceSetISRProperties: name == NULL", 0);\r
\r
+ handle++;\r
+\r
prvTraceSetObjectName(TRACE_CLASS_ISR, handle, name);\r
prvTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority);\r
\r
* ...\r
* vTraceStoreISREnd(0);\r
* }\r
- *\r
******************************************************************************/\r
void vTraceStoreISRBegin(traceHandle handle)\r
{\r
{\r
uint16_t dts4;\r
\r
- TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", TRC_UNUSED);\r
+ TRACE_ASSERT(handle != 0, "vTraceStoreISRBegin: Invalid ISR handle (NULL)", TRC_UNUSED); \r
+ TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid ISR handle (> NISR)", TRC_UNUSED);\r
\r
dts4 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
\r
* ...\r
* vTraceStoreISREnd(0);\r
* }\r
- *\r
******************************************************************************/\r
void vTraceStoreISREnd(int pendingISR)\r
{\r
}\r
#endif /* (TRC_CFG_INCLUDE_ISR_TRACING == 1)*/\r
\r
+\r
/********************************************************************************/\r
/* User Event functions */\r
/********************************************************************************/\r
{\r
uint32_t slots;\r
\r
- TRACE_ASSERT(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE >= count,\r
+ TRACE_ASSERT((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) >= count,\r
"prvTraceClearChannelBuffer: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);\r
\r
/* Check if we're close to the end of the buffer */\r
- if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE)\r
+ if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE))\r
{\r
- slots = TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */\r
+ slots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */\r
(void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite], 0, slots);\r
(void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[0], 0, (count - slots));\r
}\r
\r
TRACE_ASSERT(data != NULL,\r
"prvTraceCopyToDataBuffer: data == NULL.", TRC_UNUSED);\r
- TRACE_ASSERT(count <= TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE,\r
+ TRACE_ASSERT(count <= (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE),\r
"prvTraceCopyToDataBuffer: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);\r
/* Check if we're close to the end of the buffer */\r
- if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE)\r
+ if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE))\r
{\r
- slots = TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */\r
+ slots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */\r
(void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite * 4], data, slots * 4);\r
(void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[0], data + slots, (count - slots) * 4);\r
}\r
\r
TRACE_ALLOC_CRITICAL_SECTION();\r
\r
- TRACE_ASSERT(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE >= noOfSlots, "prvTraceUBHelper2: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);\r
+ TRACE_ASSERT((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) >= noOfSlots, "prvTraceUBHelper2: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);\r
\r
trcCRITICAL_SECTION_BEGIN();\r
/* Store the timestamp */\r
prvTraceCopyToDataBuffer(data, noOfSlots); /* Will wrap around the data if necessary */\r
\r
old_nextSlotToWrite = RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Save the index that we want to write the channel data at when we're done */\r
- RecorderDataPtr->userEventBuffer.nextSlotToWrite = (RecorderDataPtr->userEventBuffer.nextSlotToWrite + noOfSlots) % TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE; /* Make sure we never end up outside the buffer */\r
+ RecorderDataPtr->userEventBuffer.nextSlotToWrite = (RecorderDataPtr->userEventBuffer.nextSlotToWrite + noOfSlots) % (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE); /* Make sure we never end up outside the buffer */\r
\r
/* Write to the channel buffer to indicate that this user event is ready to be used */\r
if (channel != 0)\r
TRACE_ASSERT(formatStr != 0, "xTraceRegisterChannelFormat: formatStr == 0", (traceUBChannel)0);\r
\r
trcCRITICAL_SECTION_BEGIN();\r
- for (i = 1; i <= TRC_CFG_UB_CHANNELS; i++) /* Size of the channels buffer is TRC_CFG_UB_CHANNELS + 1. Index 0 is unused. */\r
+ for (i = 1; i <= (TRC_CFG_UB_CHANNELS); i++) /* Size of the channels buffer is TRC_CFG_UB_CHANNELS + 1. Index 0 is unused. */\r
{\r
if(RecorderDataPtr->userEventBuffer.channels[i].name == 0 && RecorderDataPtr->userEventBuffer.channels[i].defaultFormat == 0)\r
{\r
*\r
* Slightly faster version of vTracePrintF() due to no lookups.\r
*\r
- * Note: This is only available if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is enabled in\r
- * trcConfig.h\r
- *\r
+ * Note: This is only available if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is\r
+ * enabled in trcSnapshotConfig.h\r
******************************************************************************/\r
#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))\r
void vTraceUBData(traceUBChannel channelPair, ...)\r
traceString formatStr;\r
\r
TRACE_ASSERT(channelPair != 0, "vTraceUBData_Helper: channelPair == 0", TRC_UNUSED);\r
- TRACE_ASSERT(channelPair <= TRC_CFG_UB_CHANNELS, "vTraceUBData_Helper: ", TRC_UNUSED);\r
+ TRACE_ASSERT(channelPair <= (TRC_CFG_UB_CHANNELS), "vTraceUBData_Helper: ", TRC_UNUSED);\r
\r
channel = RecorderDataPtr->userEventBuffer.channels[channelPair].name;\r
formatStr = RecorderDataPtr->userEventBuffer.channels[channelPair].defaultFormat;\r
uint32_t data[(3 + MAX_ARG_SIZE) / 4];\r
\r
TRACE_ASSERT(channelPair != 0, "vTraceUBEvent: channelPair == 0", TRC_UNUSED);\r
- TRACE_ASSERT(channelPair <= TRC_CFG_UB_CHANNELS, "vTraceUBEvent: ", TRC_UNUSED);\r
+ TRACE_ASSERT(channelPair <= (TRC_CFG_UB_CHANNELS), "vTraceUBEvent: ", TRC_UNUSED);\r
\r
prvTraceUBHelper2(channelPair, data, 1); /* Only need one slot for timestamp */\r
}\r
\r
trcCRITICAL_SECTION_BEGIN();\r
\r
- if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
+ if (RecorderDataPtr->recorderActive && 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
RecorderDataPtr->nextFreeIndex += noOfSlots;\r
RecorderDataPtr->numEvents += noOfSlots;\r
\r
- if (RecorderDataPtr->nextFreeIndex >= TRC_CFG_EVENT_BUFFER_SIZE)\r
+ if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))\r
{\r
#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)\r
/* We have reached the end, but this is a ring buffer. Start from the beginning again. */\r
traceString formatLabel;\r
traceUBChannel channel;\r
\r
- if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
{\r
formatLabel = xTraceRegisterString(formatStr);\r
\r
TRACE_ALLOC_CRITICAL_SECTION();\r
\r
trcCRITICAL_SECTION_BEGIN();\r
- if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
{\r
dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
ue = (UserEvent*) prvTraceNextFreeEventBufferSlot();\r
traceUBChannel channel;\r
uint32_t noOfSlots = 1;\r
uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];\r
- if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
{\r
traceString trcStr = prvTraceOpenSymbol(str, chn);\r
channel = xTraceRegisterUBChannel(chn, trcStr);\r
* myEventHandle = xTraceRegisterString("MyUserEvent");\r
* ...\r
* vTracePrintF(myEventHandle, "My value is: %d", myValue);\r
- *\r
******************************************************************************/\r
#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))\r
traceString xTraceRegisterString(const char* label)\r
{\r
TRACE_ASSERT(label != NULL, "xTraceRegisterString: label == NULL", (traceString)0);\r
-\r
+ TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);\r
return prvTraceOpenSymbol(label, 0);\r
}\r
#endif\r
return;\r
}\r
\r
- TRACE_ASSERT(handle <= TRC_CFG_NTASK, "prvTraceStoreTaskReady: Invalid value for handle", TRC_UNUSED);\r
+ TRACE_ASSERT(handle <= (TRC_CFG_NTASK), "prvTraceStoreTaskReady: Invalid value for handle", TRC_UNUSED);\r
\r
if (recorder_busy)\r
{\r
trcCRITICAL_SECTION_BEGIN();\r
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
{\r
- if (!TRACE_GET_TASK_FLAG_ISEXCLUDED(handle))\r
+ dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
+ hnd8 = prvTraceGet8BitHandle(handle);\r
+ tr = (TREvent*)prvTraceNextFreeEventBufferSlot();\r
+ if (tr != NULL)\r
{\r
- dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
- hnd8 = prvTraceGet8BitHandle(handle);\r
- tr = (TREvent*)prvTraceNextFreeEventBufferSlot();\r
- if (tr != NULL)\r
- {\r
- tr->type = DIV_TASK_READY;\r
- tr->dts = dts3;\r
- tr->objHandle = hnd8;\r
- prvTraceUpdateCounters();\r
- }\r
+ tr->type = DIV_TASK_READY;\r
+ tr->dts = dts3;\r
+ tr->objHandle = hnd8;\r
+ prvTraceUpdateCounters();\r
}\r
}\r
trcCRITICAL_SECTION_END();\r
\r
if (RecorderDataPtr->recorderActive)\r
{\r
- /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */\r
- if (nISRactive || !inExcludedTask)\r
+ dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
+ size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);\r
+ ms = (MemEventSize *)prvTraceNextFreeEventBufferSlot();\r
+\r
+ if (ms != NULL)\r
{\r
- dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
- size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);\r
- ms = (MemEventSize *)prvTraceNextFreeEventBufferSlot();\r
+ ms->dts = dts1;\r
+ ms->type = NULL_EVENT; /* Updated when all events are written */\r
+ ms->size = size_low;\r
+ prvTraceUpdateCounters();\r
\r
- if (ms != NULL)\r
- {\r
- ms->dts = dts1;\r
- ms->type = NULL_EVENT; /* Updated when all events are written */\r
- ms->size = size_low;\r
- prvTraceUpdateCounters();\r
-\r
- /* Storing a second record with address (signals "failed" if null) */\r
- #if (TRC_CFG_HEAP_SIZE_BELOW_16M)\r
- /* If the heap address range is within 16 MB, i.e., the upper 8 bits\r
- of addresses are constant, this optimization avoids storing an extra\r
- event record by ignoring the upper 8 bit of the address */\r
- addr_low = address & 0xFFFF; \r
- addr_high = (address >> 16) & 0xFF;\r
- #else\r
- /* The whole 32 bit address is stored using a second event record\r
- for the upper 16 bit */\r
- addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address);\r
- addr_high = 0;\r
- #endif\r
+ /* Storing a second record with address (signals "failed" if null) */\r
+ #if (TRC_CFG_HEAP_SIZE_BELOW_16M)\r
+ /* If the heap address range is within 16 MB, i.e., the upper 8 bits\r
+ of addresses are constant, this optimization avoids storing an extra\r
+ event record by ignoring the upper 8 bit of the address */\r
+ addr_low = address & 0xFFFF; \r
+ addr_high = (address >> 16) & 0xFF;\r
+ #else\r
+ /* The whole 32 bit address is stored using a second event record\r
+ for the upper 16 bit */\r
+ addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address);\r
+ addr_high = 0;\r
+ #endif\r
\r
- ma = (MemEventAddr *) prvTraceNextFreeEventBufferSlot();\r
- if (ma != NULL)\r
- {\r
- ma->addr_low = addr_low;\r
- ma->addr_high = addr_high;\r
- ma->type = (uint8_t) (ecode + 1); /* Note this! */\r
- ms->type = (uint8_t) ecode;\r
- prvTraceUpdateCounters(); \r
- RecorderDataPtr->heapMemUsage = heapMemUsage;\r
- }\r
+ ma = (MemEventAddr *) prvTraceNextFreeEventBufferSlot();\r
+ if (ma != NULL)\r
+ {\r
+ ma->addr_low = addr_low;\r
+ ma->addr_high = addr_high;\r
+ ma->type = (uint8_t) (ecode + 1); /* Note this! */\r
+ ms->type = (uint8_t) ecode;\r
+ prvTraceUpdateCounters(); \r
+ RecorderDataPtr->heapMemUsage = heapMemUsage;\r
}\r
}\r
}\r
trcCRITICAL_SECTION_BEGIN();\r
if (RecorderDataPtr->recorderActive)\r
{\r
- /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */\r
- if (nISRactive || !inExcludedTask)\r
+ dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
+ hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);\r
+ kse = (KernelCall*) prvTraceNextFreeEventBufferSlot();\r
+ if (kse != NULL)\r
{\r
- /* Check if the referenced object or the event code is excluded */\r
- if (!uiTraceIsObjectExcluded(objectClass, (traceHandle)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))\r
- {\r
- dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
- hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);\r
- kse = (KernelCall*) prvTraceNextFreeEventBufferSlot();\r
- if (kse != NULL)\r
- {\r
- kse->dts = dts1;\r
- kse->type = (uint8_t)ecode;\r
- kse->objHandle = hnd8;\r
- prvTraceUpdateCounters();\r
- }\r
- }\r
+ kse->dts = dts1;\r
+ kse->type = (uint8_t)ecode;\r
+ kse->objHandle = hnd8;\r
+ prvTraceUpdateCounters();\r
}\r
}\r
trcCRITICAL_SECTION_END();\r
}\r
\r
trcCRITICAL_SECTION_BEGIN();\r
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && (! inExcludedTask || nISRactive))\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
{\r
- /* Check if the referenced object or the event code is excluded */\r
- if (!uiTraceIsObjectExcluded(objectClass, (traceHandle)objectNumber) &&\r
- !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
+ dts2 = (uint8_t)prvTraceGetDTS(0xFF);\r
+ p8 = (uint8_t) prvTraceGetParam(0xFF, param);\r
+ hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);\r
+ kse = (KernelCallWithParamAndHandle*) prvTraceNextFreeEventBufferSlot();\r
+ if (kse != NULL)\r
{\r
- dts2 = (uint8_t)prvTraceGetDTS(0xFF);\r
- p8 = (uint8_t) prvTraceGetParam(0xFF, param);\r
- hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);\r
- kse = (KernelCallWithParamAndHandle*) prvTraceNextFreeEventBufferSlot();\r
- if (kse != NULL)\r
- {\r
- kse->dts = dts2;\r
- kse->type = (uint8_t)evtcode;\r
- kse->objHandle = hnd8;\r
- kse->param = p8;\r
- prvTraceUpdateCounters();\r
- }\r
+ kse->dts = dts2;\r
+ kse->type = (uint8_t)evtcode;\r
+ kse->objHandle = hnd8;\r
+ kse->param = p8;\r
+ prvTraceUpdateCounters();\r
}\r
}\r
trcCRITICAL_SECTION_END();\r
}\r
\r
trcCRITICAL_SECTION_BEGIN();\r
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task\r
- && (! inExcludedTask || nISRactive))\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
{\r
- /* Check if the event code is excluded */\r
- if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
+ dts6 = (uint8_t)prvTraceGetDTS(0xFF);\r
+ restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);\r
+ kse = (KernelCallWithParam16*) prvTraceNextFreeEventBufferSlot();\r
+ if (kse != NULL)\r
{\r
- dts6 = (uint8_t)prvTraceGetDTS(0xFF);\r
- restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);\r
- kse = (KernelCallWithParam16*) prvTraceNextFreeEventBufferSlot();\r
- if (kse != NULL)\r
- {\r
- kse->dts = dts6;\r
- kse->type = (uint8_t)evtcode;\r
- kse->param = restParam;\r
- prvTraceUpdateCounters();\r
- }\r
+ kse->dts = dts6;\r
+ kse->type = (uint8_t)evtcode;\r
+ kse->param = restParam;\r
+ prvTraceUpdateCounters();\r
}\r
}\r
trcCRITICAL_SECTION_END();\r
{\r
uint16_t dts3;\r
TSEvent* ts;\r
- int8_t skipEvent;\r
uint8_t hnd8;\r
#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)\r
extern int32_t isPendingContextSwitch;\r
#endif\r
trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY();\r
\r
- skipEvent = 0;\r
-\r
- TRACE_ASSERT(task_handle <= TRC_CFG_NTASK,\r
+ TRACE_ASSERT(task_handle <= (TRC_CFG_NTASK),\r
"prvTraceStoreTaskswitch: Invalid value for task_handle", TRC_UNUSED);\r
\r
- /* Skip the event if the task has been excluded, using vTraceExcludeTask */\r
- if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))\r
- {\r
- skipEvent = 1;\r
- inExcludedTask = 1;\r
- }\r
- else\r
- {\r
- inExcludedTask = 0;\r
- }\r
-\r
trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY();\r
\r
- /* Skip the event if the same task is scheduled */\r
- if (task_handle == handle_of_last_logged_task)\r
- {\r
- skipEvent = 1;\r
- }\r
-\r
- if (!RecorderDataPtr->recorderActive)\r
- {\r
- skipEvent = 1;\r
- }\r
-\r
- /* If this event should be logged, log it! */\r
- if (skipEvent == 0)\r
+ if ((task_handle != handle_of_last_logged_task) && (RecorderDataPtr->recorderActive))\r
{\r
#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)\r
isPendingContextSwitch = 0;\r
* and name (a symbol table handle). The stored name-handle mapping is thus the\r
* "old" one, valid up until this point.\r
******************************************************************************/\r
-#if (TRC_CFG_INCLUDE_OBJECT_DELETE == 1)\r
-void prvTraceStoreObjectNameOnCloseEvent(traceHandle handle,\r
+void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle,\r
traceObjectClass objectclass)\r
{\r
ObjCloseNameEvent * ce;\r
ce = (ObjCloseNameEvent*) prvTraceNextFreeEventBufferSlot();\r
if (ce != NULL)\r
{\r
- ce->type = (uint8_t) (EVENTGROUP_OBJCLOSE_NAME + objectclass);\r
+ ce->type = (uint8_t) evtcode;\r
ce->objHandle = hnd8;\r
ce->symbolIndex = idx;\r
prvTraceUpdateCounters();\r
}\r
}\r
\r
-void prvTraceStoreObjectPropertiesOnCloseEvent(traceHandle handle,\r
+void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle,\r
traceObjectClass objectclass)\r
{\r
ObjClosePropEvent * pe;\r
{\r
pe->arg1 = TRACE_PROPERTY_OBJECT_STATE(objectclass, handle);\r
}\r
- pe->type = (uint8_t) (EVENTGROUP_OBJCLOSE_PROP + objectclass);\r
+ pe->type = evtcode;\r
prvTraceUpdateCounters();\r
}\r
}\r
}\r
-#endif\r
\r
void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value)\r
{\r
* Static data initializations\r
******************************************************************************/\r
\r
-/* Tasks and kernel objects can be explicitly excluded from the trace to reduce\r
-buffer usage. This structure handles the exclude flags for all objects and tasks. \r
-Note that slot 0 is not used, since not a valid handle. */\r
-uint8_t trcExcludedObjects[(TRACE_KERNEL_OBJECT_COUNT + TRACE_NCLASSES) / 8 + 1] = { 0 };\r
-\r
-/* Specific events can also be excluded, i.e., by the event code. This can be\r
-used to exclude kernel calls that don't refer to a kernel object, like a delay.\r
-This structure handle the exclude flags for all event codes */\r
-uint8_t trcExcludedEventCodes[NEventCodes / 8 + 1] = { 0 };\r
-\r
/* A set of stacks that keeps track of available object handles for each class.\r
The stacks are empty initially, meaning that allocation of new handles will be \r
based on a counter (for each object class). Any delete operation will\r
RecorderDataPtr->minor_version = TRACE_MINOR_VERSION;\r
RecorderDataPtr->irq_priority_order = TRC_IRQ_PRIORITY_ORDER;\r
RecorderDataPtr->filesize = sizeof(RecorderDataType);\r
- RecorderDataPtr->maxEvents = TRC_CFG_EVENT_BUFFER_SIZE;\r
+ RecorderDataPtr->maxEvents = (TRC_CFG_EVENT_BUFFER_SIZE);\r
RecorderDataPtr->debugMarker0 = (int32_t) 0xF0F0F0F0;\r
RecorderDataPtr->isUsing16bitHandles = TRC_CFG_USE_16BIT_OBJECT_HANDLES;\r
RecorderDataPtr->isrTailchainingThreshold = TRC_CFG_ISR_TAILCHAINING_THRESHOLD;\r
vTraceInitObjectPropertyTable();\r
\r
RecorderDataPtr->debugMarker1 = (int32_t)0xF1F1F1F1;\r
- RecorderDataPtr->SymbolTable.symTableSize = TRC_CFG_SYMBOL_TABLE_SIZE;\r
+ RecorderDataPtr->SymbolTable.symTableSize = (TRC_CFG_SYMBOL_TABLE_SIZE);\r
RecorderDataPtr->SymbolTable.nextFreeSymbolIndex = 1;\r
#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1)\r
RecorderDataPtr->exampleFloatEncoding = 1.0f; /* otherwise already zero */\r
#if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER\r
RecorderDataPtr->userEventBuffer.bufferID = 1;\r
RecorderDataPtr->userEventBuffer.version = 0;\r
- RecorderDataPtr->userEventBuffer.numberOfSlots = TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE;\r
- RecorderDataPtr->userEventBuffer.numberOfChannels = TRC_CFG_UB_CHANNELS + 1;\r
+ RecorderDataPtr->userEventBuffer.numberOfSlots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE);\r
+ RecorderDataPtr->userEventBuffer.numberOfChannels = (TRC_CFG_UB_CHANNELS) + 1;\r
#endif\r
\r
/* Kernel specific initialization of the objectHandleStacks variable */\r
RecorderDataPtr->startmarker1 = 0x02; \r
RecorderDataPtr->startmarker0 = 0x01; \r
\r
+ if (traceErrorMessage != NULL)\r
+ {\r
+ // An error was detected before vTraceEnable was called, make sure this is stored in the trace data.\r
+ prvStrncpy(RecorderDataPtr->systemInfo, traceErrorMessage, 80);\r
+ RecorderDataPtr->internalErrorOccured = 1;\r
+ vTraceStop();\r
+ }\r
+\r
+\r
\r
#ifdef TRC_PORT_SPECIFIC_INIT\r
TRC_PORT_SPECIFIC_INIT();\r
return NULL;\r
}\r
\r
- if (RecorderDataPtr->nextFreeIndex >= TRC_CFG_EVENT_BUFFER_SIZE)\r
+ if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))\r
{\r
prvTraceError("Attempt to index outside event buffer!");\r
return NULL;\r
traceHandle handle;\r
static int indexOfHandle;\r
\r
+ TRACE_ALLOC_CRITICAL_SECTION();\r
+\r
+ TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);\r
+ \r
TRACE_ASSERT(objectclass < TRACE_NCLASSES, \r
"prvTraceGetObjectHandle: Invalid value for objectclass", (traceHandle)0);\r
\r
+ trcCRITICAL_SECTION_BEGIN();\r
indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass];\r
if (objectHandleStacks.objectHandles[indexOfHandle] == 0)\r
{\r
objectHandleStacks.handleCountWaterMarksOfClass[objectclass] =\r
(traceHandle)hndCount;\r
}\r
- TRACE_CLEAR_OBJECT_FLAG_ISEXCLUDED(objectclass, handle);\r
}\r
+ trcCRITICAL_SECTION_END();\r
+\r
return handle;\r
}\r
\r
void prvTraceError(const char* msg)\r
{\r
/* Stop the recorder */\r
- vTraceStop();\r
- \r
+ if (RecorderDataPtr != NULL)\r
+ {\r
+ vTraceStop();\r
+ }\r
+\r
/* If first error only... */\r
if (traceErrorMessage == NULL)\r
{\r
}\r
}\r
\r
+void vTraceSetFilterMask(uint16_t filterMask)\r
+{\r
+ CurrentFilterMask = filterMask;\r
+}\r
+\r
+void vTraceSetFilterGroup(uint16_t filterGroup)\r
+{\r
+ CurrentFilterGroup = filterGroup;\r
+}\r
+\r
/******************************************************************************\r
* prvCheckDataToBeOverwrittenForMultiEntryEvents\r
*\r
\r
RecorderDataPtr->nextFreeIndex++;\r
\r
- if (RecorderDataPtr->nextFreeIndex >= TRC_CFG_EVENT_BUFFER_SIZE)\r
+ if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))\r
{\r
#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)\r
RecorderDataPtr->bufferIsFull = 1;\r
if (timestampFrequency != 0)\r
{\r
/* If to override default TRC_HWTC_FREQ_HZ value with value set by vTraceSetFrequency */\r
- RecorderDataPtr->frequency = timestampFrequency / TRC_HWTC_DIVISOR;\r
+ RecorderDataPtr->frequency = timestampFrequency / (TRC_HWTC_DIVISOR);\r
} \r
- else if (init_hwtc_count != TRC_HWTC_COUNT)\r
+ else if (init_hwtc_count != (TRC_HWTC_COUNT))\r
{\r
/* If using default value and timer has been started. \r
Note: If the default frequency value set here would be incorrect, e.g.,\r
if the timer has actually not been configured yet, override this \r
with vTraceSetFrequency.\r
*/\r
- RecorderDataPtr->frequency = TRC_HWTC_FREQ_HZ / TRC_HWTC_DIVISOR; \r
+ RecorderDataPtr->frequency = (TRC_HWTC_FREQ_HZ) / (TRC_HWTC_DIVISOR); \r
}\r
/* If no override (vTraceSetFrequency) and timer inactive -> no action */\r
}\r
TRACE_ASSERT(name != NULL, "prvTraceCreateSymbolTableEntry: name == NULL", 0);\r
TRACE_ASSERT(len != 0, "prvTraceCreateSymbolTableEntry: len == 0", 0);\r
\r
- if (RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + len + 4 >= TRC_CFG_SYMBOL_TABLE_SIZE)\r
+ if (RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + len + 4 >= (TRC_CFG_SYMBOL_TABLE_SIZE))\r
{\r
prvTraceError("Symbol table full. Increase TRC_CFG_SYMBOL_TABLE_SIZE in trcConfig.h");\r
ret = 0;\r
/* Retrieve TRC_HWTC_COUNT only once since the same value should be used all throughout this function. */\r
#if (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_INCR)\r
/* Get the increasing tick count */\r
- hwtc_count = TRC_HWTC_COUNT;\r
+ hwtc_count = (TRC_HWTC_COUNT);\r
#elif (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR || TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_DECR)\r
/* Convert decreasing tick count into increasing tick count */\r
- hwtc_count = TRC_HWTC_PERIOD - TRC_HWTC_COUNT;\r
+ hwtc_count = (TRC_HWTC_PERIOD) - (TRC_HWTC_COUNT);\r
#else\r
#error "TRC_HWTC_TYPE has unexpected value"\r
#endif\r
if (pTimestamp)\r
{\r
/* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */\r
- last_timestamp = traceTickCount * (TRC_HWTC_PERIOD / TRC_HWTC_DIVISOR);\r
+ last_timestamp = traceTickCount * ((TRC_HWTC_PERIOD) / (TRC_HWTC_DIVISOR));\r
/* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / TRC_HWTC_DIVISOR. */\r
- last_timestamp += (hwtc_count + traceTickCount * (TRC_HWTC_PERIOD % TRC_HWTC_DIVISOR)) / TRC_HWTC_DIVISOR;\r
+ last_timestamp += (hwtc_count + traceTickCount * ((TRC_HWTC_PERIOD) % (TRC_HWTC_DIVISOR))) / (TRC_HWTC_DIVISOR);\r
}\r
/* Store the previous value */\r
last_traceTickCount = traceTickCount;\r
diff = (hwtc_count - last_hwtc_count) + last_hwtc_rest;\r
\r
/* Scale down the diff */\r
- diff_scaled = diff / TRC_HWTC_DIVISOR;\r
+ diff_scaled = diff / (TRC_HWTC_DIVISOR);\r
\r
/* Find out how many ticks were lost when scaling down, so we can add them the next time */\r
- last_hwtc_rest = diff % TRC_HWTC_DIVISOR;\r
+ last_hwtc_rest = diff % (TRC_HWTC_DIVISOR);\r
\r
/* We increase the scaled timestamp by the scaled amount */\r
last_timestamp += diff_scaled;\r