/* * Percepio Trace Recorder for Tracealyzer v4.6.0 * Copyright 2021 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 & ( 1 << ( ( errorCode ) - 1 ) ) ) #define SET_ERROR_WARNING_FLAG( errorCode ) ( pxErrorInfo->uiErrorAndWarningFlags |= ( 1 << ( ( errorCode ) - 1 ) ) ) traceResult prvTraceErrorPrint( uint32_t uiErrorCode ); traceResult prvTraceErrorGetDescription( uint32_t uiErrorCode, const char ** pszDesc ); typedef struct TraceErrorInfo { uint32_t uiErrorAndWarningFlags; uint32_t uiErrorCode; TraceStringHandle_t xWarningChannel; } TraceErrorInfo_t; static TraceErrorInfo_t * pxErrorInfo; traceResult xTraceErrorInitialize( TraceErrorBuffer_t * pxBuffer ) { TRC_ASSERT_EQUAL_SIZE( TraceErrorBuffer_t, TraceErrorInfo_t ); /* This should never fail */ TRC_ASSERT( pxBuffer != 0 ); pxErrorInfo = ( TraceErrorInfo_t * ) pxBuffer; pxErrorInfo->uiErrorAndWarningFlags = 0; pxErrorInfo->uiErrorCode = 0; pxErrorInfo->xWarningChannel = 0; xTraceSetComponentInitialized( TRC_RECORDER_COMPONENT_ERROR ); return TRC_SUCCESS; } /* Called on warnings, when the recording can continue. */ traceResult xTraceWarning( uint32_t uiErrorCode ) { /* Probably good to verify this */ if( !xTraceIsComponentInitialized( TRC_RECORDER_COMPONENT_ERROR ) ) { /* If not initialized */ return TRC_FAIL; } if( GET_ERROR_WARNING_FLAG( uiErrorCode ) == 0 ) { /* 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 ); prvTraceErrorPrint( uiErrorCode ); } return TRC_SUCCESS; } /* Called on critical errors in the recorder. Stops the recorder! */ traceResult xTraceError( uint32_t uiErrorCode ) { /* Probably good to verify this */ if( !xTraceIsComponentInitialized( TRC_RECORDER_COMPONENT_ERROR ) ) { 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 ) { xTraceDisable(); return TRC_FAIL; } xTracePrint( pxErrorInfo->xWarningChannel, "Recorder stopped in xTraceError(...)!" ); xTraceDisable(); } return TRC_SUCCESS; } /******************************************************************************* * xTraceErrorGetLast * * Returns the last error or warning, as a string, or NULL if none. *****************************************************************************/ traceResult xTraceErrorGetLast( const char ** pszError ) { /* Probably good to verify this */ if( !xTraceIsComponentInitialized( TRC_RECORDER_COMPONENT_ERROR ) ) { return TRC_FAIL; } /* This should never fail */ TRC_ASSERT( pszError != 0 ); return prvTraceErrorGetDescription( pxErrorInfo->uiErrorCode, pszError ); } /******************************************************************************* * xTraceErrorClear * * Clears any errors. *****************************************************************************/ traceResult xTraceErrorClear( void ) { /* Probably good to verify this */ if( !xTraceIsComponentInitialized( TRC_RECORDER_COMPONENT_ERROR ) ) { /* If not initialized */ return TRC_FAIL; } pxErrorInfo->uiErrorCode = TRC_ERROR_NONE; return TRC_SUCCESS; } /* Returns the error or warning, as a string, or NULL if none. */ traceResult prvTraceErrorPrint( uint32_t uiErrorCode ) { const char * szDesc; /* 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; } } 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: xTracePrint( pxErrorInfo->xWarningChannel, szDesc ); break; case TRC_ERROR_ASSERT: /* A TRC_ASSERT has triggered */ { TraceUnsignedBaseType_t uxLineNumber; TraceStringHandle_t xFileName; if( xTraceAssertGet( &xFileName, &uxLineNumber ) == TRC_FAIL ) { return TRC_FAIL; } xTracePrintF( pxErrorInfo->xWarningChannel, szDesc, xFileName, ( uint32_t ) uxLineNumber ); return TRC_SUCCESS; } default: /* No error, or an unknown error occurred */ xTracePrintF( pxErrorInfo->xWarningChannel, "Unknown error code: 0x%08X", uiErrorCode ); return TRC_FAIL; } return TRC_SUCCESS; } /* Returns the error or warning, as a string, or NULL if none. */ 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; 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 /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */