/* * Percepio Trace Recorder for Tracealyzer v4.8.1 * Copyright 2023 Percepio AB * www.percepio.com * * SPDX-License-Identifier: Apache-2.0 * * The implementation for errors. */ #include #if (TRC_USE_TRACEALYZER_RECORDER == 1) #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) /* We skip the slot for TRC_ERROR_NONE so error code 1 is the first bit */ #define GET_ERROR_WARNING_FLAG(errorCode) (pxErrorInfo->uiErrorAndWarningFlags & (1UL << ((errorCode) - 1UL))) #define SET_ERROR_WARNING_FLAG(errorCode) (pxErrorInfo->uiErrorAndWarningFlags |= (1UL << ((errorCode) - 1UL))) static traceResult prvTraceErrorPrint(uint32_t uiErrorCode); static traceResult prvTraceErrorGetDescription(uint32_t uiErrorCode, const char** pszDesc); static TraceErrorData_t* pxErrorInfo TRC_CFG_RECORDER_DATA_ATTRIBUTE; traceResult xTraceErrorInitialize(TraceErrorData_t* pxBuffer) { /* This should never fail */ TRC_ASSERT(pxBuffer != (void*)0); pxErrorInfo = pxBuffer; pxErrorInfo->uiErrorAndWarningFlags = 0u; pxErrorInfo->uiErrorCode = 0u; pxErrorInfo->xWarningChannel = 0; xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ERROR); return TRC_SUCCESS; } traceResult xTraceWarning(uint32_t uiErrorCode) { /* Probably good to verify this */ if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR) == 0U) { /* If not initialized */ return TRC_FAIL; } if (GET_ERROR_WARNING_FLAG(uiErrorCode) == 0u) { /* Will never reach this point more than once per warning type, since we verify if uiErrorAndWarningFlags[uiErrorCode] has already been set */ SET_ERROR_WARNING_FLAG(uiErrorCode); (void)prvTraceErrorPrint(uiErrorCode); } return TRC_SUCCESS; } traceResult xTraceError(uint32_t uiErrorCode) { /* Probably good to verify this */ if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR) == 0U) { return TRC_FAIL; } if (pxErrorInfo->uiErrorCode == TRC_ERROR_NONE) { /* Will never reach this point more than once, since we verify if uiErrorCode has already been set */ SET_ERROR_WARNING_FLAG(uiErrorCode); pxErrorInfo->uiErrorCode = uiErrorCode; if (prvTraceErrorPrint(uiErrorCode) == TRC_FAIL) { (void)xTraceDisable(); return TRC_FAIL; } (void)xTracePrint(pxErrorInfo->xWarningChannel, "Recorder stopped in xTraceError(...)!"); (void)xTraceDisable(); } return TRC_SUCCESS; } /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ traceResult xTraceErrorGetLast(const char **pszError) { /* Probably good to verify this */ if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR) == 0U) { return TRC_FAIL; } /* This should never fail */ TRC_ASSERT(pszError != (void*)0); return prvTraceErrorGetDescription(pxErrorInfo->uiErrorCode, pszError); } traceResult xTraceErrorClear(void) { /* Probably good to verify this */ if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR) == 0U) { /* If not initialized */ return TRC_FAIL; } pxErrorInfo->uiErrorCode = TRC_ERROR_NONE; return TRC_SUCCESS; } static traceResult prvTraceErrorPrint(uint32_t uiErrorCode) { const char* szDesc; /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ TraceUnsignedBaseType_t uxLineNumber; TraceStringHandle_t xFileName; /* Note: the error messages are short, in order to fit in a User Event. Instead, the users can read more in the below comments.*/ if (pxErrorInfo->xWarningChannel == 0) { /* The #WFR channel means "Warnings from Recorder" and * is used to store warnings and errors from the recorder. * The abbreviation #WFR is used instead of the longer full name, * to avoid truncation by small slots in the symbol table. * This is translated in Tracealyzer and shown as the full name, * "Warnings from Recorder". */ if (xTraceStringRegister("#WFR", &pxErrorInfo->xWarningChannel) == TRC_FAIL) { return TRC_FAIL; } } (void)prvTraceErrorGetDescription(uiErrorCode, &szDesc); switch (uiErrorCode) { case TRC_WARNING_ENTRY_TABLE_SLOTS: case TRC_WARNING_ENTRY_SYMBOL_MAX_LENGTH: case TRC_WARNING_EVENT_SIZE_TRUNCATED: case TRC_WARNING_STREAM_PORT_READ: case TRC_WARNING_STREAM_PORT_WRITE: case TRC_WARNING_STREAM_PORT_INITIAL_BLOCKING: case TRC_WARNING_STACKMON_NO_SLOTS: case TRC_ERROR_STREAM_PORT_WRITE: case TRC_ERROR_EVENT_CODE_TOO_LARGE: case TRC_ERROR_ISR_NESTING_OVERFLOW: case TRC_ERROR_DWT_NOT_SUPPORTED: case TRC_ERROR_DWT_CYCCNT_NOT_SUPPORTED: case TRC_ERROR_TZCTRLTASK_NOT_CREATED: (void)xTracePrint(pxErrorInfo->xWarningChannel, szDesc); break; case TRC_ERROR_ASSERT: /* A TRC_ASSERT has triggered */ if (xTraceAssertGet(&xFileName, &uxLineNumber) == TRC_FAIL) { return TRC_FAIL; } (void)xTracePrintF(pxErrorInfo->xWarningChannel, szDesc, xFileName, (uint32_t)uxLineNumber); return TRC_SUCCESS; break; default: /* No error, or an unknown error occurred */ (void)xTracePrintF(pxErrorInfo->xWarningChannel, "Unknown error code: 0x%08X", uiErrorCode); return TRC_FAIL; break; } return TRC_SUCCESS; } /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ static traceResult prvTraceErrorGetDescription(uint32_t uiErrorCode, const char** pszDesc) { /* Note: the error messages are short, in order to fit in a User Event. Instead, the users can read more in the below comments.*/ switch (uiErrorCode) { case TRC_ERROR_NONE: return TRC_FAIL; break; case TRC_WARNING_ENTRY_TABLE_SLOTS: /* There was not enough symbol table slots for storing symbol names. The number of missing slots is counted by NoRoomForSymbol. Inspect this variable and increase TRC_CFG_ENTRY_TABLE_SLOTS by at least that value. */ *pszDesc = "Exceeded TRC_CFG_ENTRY_TABLE_SLOTS"; break; case TRC_WARNING_ENTRY_SYMBOL_MAX_LENGTH: /* A symbol name exceeded TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH in length. Make sure the symbol names are at most TRC_CFG_SYMBOL_MAX_LENGTH, or inspect uiLongestSymbolName in trcEntryTable and increase TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH to at least this value. */ *pszDesc = "Exceeded TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH"; break; case TRC_WARNING_EVENT_SIZE_TRUNCATED: /* Some arguments was longer than the maximum payload size and has been truncated by "uiMaxBytesTruncated" bytes. This usually happens for the following functions: - xTracePrint - xTracePrintF - xTraceStringRegister A trace event may store a maximum of 56 bytes payload, including data arguments and string characters. */ *pszDesc = "Event size exceeded"; break; case TRC_WARNING_STREAM_PORT_READ: /* TRC_STREAM_PORT_READ_DATA is expected to return 0 when completed successfully. This means there is an error in the communication with host/Tracealyzer. */ *pszDesc = "TRC_STREAM_PORT_READ_DATA returned error"; break; case TRC_WARNING_STREAM_PORT_WRITE: /* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully. This means there is an error in the communication with host/Tracealyzer. */ *pszDesc = "TRC_STREAM_PORT_WRITE_DATA returned error"; break; case TRC_WARNING_STREAM_PORT_INITIAL_BLOCKING: /* Blocking occurred during xTraceEnable. This happens if the trace buffer is smaller than the initial transmission (trace header, object table, and symbol table). */ *pszDesc = "Blocking in xTraceEnable"; break; case TRC_WARNING_STACKMON_NO_SLOTS: /* Some tasks did not fit in the stack monitor. Increase the slot count. */ *pszDesc = "No slots left in Stack Monitor"; break; case TRC_ERROR_STREAM_PORT_WRITE: /* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully. This means there is an error in the communication with host/Tracealyzer. */ *pszDesc = "TRC_STREAM_PORT_WRITE_DATA returned error"; break; case TRC_ERROR_EVENT_CODE_TOO_LARGE: /* The highest allowed event code is 4095, anything higher is an unexpected error. Please contact support@percepio.com for assistance.*/ *pszDesc = "Invalid event code"; break; case TRC_ERROR_ISR_NESTING_OVERFLOW: /* Nesting of ISR trace calls exceeded the limit (TRC_CFG_MAX_ISR_NESTING). If this is unlikely, make sure that you call vTraceStoreISRExit in the end of all ISR handlers. Or increase TRC_CFG_MAX_ISR_NESTING. */ *pszDesc = "Exceeded ISR nesting"; break; case TRC_ERROR_DWT_NOT_SUPPORTED: /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip. DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M macro normally set by ARM's CMSIS library, since typically available. You can however select SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/ *pszDesc = "DWT not supported"; break; case TRC_ERROR_DWT_CYCCNT_NOT_SUPPORTED: /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip. DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M macro normally set by ARM's CMSIS library, since typically available. You can however select SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/ *pszDesc = "DWT_CYCCNT not supported"; break; case TRC_ERROR_TZCTRLTASK_NOT_CREATED: /* xTraceEnable failed creating the trace control task (TzCtrl) - incorrect parameters (priority?) or insufficient heap size? */ *pszDesc = "Could not create TzCtrl"; break; case TRC_ERROR_ASSERT: /* A TRC_ASSERT has triggered */ *pszDesc = "ASSERT: %s (%d)"; break; default: /* An unknown error occurred */ *pszDesc = "Unknown error code: 0x%08X"; break; } return TRC_SUCCESS; } #endif #endif