]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c
Update trace recorder code.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace / trcStreamingRecorder.c
index 65a7d11a4cd8983a26fad57849a29dd9a523296b..c86d688e6baffbe1d712bf802e36a05e330008f8 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\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
@@ -38,7 +38,7 @@
  *\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
@@ -121,7 +121,7 @@ typedef struct{
 } 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
@@ -135,13 +135,6 @@ typedef struct{
 \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
@@ -190,9 +183,9 @@ int32_t isPendingContextSwitch = 0;
 \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
@@ -228,9 +221,9 @@ volatile uint32_t NoRoomForObjectData = 0;
 /*******************************************************************************\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
@@ -245,15 +238,23 @@ volatile uint32_t LongestSymbolName = 0;
  ******************************************************************************/\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
@@ -278,7 +279,8 @@ static void prvPageReadComplete(int pageIndex);
 /* 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
@@ -287,6 +289,9 @@ static uint32_t prvGetTimestamp32(void);
 /* 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
@@ -315,21 +320,6 @@ void vTraceInstanceFinishedNext(void)
        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
@@ -362,6 +352,23 @@ void vTraceSetFrequency(uint32_t frequency)
        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
@@ -450,7 +457,7 @@ void vTracePrintF(traceString chn, const char* fmt, ...)
        {\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
@@ -463,15 +470,15 @@ void vTracePrintF(traceString chn, const char* fmt, ...)
        \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
@@ -536,11 +543,13 @@ void vTraceStoreISRBegin(traceHandle handle)
        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
@@ -578,6 +587,8 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
        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
@@ -586,8 +597,10 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
        {\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
@@ -596,7 +609,9 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
                /* 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
@@ -607,43 +622,106 @@ void vTraceStoreISREnd(int isTaskSwitchRequired)
 /*******************************************************************************\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
@@ -686,6 +764,27 @@ void vTraceSetRecorderDataBuffer(void* pRecorderData)
 }\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
@@ -697,6 +796,11 @@ static void prvSetRecorderEnabled(uint32_t isEnabled)
        \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
@@ -710,8 +814,12 @@ static void prvSetRecorderEnabled(uint32_t isEnabled)
 \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
@@ -726,14 +834,14 @@ static void prvSetRecorderEnabled(uint32_t isEnabled)
        }\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
@@ -760,7 +868,7 @@ static void prvTraceStoreSymbolTable()
 }\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
@@ -787,7 +895,7 @@ static void prvTraceStoreObjectDataTable()
 }\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
@@ -807,7 +915,7 @@ static void prvTraceStoreHeader()
                        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
@@ -815,64 +923,17 @@ static void prvTraceStoreHeader()
 }\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
@@ -1035,20 +1096,24 @@ void prvTraceStoreEvent(int nParam, uint16_t eventID, ...)
 /* 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
@@ -1056,8 +1121,6 @@ static void prvTraceStoreStringEventHelper(       int nArgs,
        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
@@ -1140,8 +1203,8 @@ static void prvTraceStoreStringEventHelper(       int nArgs,
 }\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
@@ -1465,6 +1528,16 @@ void prvProcessCommand(TracealyzerCommandType* cmd)
        }\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
@@ -1472,7 +1545,7 @@ void prvTraceError(int errCode)
        {\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
@@ -1550,7 +1623,7 @@ static uint32_t prvGetTimestamp32(void)
        \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
@@ -1563,25 +1636,25 @@ static void prvTraceStoreTSConfig(void)
                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
@@ -1590,11 +1663,11 @@ static int prvAllocateBufferPage(int prevPage)
        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
@@ -1611,11 +1684,11 @@ static void prvPageReadComplete(int pageIndex)
        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
@@ -1625,16 +1698,16 @@ static int prvGetBufferPage(int32_t* bytesUsed)
 {\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
@@ -1645,63 +1718,58 @@ static int prvGetBufferPage(int32_t* bytesUsed)
 }\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
@@ -1709,19 +1777,16 @@ int32_t prvPagedEventBufferTransfer(int32_t (*writeFunc)(void* data, uint32_t si
 }\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
@@ -1767,19 +1832,15 @@ void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)
 }\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
@@ -1789,13 +1850,14 @@ void prvPagedEventBufferInit(char* buffer)
     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