/*******************************************************************************\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
* trcStreamingRecorder.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
} ObjectDataTable;\r
\r
typedef struct{\r
- uint8_t Status;\r
+ uint16_t Status; /* 16 bit to avoid implicit padding (warnings) */\r
uint16_t BytesRemaining;\r
char* WritePointer;\r
} PageType;\r
\r
#define PSF_ASSERT(_assert, _err) if (! (_assert)){ prvTraceError(_err); return; }\r
\r
-#define PSF_ERROR_NONE 0\r
-#define PSF_ERROR_EVENT_CODE_TOO_LARGE 1\r
-#define PSF_ERROR_ISR_NESTING_OVERFLOW 2\r
-#define PSF_ERROR_DWT_NOT_SUPPORTED 3\r
-#define PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED 4\r
-#define PSF_ERROR_AUTO_ISR_END 5\r
-\r
/* Part of the PSF format - encodes the number of 32-bit params in an event */\r
#define PARAM_COUNT(n) ((n & 0xF) << 12)\r
\r
\r
uint32_t uiTraceTickCount = 0;\r
uint32_t timestampFrequency = 0;\r
-uint32_t DroppedEventCounter = 0; // Total number of dropped events (failed allocations)\r
-uint32_t TotalBytesRemaining_LowWaterMark = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;\r
-uint32_t TotalBytesRemaining = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;\r
+uint32_t DroppedEventCounter = 0;\r
+uint32_t TotalBytesRemaining_LowWaterMark = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);\r
+uint32_t TotalBytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);\r
\r
PageType PageInfo[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT];\r
\r
/*******************************************************************************\r
* LongestSymbolName\r
*\r
- * Updated in prvTraceSaveSymbol. Should not exceed SYMBOL_MAX_LENGTH, otherwise\r
- * symbol names will be truncated. In that case, set SYMBOL_MAX_LENGTH to (at\r
- * least) this value.\r
+ * Updated in prvTraceSaveSymbol. Should not exceed TRC_CFG_SYMBOL_MAX_LENGTH, \r
+ * otherwise symbol names will be truncated. In that case, set \r
+ * TRC_CFG_SYMBOL_MAX_LENGTH to (at least) this value.\r
******************************************************************************/\r
volatile uint32_t LongestSymbolName = 0;\r
\r
******************************************************************************/\r
volatile uint32_t MaxBytesTruncated = 0;\r
\r
+uint16_t CurrentFilterMask = 0xFFFF;\r
+\r
+uint16_t CurrentFilterGroup = FilterGroup0;\r
+\r
/* Internal common function for storing string events */\r
static void prvTraceStoreStringEventHelper( int nArgs,\r
uint16_t eventID,\r
traceString userEvtChannel,\r
+ int len,\r
const char* str,\r
va_list* vl);\r
-static void prvTraceStoreSimpleStringEventHelper( traceString userEvtChannel,\r
- const char* str);\r
\r
+/* Not static to avoid warnings from SysGCC/PPC */ \r
+void prvTraceStoreSimpleStringEventHelper(traceString userEvtChannel,\r
+ const char* str);\r
+\r
+ \r
/* Stores the header information on Start */\r
static void prvTraceStoreHeader(void);\r
\r
/* Retrieve a buffer page to write to. */\r
static int prvAllocateBufferPage(int prevPage);\r
\r
-/* Get the current buffer page index and remaining number of bytes. */\r
+/* Get the current buffer page index (return value) and the number \r
+of valid bytes in the buffer page (bytesUsed). */\r
static int prvGetBufferPage(int32_t* bytesUsed);\r
\r
/* Performs timestamping using definitions in trcHardwarePort.h */\r
/* Signal an error. */\r
void prvTraceError(int errCode);\r
\r
+/* Signal an warning (does not stop the recorder). */\r
+void prvTraceWarning(int errCode);\r
+\r
/******************************************************************************\r
* vTraceInstanceFinishedNow\r
*\r
prvTraceStoreEvent0(PSF_EVENT_IFE_NEXT);\r
}\r
\r
-/*******************************************************************************\r
- * xTraceRegisterString\r
- *\r
- * Stores a name for a user event channel, returns the handle.\r
- ******************************************************************************/\r
-traceString xTraceRegisterString(const char* name)\r
-{\r
- prvTraceSaveSymbol((const void*)name, name);\r
-\r
- /* Always save in symbol table, if the recording has not yet started */\r
- prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)name, (uint32_t)name);\r
-\r
- return (traceString)name;\r
-}\r
-\r
/*******************************************************************************\r
* vTraceStoreKernelObjectName\r
*\r
timestampFrequency = frequency;\r
}\r
\r
+#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)\r
+\r
+/*******************************************************************************\r
+* xTraceRegisterString\r
+*\r
+* Stores a name for a user event channel, returns the handle.\r
+******************************************************************************/\r
+traceString xTraceRegisterString(const char* name)\r
+{\r
+ prvTraceSaveSymbol((const void*)name, name);\r
+\r
+ /* Always save in symbol table, if the recording has not yet started */\r
+ prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)name, (uint32_t)name);\r
+\r
+ return (traceString)name;\r
+}\r
+\r
/******************************************************************************\r
* vTracePrint\r
*\r
{\r
if (fmt[i] == '%')\r
{\r
- if (fmt[i + 1] != '%')\r
+ if (fmt[i + 1] != 0 && fmt[i + 1] != '%')\r
{\r
nArgs++; /* Found an argument */\r
}\r
\r
if (chn != NULL)\r
{\r
- prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs + 1), chn, fmt, &vl);\r
+ prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs + 1), chn, i, fmt, &vl);\r
}\r
else\r
{\r
- prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs), chn, fmt, &vl);\r
+ prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs), chn, i, fmt, &vl);\r
}\r
-\r
va_end(vl);\r
}\r
+#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) */\r
\r
/*******************************************************************************\r
* xTraceSetISRProperties\r
if (ISR_stack_index == -1)\r
isPendingContextSwitch = 0; \r
\r
- if (ISR_stack_index < TRC_CFG_MAX_ISR_NESTING - 1)\r
+ if (ISR_stack_index < (TRC_CFG_MAX_ISR_NESTING) - 1)\r
{\r
ISR_stack_index++;\r
ISR_stack[ISR_stack_index] = (uint32_t)handle;\r
+#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)\r
prvTraceStoreEvent1(PSF_EVENT_ISR_BEGIN, (uint32_t)handle);\r
+#endif\r
TRACE_EXIT_CRITICAL_SECTION();\r
}\r
else\r
TRACE_ALLOC_CRITICAL_SECTION();\r
\r
TRACE_ENTER_CRITICAL_SECTION();\r
+ \r
+ (void)ISR_stack;\r
\r
/* Is there a pending task-switch? (perhaps from an earlier ISR) */\r
isPendingContextSwitch |= isTaskSwitchRequired;\r
{\r
ISR_stack_index--;\r
\r
+#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)\r
/* Store return to interrupted ISR (if nested ISRs)*/\r
prvTraceStoreEvent1(PSF_EVENT_ISR_RESUME, (uint32_t)ISR_stack[ISR_stack_index]);\r
+#endif\r
}\r
else\r
{\r
/* Store return to interrupted task, if no context switch will occur in between. */\r
if ((isPendingContextSwitch == 0) || (prvTraceIsSchedulerSuspended()))\r
{\r
+#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)\r
prvTraceStoreEvent1(PSF_EVENT_TS_RESUME, (uint32_t)TRACE_GET_CURRENT_TASK());\r
+#endif\r
}\r
}\r
\r
/*******************************************************************************\r
* xTraceGetLastError\r
*\r
- * Returns the last error, if any.\r
+ * Returns the last error or warning, as a string, or NULL if none.\r
*****************************************************************************/\r
const char* xTraceGetLastError(void)\r
{\r
- if (NoRoomForSymbol > 0)\r
+ /* Note: the error messages are short, in order to fit in a User Event.\r
+ Instead, the users can read more in the below comments.*/\r
+ \r
+ switch (errorCode)\r
{\r
- return "TRC_CFG_SYMBOL_TABLE_SLOTS too small.";\r
- }\r
+ \r
+ case PSF_WARNING_SYMBOL_TABLE_SLOTS:\r
+ /* There was not enough symbol table slots for storing symbol names.\r
+ The number of missing slots is counted by NoRoomForSymbol. Inspect this\r
+ variable and increase TRC_CFG_SYMBOL_TABLE_SLOTS by at least that value. */\r
+\r
+ return "Exceeded SYMBOL_TABLE_SLOTS (see xTraceGetLastError)";\r
+\r
+ case PSF_WARNING_SYMBOL_MAX_LENGTH:\r
+ /* A symbol name exceeded TRC_CFG_SYMBOL_MAX_LENGTH in length.\r
+ Make sure the symbol names are at most TRC_CFG_SYMBOL_MAX_LENGTH,\r
+ or inspect LongestSymbolName and increase TRC_CFG_SYMBOL_MAX_LENGTH\r
+ to at least this value. */\r
+\r
+ return "Exceeded SYMBOL_MAX_LENGTH (see xTraceGetLastError)";\r
+\r
+ case PSF_WARNING_OBJECT_DATA_SLOTS:\r
+ /* There was not enough symbol object table slots for storing object\r
+ properties, such as task priorites. The number of missing slots is \r
+ counted by NoRoomForObjectData. Inspect this variable and increase \r
+ TRC_CFG_OBJECT_DATA_SLOTS by at least that value. */\r
+ \r
+ return "Exceeded OBJECT_DATA_SLOTS (see xTraceGetLastError)";\r
\r
- if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH))\r
- {\r
- return "TRC_CFG_SYMBOL_MAX_LENGTH too small.";\r
- }\r
+ case PSF_WARNING_STRING_TOO_LONG:\r
+ /* Some string argument was longer than the maximum payload size\r
+ and has been truncated by "MaxBytesTruncated" bytes.\r
\r
- if (NoRoomForObjectData > 0)\r
- {\r
- return "TRC_CFG_OBJECT_DATA_SLOTS too small.";\r
- }\r
+ This may happen for the following functions:\r
+ - vTracePrint\r
+ - vTracePrintF\r
+ - vTraceStoreKernelObjectName\r
+ - xTraceRegisterString\r
+ - vTraceSetISRProperties\r
\r
- if (MaxBytesTruncated > 0)\r
- {\r
- return "String or User Event too long.";\r
- }\r
+ A PSF event may store maximum 60 bytes payload, including data\r
+ arguments and string characters. For User Events, also the User\r
+ Event Channel (4 bytes) must be squeezed in, if a channel is\r
+ specified (can be NULL). */\r
+\r
+ return "String too long (see xTraceGetLastError)";\r
+\r
+ case PSF_WARNING_STREAM_PORT_READ:\r
+ /* TRC_STREAM_PORT_READ_DATA is expected to return 0 when completed successfully.\r
+ This means there is an error in the communication with host/Tracealyzer. */\r
+\r
+ return "TRC_STREAM_PORT_READ_DATA returned error (!= 0).";\r
+\r
+ case PSF_WARNING_STREAM_PORT_WRITE:\r
+ /* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully.\r
+ This means there is an error in the communication with host/Tracealyzer. */\r
+\r
+ return "TRC_STREAM_PORT_WRITE_DATA returned error (!= 0).";\r
\r
- switch (errorCode)\r
- {\r
case PSF_ERROR_EVENT_CODE_TOO_LARGE:\r
- return "An invalid event code was used.";\r
+ /* The highest allowed event code is 4095, anything higher is an unexpected error. \r
+ Please contact support@percepio.com for assistance.*/\r
+ \r
+ return "Invalid event code (see xTraceGetLastError)";\r
+ \r
case PSF_ERROR_ISR_NESTING_OVERFLOW:\r
- return "Too much ISR nesting.";\r
+ /* Nesting of ISR trace calls exceeded the limit (TRC_CFG_MAX_ISR_NESTING).\r
+ If this is unlikely, make sure that you call vTraceStoreISRExit in the end \r
+ of all ISR handlers. Or increase TRC_CFG_MAX_ISR_NESTING. */\r
+\r
+ return "Exceeded ISR nesting (see xTraceGetLastError)";\r
+\r
case PSF_ERROR_DWT_NOT_SUPPORTED:\r
- return "DWT not supported by this chip.";\r
+ /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip.\r
+ DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M\r
+ macro normally set by ARM's CMSIS library, since typically available. You can however select\r
+ SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/\r
+\r
+ return "DWT not supported (see xTraceGetLastError)";\r
+\r
case PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED:\r
- return "DWT_CYCCNT not supported by this chip.";\r
+ /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip.\r
+ DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M\r
+ macro normally set by ARM's CMSIS library, since typically available. You can however select \r
+ SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/\r
+ \r
+ return "DWT_CYCCNT not supported (see xTraceGetLastError)";\r
+ \r
+ case PSF_ERROR_TZCTRLTASK_NOT_CREATED:\r
+ /* vTraceEnable failed creating the trace control task (TzCtrl) - incorrect parameters (priority?)\r
+ or insufficient heap size? */\r
+ return "Could not create TzCtrl (see xTraceGetLastError)";\r
+ \r
}\r
\r
- return "";\r
+ return NULL;\r
}\r
\r
/*******************************************************************************\r
}\r
#endif\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
+ return (int)RecorderEnabled;\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
/******************************************************************************/\r
/*** INTERNAL FUNCTIONS *******************************************************/\r
/******************************************************************************/\r
\r
TRACE_ALLOC_CRITICAL_SECTION();\r
\r
+ if (RecorderEnabled == isEnabled)\r
+ {\r
+ return;\r
+ }\r
+ \r
currentTask = TRACE_GET_CURRENT_TASK();\r
\r
TRACE_ENTER_CRITICAL_SECTION();\r
\r
if (RecorderEnabled)\r
{\r
- prvTraceOnBegin();\r
- \r
+ TRC_STREAM_PORT_ON_TRACE_BEGIN();\r
+\r
+ #if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)\r
+ prvPagedEventBufferInit(_TzTraceData);\r
+ #endif\r
+ \r
eventCounter = 0;\r
ISR_stack_index = -1;\r
prvTraceStoreHeader();\r
}\r
else\r
{\r
- prvTraceOnEnd();\r
+ TRC_STREAM_PORT_ON_TRACE_END();\r
}\r
\r
TRACE_EXIT_CRITICAL_SECTION();\r
}\r
\r
/* Stores the symbol table on Start */\r
-static void prvTraceStoreSymbolTable()\r
+static void prvTraceStoreSymbolTable(void)\r
{\r
uint32_t i = 0;\r
uint32_t j = 0;\r
}\r
\r
/* Stores the object table on Start */\r
-static void prvTraceStoreObjectDataTable()\r
+static void prvTraceStoreObjectDataTable(void)\r
{\r
uint32_t i = 0;\r
uint32_t j = 0;\r
}\r
\r
/* Stores the header information on Start */\r
-static void prvTraceStoreHeader()\r
+static void prvTraceStoreHeader(void)\r
{\r
TRACE_ALLOC_CRITICAL_SECTION();\r
\r
header->symbolSize = SYMBOL_TABLE_SLOT_SIZE;\r
header->symbolCount = (TRC_CFG_SYMBOL_TABLE_SLOTS);\r
header->objectDataSize = 8;\r
- header->objectDataCount = TRC_CFG_OBJECT_DATA_SLOTS;\r
+ header->objectDataCount = (TRC_CFG_OBJECT_DATA_SLOTS);\r
TRC_STREAM_PORT_COMMIT_EVENT(header, sizeof(PSFHeaderInfo));\r
}\r
}\r
}\r
\r
/* Store the current warnings */\r
-static void prvTraceStoreWarnings()\r
+static void prvTraceStoreWarnings(void)\r
{\r
- TRACE_ALLOC_CRITICAL_SECTION();\r
-\r
- TRACE_ENTER_CRITICAL_SECTION();\r
-\r
if (RecorderEnabled)\r
{\r
- if (NoRoomForSymbol > 0)\r
- {\r
- vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_TABLE_SLOTS too small. Add %d slots.", NoRoomForSymbol);\r
- }\r
-\r
- if (LongestSymbolName > 0)\r
- {\r
- if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH))\r
- {\r
- vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_MAX_LENGTH too small. Add %d chars.", LongestSymbolName - (TRC_CFG_SYMBOL_MAX_LENGTH));\r
- }\r
- }\r
-\r
- if (NoRoomForObjectData > 0)\r
- {\r
- /* We don't know how many objects we actually need to make room for since NoRoomForObjectData can be increased multiple times for the same object! */\r
- vTracePrintF(trcWarningChannel, "TRC_CFG_OBJECT_DATA_SLOTS too small. Add more slots.");\r
- }\r
+ const char* errStr = xTraceGetLastError();\r
\r
- if (MaxBytesTruncated > 0)\r
+ if (errStr != NULL)\r
{\r
- /* Some string event generated a too long string that was truncated.\r
- This may happen for the following functions:\r
- - vTracePrintF\r
- - vTraceStoreKernelObjectName\r
- - vTraceStoreUserEventChannelName\r
- - vTraceSetISRProperties\r
-\r
- A PSF event may store maximum 60 bytes payload, including data arguments\r
- and string characters. For User Events, also the User Event Channel ptr\r
- must be squeezed in, if a channel is specified. */\r
-\r
- vTracePrintF(trcWarningChannel, "String event too long, up to %d bytes truncated.", MaxBytesTruncated);\r
- }\r
-\r
- switch (errorCode)\r
- {\r
- case PSF_ERROR_EVENT_CODE_TOO_LARGE:\r
- break;\r
- case PSF_ERROR_ISR_NESTING_OVERFLOW: \r
- break;\r
- case PSF_ERROR_DWT_NOT_SUPPORTED:\r
- vTracePrintF(trcWarningChannel, "DWT not supported, see prvTraceInitCortexM.");\r
- break;\r
- case PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED:\r
- vTracePrintF(trcWarningChannel, "DWT_CYCCNT not supported, see prvTraceInitCortexM.");\r
- break;\r
+ vTracePrint(trcWarningChannel, errStr);\r
}\r
}\r
- TRACE_EXIT_CRITICAL_SECTION();\r
}\r
\r
/* Store an event with zero parameters (event ID only) */\r
/* Stories an event with a string and <nParam> 32-bit integer parameters */\r
void prvTraceStoreStringEvent(int nArgs, uint16_t eventID, const char* str, ...)\r
{\r
+ int len;\r
va_list vl;\r
\r
+ for (len = 0; (str[len] != 0) && (len < 52); len++); /* empty loop */\r
+\r
va_start(vl, str);\r
- prvTraceStoreStringEventHelper(nArgs, eventID, NULL, str, &vl);\r
+ prvTraceStoreStringEventHelper(nArgs, eventID, NULL, len, str, &vl);\r
va_end(vl);\r
}\r
\r
/* Internal common function for storing string events */\r
-static void prvTraceStoreStringEventHelper( int nArgs,\r
+static void prvTraceStoreStringEventHelper(int nArgs,\r
uint16_t eventID,\r
traceString userEvtChannel,\r
- const char* str, va_list* vl)\r
+ int len,\r
+ const char* str,\r
+ va_list* vl)\r
{\r
- int len;\r
int nWords;\r
int nStrWords;\r
int i;\r
TRACE_ALLOC_CRITICAL_SECTION();\r
\r
PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);\r
-\r
- for (len = 0; (str[len] != 0) && (len < 52); len++); /* empty loop */\r
\r
/* The string length in multiples of 32 bit words (+1 for null character) */\r
nStrWords = (len+1+3)/4;\r
}\r
\r
/* Internal common function for storing string events without additional arguments */\r
-static void prvTraceStoreSimpleStringEventHelper( traceString userEvtChannel,\r
- const char* str)\r
+void prvTraceStoreSimpleStringEventHelper(traceString userEvtChannel,\r
+ const char* str)\r
{\r
int len;\r
int nWords;\r
}\r
}\r
\r
+/* Called on warnings, when the recording can continue. */\r
+void prvTraceWarning(int errCode)\r
+{\r
+ if (!errorCode)\r
+ {\r
+ errorCode = errCode;\r
+ prvTraceStoreWarnings();\r
+ }\r
+}\r
+\r
/* Called on critical errors in the recorder. Stops the recorder! */\r
void prvTraceError(int errCode)\r
{\r
{\r
errorCode = errCode;\r
prvTraceStoreWarnings();\r
- vTracePrintF(trcWarningChannel, "Error detected. Stopped recorder.");\r
+ vTracePrintF(trcWarningChannel, "Recorder stopped in prvTraceError()");\r
\r
prvSetRecorderEnabled(0);\r
}\r
\r
#if ((TRC_HWTC_TYPE == TRC_OS_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))\r
uint32_t ticks = TRACE_GET_OS_TICKS();\r
- return (TRC_HWTC_COUNT & 0x00FFFFFFU) + ((ticks & 0x000000FFU) << 24);\r
+ return ((TRC_HWTC_COUNT) & 0x00FFFFFFU) + ((ticks & 0x000000FFU) << 24);\r
#endif\r
}\r
\r
timestampFrequency = TRC_HWTC_FREQ_HZ;\r
}\r
\r
- if (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR || TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR)\r
- {\r
+ #if (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR || TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR)\r
+ \r
prvTraceStoreEvent(5, \r
PSF_EVENT_TS_CONFIG,\r
(uint32_t)timestampFrequency, \r
- (uint32_t)TRACE_TICK_RATE_HZ,\r
- (uint32_t)TRC_HWTC_TYPE,\r
- (uint32_t)TRC_CFG_ISR_TAILCHAINING_THRESHOLD,\r
- (uint32_t)TRC_HWTC_PERIOD);\r
- }\r
- else\r
- {\r
+ (uint32_t)(TRACE_TICK_RATE_HZ),\r
+ (uint32_t)(TRC_HWTC_TYPE),\r
+ (uint32_t)(TRC_CFG_ISR_TAILCHAINING_THRESHOLD),\r
+ (uint32_t)(TRC_HWTC_PERIOD));\r
+ \r
+ #else\r
+ \r
prvTraceStoreEvent(4, \r
PSF_EVENT_TS_CONFIG,\r
(uint32_t)timestampFrequency, \r
- (uint32_t)TRACE_TICK_RATE_HZ,\r
- (uint32_t)TRC_HWTC_TYPE,\r
- (uint32_t)TRC_CFG_ISR_TAILCHAINING_THRESHOLD);\r
- }\r
+ (uint32_t)(TRACE_TICK_RATE_HZ),\r
+ (uint32_t)(TRC_HWTC_TYPE),\r
+ (uint32_t)(TRC_CFG_ISR_TAILCHAINING_THRESHOLD)); \r
+ #endif\r
}\r
\r
/* Retrieve a buffer page to write to. */\r
int index;\r
int count = 0;\r
\r
- index = (prevPage + 1) % TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT;\r
+ index = (prevPage + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);\r
\r
- while((PageInfo[index].Status != PAGE_STATUS_FREE) && (count ++ < TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT))\r
+ while((PageInfo[index].Status != PAGE_STATUS_FREE) && (count ++ < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT)))\r
{\r
- index = (index + 1) % TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT;\r
+ index = (index + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);\r
}\r
\r
if (PageInfo[index].Status == PAGE_STATUS_FREE)\r
TRACE_ALLOC_CRITICAL_SECTION();\r
\r
TRACE_ENTER_CRITICAL_SECTION();\r
- PageInfo[pageIndex].BytesRemaining = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;\r
- PageInfo[pageIndex].WritePointer = &EventBuffer[pageIndex * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE];\r
+ PageInfo[pageIndex].BytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);\r
+ PageInfo[pageIndex].WritePointer = &EventBuffer[pageIndex * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];\r
PageInfo[pageIndex].Status = PAGE_STATUS_FREE;\r
\r
- TotalBytesRemaining += TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;\r
+ TotalBytesRemaining += (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);\r
\r
TRACE_EXIT_CRITICAL_SECTION();\r
}\r
{\r
static int8_t lastPage = -1;\r
int count = 0;\r
- int8_t index = (int8_t) ((lastPage + 1) % TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);\r
+ int8_t index = (int8_t) ((lastPage + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT));\r
\r
- while((PageInfo[index].Status != PAGE_STATUS_READ) && (count++ < TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT))\r
+ while((PageInfo[index].Status != PAGE_STATUS_READ) && (count++ < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT)))\r
{\r
- index = (int8_t)((index + 1) % TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);\r
+ index = (int8_t)((index + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT));\r
}\r
\r
if (PageInfo[index].Status == PAGE_STATUS_READ)\r
{\r
- *bytesUsed = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE - PageInfo[index].BytesRemaining;\r
+ *bytesUsed = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE) - PageInfo[index].BytesRemaining;\r
lastPage = index;\r
return index;\r
}\r
}\r
\r
/*******************************************************************************\r
-\r
-int32_t prvPagedEventBufferTransfer(int32_t (*writeFunc)(void* data,\r
- uint32_t size),\r
- int32_t* nofBytes)\r
-\r
-Transfers one block of trace data, if available for reading. Returns the number\r
-of bytes transfered, or a negative error code. If data was transferred (return\r
-value > 0), it can be good to call this function again until all data available\r
-has been transfered.\r
-\r
-This function is intended to be called by a periodic task with a suitable\r
-delay (e.g. 10-100 ms).\r
-\r
-Return value: as returned from writeFunc (0 == OK)\r
-\r
-Parameters:\r
-\r
-- writeFunc\r
-Function pointer (example: int32_t write(void* data, uint32_t size))\r
-The function passed as writeFunc should write "size" bytes from "data" to the\r
-socket/file/channel, and return a status code where 0 means OK,\r
-and any other non-zero value means an error.\r
-\r
-- int32_t* nofBytes\r
-Pointer to an integer assigned the number of bytes that was transfered.\r
-\r
-*******************************************************************************/\r
-int32_t prvPagedEventBufferTransfer(int32_t (*writeFunc)(void* data, uint32_t size, int32_t* ptrBytesWritten), int32_t* nofBytes)\r
+ * uint32_t prvPagedEventBufferTransfer(void)\r
+ *\r
+ * Transfers one buffer page of trace data, if a full page is available, using\r
+ * the macro TRC_STREAM_PORT_WRITE_DATA as defined in trcStreamingPort.h.\r
+ *\r
+ * This function is intended to be called the periodic TzCtrl task with a suitable\r
+ * delay (e.g. 10-100 ms).\r
+ *\r
+ * Returns the number of bytes sent. If non-zero, it is good to call this \r
+ * again, in order to send any additional data waiting in the buffer.\r
+ * If zero, wait a while before calling again.\r
+ *\r
+ * In case of errors from the streaming interface, it registers a warning\r
+ * (PSF_WARNING_STREAM_PORT_WRITE) provided by xTraceGetLastError().\r
+ *\r
+ *******************************************************************************/\r
+uint32_t prvPagedEventBufferTransfer(void)\r
{\r
int8_t pageToTransfer = -1;\r
- int32_t transferred = 0;\r
- int32_t size = 0;\r
- \r
- pageToTransfer = (int8_t)prvGetBufferPage(nofBytes);\r
- size = *nofBytes; // The number of bytes we want to transfer\r
- transferred = 0; // The number of bytes we have transferred so far\r
+ int32_t bytesTransferredTotal = 0;\r
+ int32_t bytesTransferredNow = 0;\r
+ int32_t bytesToTransfer;\r
+\r
+ pageToTransfer = (int8_t)prvGetBufferPage(&bytesToTransfer);\r
\r
+ /* bytesToTransfer now contains the number of "valid" bytes in the buffer page, that should be transmitted.\r
+ There might be some unused junk bytes in the end, that must be ignored. */\r
+ \r
if (pageToTransfer > -1)\r
{\r
- while (1) // Keep going until we have transferred all that we intended to\r
+ while (1) /* Keep going until we have transferred all that we intended to */\r
{\r
- if (writeFunc(&EventBuffer[pageToTransfer * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE + transferred], (uint32_t)(size - transferred), nofBytes) == 0)\r
+ if (TRC_STREAM_PORT_WRITE_DATA(\r
+ &EventBuffer[pageToTransfer * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE) + bytesTransferredTotal],\r
+ (uint32_t)(bytesToTransfer - bytesTransferredTotal),\r
+ &bytesTransferredNow) == 0)\r
{\r
- // Write was successful. Update the number of transferred bytes.\r
- transferred += *nofBytes;\r
- if (size == transferred)\r
+ /* Write was successful. Update the number of transferred bytes. */\r
+ bytesTransferredTotal += bytesTransferredNow;\r
+\r
+ if (bytesTransferredTotal == bytesToTransfer)\r
{\r
- // All bytes have been transferred. Mark as Complete and return.\r
- *nofBytes = transferred;\r
+ /* All bytes have been transferred. Mark the buffer page as "Read Complete" (so it can be written to) and return OK. */\r
prvPageReadComplete(pageToTransfer);\r
- return 0;\r
+ return (uint32_t)bytesTransferredTotal;\r
}\r
}\r
else\r
{\r
- *nofBytes = 0;\r
- return 1;\r
+ /* Some error from the streaming interface... */\r
+ prvTraceWarning(PSF_WARNING_STREAM_PORT_WRITE);\r
+ return 0;\r
}\r
}\r
}\r
}\r
\r
/*******************************************************************************\r
-\r
-void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)\r
-\r
-Returns a pointer to an available location in the buffer able to store the\r
-requested size.\r
-\r
-Return value: The pointer.\r
-\r
-Parameters:\r
-\r
-- sizeOfEvent\r
-The size of the event that is to be placed in the buffer.\r
-\r
+ * void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)\r
+ *\r
+ * Returns a pointer to an available location in the buffer able to store the\r
+ * requested size.\r
+ * \r
+ * Return value: The pointer.\r
+ * \r
+ * Parameters:\r
+ * - sizeOfEvent: The size of the event that is to be placed in the buffer.\r
+ *\r
*******************************************************************************/\r
void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)\r
{\r
}\r
\r
/*******************************************************************************\r
-\r
-void prvPagedEventBufferInit(char* buffer)\r
-\r
-Assigns the buffer to use and initializes the PageInfo structure.\r
-\r
-Return value: void\r
-\r
-Parameters:\r
-\r
-- buffer\r
-Pointer to the buffer location that is dynamically or statically allocated by\r
-the caller.\r
-\r
+ * void prvPagedEventBufferInit(char* buffer)\r
+ *\r
+ * Assigns the buffer to use and initializes the PageInfo structure.\r
+ *\r
+ * Return value: void\r
+ * \r
+ * Parameters:\r
+ * - char* buffer: pointer to the trace data buffer, allocated by the caller.\r
+ *\r
*******************************************************************************/\r
void prvPagedEventBufferInit(char* buffer)\r
{\r
EventBuffer = buffer;\r
\r
TRACE_ENTER_CRITICAL_SECTION();\r
- for (i = 0; i < TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT; i++)\r
+ for (i = 0; i < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT); i++)\r
{\r
- PageInfo[i].BytesRemaining = TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE;\r
- PageInfo[i].WritePointer = &EventBuffer[i * TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE];\r
+ PageInfo[i].BytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);\r
+ PageInfo[i].WritePointer = &EventBuffer[i * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];\r
PageInfo[i].Status = PAGE_STATUS_FREE;\r
}\r
TRACE_EXIT_CRITICAL_SECTION();\r
+\r
}\r
\r
#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/\r