mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-14 16:57:41 -04:00
* Use new version of CI-CD Actions, checkout@v3 instead of checkout@v2 on all jobs * Use cSpell spell check, and use ubuntu-20.04 for formatting check * Add in bot formatting action * Update freertos_demo.yml and freertos_plus_demo.yml files to increase github log readability * Add in a Qemu demo onto the workflows.
354 lines
14 KiB
C
354 lines
14 KiB
C
/*
|
|
* 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 <trcRecorder.h>
|
|
|
|
#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) */
|