mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-15 09:17:44 -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.
610 lines
21 KiB
C
610 lines
21 KiB
C
/*
|
|
* Trace Recorder for Tracealyzer v4.6.0
|
|
* Copyright 2021 Percepio AB
|
|
* www.percepio.com
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* The generic core of the trace recorder's streaming mode.
|
|
*/
|
|
|
|
#include <trcRecorder.h>
|
|
|
|
#if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING )
|
|
|
|
#if ( TRC_USE_TRACEALYZER_RECORDER == 1 )
|
|
|
|
typedef struct TraceHeader
|
|
{
|
|
uint32_t uiPSF;
|
|
uint16_t uiVersion;
|
|
uint16_t uiPlatform;
|
|
uint32_t uiOptions;
|
|
uint32_t uiNumCores;
|
|
uint32_t isrTailchainingThreshold;
|
|
char platformCfg[ 8 ];
|
|
uint16_t uiPlatformCfgPatch;
|
|
uint8_t uiPlatformCfgMinor;
|
|
uint8_t uiPlatformCfgMajor;
|
|
} TraceHeader_t;
|
|
|
|
/* The data structure for commands (a bit overkill) */
|
|
typedef struct TraceCommandType_t
|
|
{
|
|
unsigned char cmdCode;
|
|
unsigned char param1;
|
|
unsigned char param2;
|
|
unsigned char param3;
|
|
unsigned char param4;
|
|
unsigned char param5;
|
|
unsigned char checksumLSB;
|
|
unsigned char checksumMSB;
|
|
} TraceCommand_t;
|
|
|
|
#ifndef TRC_CFG_RECORDER_DATA_INIT
|
|
#define TRC_CFG_RECORDER_DATA_INIT 1
|
|
#endif
|
|
|
|
/* Used to interpret the data format */
|
|
#define TRACE_FORMAT_VERSION ( ( uint16_t ) 0x000A )
|
|
|
|
/* Used to determine endian of data (big/little) */
|
|
#define TRACE_PSF_ENDIANESS_IDENTIFIER ( ( uint32_t ) 0x50534600 )
|
|
|
|
#if ( TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC )
|
|
static TraceRecorderData_t xRecorderData TRC_CFG_RECORDER_DATA_ATTRIBUTE;
|
|
TraceRecorderData_t * pxTraceRecorderData = &xRecorderData;
|
|
#else
|
|
/* If using DYNAMIC or CUSTOM allocation */
|
|
TraceRecorderData_t * pxTraceRecorderData TRC_CFG_RECORDER_DATA_ATTRIBUTE;
|
|
#endif
|
|
|
|
static TraceHeader_t * pxHeader;
|
|
|
|
/*******************************************************************************
|
|
* RecorderInitialized
|
|
*
|
|
* Makes sure the recorder data is only initialized once.
|
|
*
|
|
* NOTE: RecorderInitialized is only initialized to 0 if
|
|
* TRC_CFG_RECORDER_DATA_INIT is non-zero.
|
|
* This will avoid issues where the recorder must be started before main(),
|
|
* which can lead to RecorderInitialized be cleared by late initialization after
|
|
* xTraceEnable(TRC_INIT) was called and assigned RecorderInitialized its'
|
|
* value.
|
|
******************************************************************************/
|
|
#if ( TRC_CFG_RECORDER_DATA_INIT != 0 )
|
|
uint32_t RecorderInitialized = 0;
|
|
#else /* (TRC_CFG_RECORDER_DATA_INIT != 0) */
|
|
uint32_t RecorderInitialized TRC_CFG_RECORDER_DATA_ATTRIBUTE;
|
|
#endif /* (TRC_CFG_RECORDER_DATA_INIT != 0) */
|
|
|
|
#if ( TRC_EXTERNAL_BUFFERS == 0 )
|
|
/* Stores the header information on Start */
|
|
static void prvTraceStoreHeader( void );
|
|
|
|
/* Store the Timestamp info */
|
|
static void prvTraceStoreTimestampInfo( void );
|
|
|
|
/* Stores the entry table on Start */
|
|
static void prvTraceStoreEntryTable( void );
|
|
|
|
#else /* (TRC_EXTERNAL_BUFFERS == 0) */
|
|
|
|
#define prvTraceStoreHeader()
|
|
#define prvTraceStoreTimestampInfo()
|
|
#define prvTraceStoreEntryTable()
|
|
|
|
#endif /* (TRC_EXTERNAL_BUFFERS == 0) */
|
|
|
|
/* Store start event. */
|
|
static void prvTraceStoreStartEvent( void );
|
|
|
|
/* Checks if the provided command is a valid command */
|
|
static int prvIsValidCommand( TraceCommand_t * cmd );
|
|
|
|
/* Executed the received command (Start or Stop) */
|
|
static void prvProcessCommand( TraceCommand_t * cmd );
|
|
|
|
/* Internal function for starting the recorder */
|
|
static void prvSetRecorderEnabled( void );
|
|
|
|
/* Internal function for stopping the recorder */
|
|
static void prvSetRecorderDisabled( void );
|
|
|
|
/******************************************************************************
|
|
* xTraceInitialize
|
|
*
|
|
* Initializes the recorder data.
|
|
* This function will be called by xTraceEnable(...).
|
|
* Only needs to be called manually if traced objects are created before the
|
|
* trace recorder can be enabled, at which point make sure to call this function
|
|
* as early as possible.
|
|
* See TRC_CFG_RECORDER_DATA_INIT in trcConfig.h.
|
|
******************************************************************************/
|
|
traceResult xTraceInitialize( void )
|
|
{
|
|
TRC_ASSERT_EQUAL_SIZE( TraceRecorderDataBuffer_t, TraceRecorderData_t );
|
|
|
|
if( RecorderInitialized != 0 )
|
|
{
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
#if ( TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC )
|
|
pxRecorderData = TRC_MALLOC( sizeof( TraceRecorderData_t ) );
|
|
#endif
|
|
|
|
/* These are set on init so they aren't overwritten by late initialization values. */
|
|
pxTraceRecorderData->uiSessionCounter = 0;
|
|
pxTraceRecorderData->uiRecorderEnabled = 0;
|
|
pxTraceRecorderData->uiTraceSystemState = TRC_STATE_IN_STARTUP;
|
|
|
|
#if ( TRC_EXTERNAL_BUFFERS == 0 )
|
|
if( xTraceHeaderInitialize( &pxTraceRecorderData->xHeaderBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceEntryTableInitialize( &pxTraceRecorderData->xEntryTableBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceTimestampInitialize( &pxTraceRecorderData->xTimestampBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
#endif /* if ( TRC_EXTERNAL_BUFFERS == 0 ) */
|
|
|
|
if( xTraceStackMonitorInitialize( &pxTraceRecorderData->xStackMonitorBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceStreamPortInitialize( &pxTraceRecorderData->xStreamPortBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceAssertInitialize( &pxTraceRecorderData->xAssertBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceDiagnosticsInitialize( &pxTraceRecorderData->xDiagnosticsBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceStaticBufferInitialize( &pxTraceRecorderData->xStaticBufferBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceEventInitialize( &pxTraceRecorderData->xEventDataBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTracePrintInitialize( &pxTraceRecorderData->xPrintBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceErrorInitialize( &pxTraceRecorderData->xErrorBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceISRInitialize( &pxTraceRecorderData->xISRInfoBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceTaskInitialize( &pxTraceRecorderData->xTaskInfoBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( xTraceKernelPortInitialize( &pxTraceRecorderData->xKernelPortBuffer ) == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
xTraceSetComponentInitialized( TRC_RECORDER_COMPONENT_CORE );
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceHeaderInitialize( TraceHeaderBuffer_t * pxBuffer )
|
|
{
|
|
uint32_t i;
|
|
char * platform_cfg = TRC_PLATFORM_CFG;
|
|
|
|
TRC_ASSERT_EQUAL_SIZE( TraceHeaderBuffer_t, TraceHeader_t );
|
|
|
|
if( pxBuffer == 0 )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
pxHeader = ( TraceHeader_t * ) pxBuffer;
|
|
|
|
pxHeader->uiPSF = TRACE_PSF_ENDIANESS_IDENTIFIER;
|
|
pxHeader->uiVersion = TRACE_FORMAT_VERSION;
|
|
pxHeader->uiPlatform = TRACE_KERNEL_VERSION;
|
|
|
|
for( i = 0; i < TRC_PLATFORM_CFG_LENGTH; i++ )
|
|
{
|
|
pxHeader->platformCfg[ i ] = platform_cfg[ i ];
|
|
|
|
if( platform_cfg[ i ] == 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
pxHeader->uiPlatformCfgPatch = TRC_PLATFORM_CFG_PATCH;
|
|
pxHeader->uiPlatformCfgMinor = TRC_PLATFORM_CFG_MINOR;
|
|
pxHeader->uiPlatformCfgMajor = TRC_PLATFORM_CFG_MAJOR;
|
|
pxHeader->uiNumCores = TRC_CFG_CORE_COUNT;
|
|
pxHeader->isrTailchainingThreshold = TRC_CFG_ISR_TAILCHAINING_THRESHOLD;
|
|
|
|
/* Lowest bit used for TRC_IRQ_PRIORITY_ORDER */
|
|
pxHeader->uiOptions = ( ( TRC_IRQ_PRIORITY_ORDER ) << 0 );
|
|
|
|
/* 3rd bit used for TRC_CFG_TEST_MODE */
|
|
pxHeader->uiOptions |= ( ( TRC_CFG_TEST_MODE ) << 2 );
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceEnable( uint32_t uiStartOption )
|
|
{
|
|
TraceCommand_t xCommand;
|
|
int32_t iBytes = 0;
|
|
|
|
if( xTraceInitialize() == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
xTraceStreamPortOnEnable( uiStartOption );
|
|
|
|
if( xTraceKernelPortEnable() == TRC_FAIL )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( uiStartOption == TRC_START_AWAIT_HOST )
|
|
{
|
|
/* We keep trying to read commands from host until the recorder has been started */
|
|
do
|
|
{
|
|
iBytes = 0;
|
|
|
|
if( xTraceStreamPortReadData( &xCommand, sizeof( TraceCommand_t ), ( int32_t * ) &iBytes ) == TRC_FAIL )
|
|
{
|
|
xTraceWarning( TRC_WARNING_STREAM_PORT_READ );
|
|
}
|
|
|
|
if( iBytes == sizeof( TraceCommand_t ) )
|
|
{
|
|
if( prvIsValidCommand( &xCommand ) )
|
|
{
|
|
if( ( xCommand.cmdCode == CMD_SET_ACTIVE ) && ( xCommand.param1 == 1 ) )
|
|
{
|
|
/* On start, init and reset the timestamping */
|
|
TRC_PORT_SPECIFIC_INIT();
|
|
}
|
|
|
|
prvProcessCommand( &xCommand );
|
|
}
|
|
}
|
|
} while( pxTraceRecorderData->uiRecorderEnabled == 0 );
|
|
}
|
|
else if( uiStartOption == TRC_START )
|
|
{
|
|
/* We start streaming directly - this assumes that the host interface is ready! */
|
|
TRC_PORT_SPECIFIC_INIT();
|
|
|
|
xCommand.cmdCode = CMD_SET_ACTIVE;
|
|
xCommand.param1 = 1;
|
|
prvProcessCommand( &xCommand );
|
|
}
|
|
else if( uiStartOption == TRC_START_FROM_HOST )
|
|
{
|
|
/* We prepare the system to receive commands from host, but let system resume execution until that happens */
|
|
TRC_PORT_SPECIFIC_INIT();
|
|
}
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceDisable( void )
|
|
{
|
|
prvSetRecorderDisabled();
|
|
|
|
xTraceStreamPortOnDisable();
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
#if ( TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM )
|
|
traceResult xTraceSetBuffer( TraceRecorderDataBuffer_t * pxBuffer )
|
|
{
|
|
if( pxBuffer == 0 )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
pxTraceRecorderData = ( TraceRecorderData_t * ) pxBuffer;
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
#endif /* if ( TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM ) */
|
|
|
|
traceResult xTraceGetEventBuffer( void ** ppvBuffer,
|
|
TraceUnsignedBaseType_t * puiSize )
|
|
{
|
|
if( ( pxTraceRecorderData == 0 ) || ( ppvBuffer == 0 ) || ( puiSize == 0 ) )
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
/* Returns the xStreamPortBuffer since that is the one containing trace data */
|
|
*ppvBuffer = ( void * ) &pxTraceRecorderData->xStreamPortBuffer;
|
|
*puiSize = sizeof( pxTraceRecorderData->xStreamPortBuffer );
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceTzCtrl( void )
|
|
{
|
|
TraceCommand_t xCommand;
|
|
int32_t iBytes = 0;
|
|
|
|
do
|
|
{
|
|
/* Listen for new commands */
|
|
iBytes = 0;
|
|
|
|
if( xTraceStreamPortReadData( &xCommand, sizeof( TraceCommand_t ), &iBytes ) == TRC_FAIL )
|
|
{
|
|
/* The connection has failed, stop tracing */
|
|
xTraceDisable();
|
|
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
if( iBytes == sizeof( TraceCommand_t ) )
|
|
{
|
|
if( prvIsValidCommand( &xCommand ) )
|
|
{
|
|
prvProcessCommand( &xCommand ); /* Start or Stop currently... */
|
|
}
|
|
}
|
|
|
|
#if ( TRC_USE_INTERNAL_BUFFER == 1 )
|
|
xTraceInternalEventBufferTransfer( &iBytes );
|
|
#endif
|
|
|
|
/* If there was data sent or received (bytes != 0), loop around and repeat, if there is more data to send or receive.
|
|
* Otherwise, step out of this loop and sleep for a while. */
|
|
} while( iBytes != 0 );
|
|
|
|
if( xTraceIsRecorderEnabled() )
|
|
{
|
|
xTraceDiagnosticsCheckStatus();
|
|
xTraceStackMonitorReport();
|
|
}
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
void vTraceSetFilterGroup( uint16_t filterGroup )
|
|
{
|
|
( void ) filterGroup;
|
|
}
|
|
|
|
void vTraceSetFilterMask( uint16_t filterMask )
|
|
{
|
|
( void ) filterMask;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*** INTERNAL FUNCTIONS *******************************************************/
|
|
/******************************************************************************/
|
|
/* Internal function for starting/stopping the recorder. */
|
|
static void prvSetRecorderEnabled( void )
|
|
{
|
|
uint32_t timestampFrequency = 0;
|
|
|
|
TRACE_ALLOC_CRITICAL_SECTION();
|
|
|
|
if( pxTraceRecorderData->uiRecorderEnabled == 1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
xTraceTimestampGetFrequency( ×tampFrequency );
|
|
|
|
/* If not overridden using xTraceTimestampSetFrequency(...), use default value */
|
|
if( timestampFrequency == 0 )
|
|
{
|
|
timestampFrequency = TRC_HWTC_FREQ_HZ;
|
|
xTraceTimestampSetFrequency( timestampFrequency );
|
|
}
|
|
|
|
TRACE_ENTER_CRITICAL_SECTION();
|
|
|
|
/* If the internal event buffer is used, we must clear it */
|
|
xTraceInternalEventBufferClear();
|
|
|
|
xTraceStreamPortOnTraceBegin();
|
|
|
|
prvTraceStoreHeader();
|
|
prvTraceStoreTimestampInfo();
|
|
prvTraceStoreEntryTable();
|
|
prvTraceStoreStartEvent();
|
|
|
|
pxTraceRecorderData->uiSessionCounter++;
|
|
|
|
pxTraceRecorderData->uiRecorderEnabled = 1;
|
|
|
|
TRACE_EXIT_CRITICAL_SECTION();
|
|
}
|
|
|
|
static void prvSetRecorderDisabled( void )
|
|
{
|
|
TRACE_ALLOC_CRITICAL_SECTION();
|
|
|
|
if( pxTraceRecorderData->uiRecorderEnabled == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
TRACE_ENTER_CRITICAL_SECTION();
|
|
|
|
pxTraceRecorderData->uiRecorderEnabled = 0;
|
|
|
|
xTraceStreamPortOnTraceEnd();
|
|
|
|
TRACE_EXIT_CRITICAL_SECTION();
|
|
}
|
|
|
|
#if ( TRC_EXTERNAL_BUFFERS == 0 )
|
|
/* Stores the header information on Start */
|
|
static void prvTraceStoreHeader( void )
|
|
{
|
|
TraceEventHandle_t xEventHandle;
|
|
|
|
if( xTraceEventBeginRawOfflineBlocking( sizeof( TraceHeader_t ), &xEventHandle ) == TRC_SUCCESS )
|
|
{
|
|
xTraceEventAddData( xEventHandle, pxHeader, sizeof( TraceHeader_t ) );
|
|
xTraceEventEndOfflineBlocking( xEventHandle );
|
|
}
|
|
}
|
|
|
|
/* Store the Timestamp */
|
|
static void prvTraceStoreTimestampInfo( void )
|
|
{
|
|
TraceEventHandle_t xEventHandle;
|
|
uint32_t timestampFrequency = 0;
|
|
|
|
xTraceTimestampGetFrequency( ×tampFrequency );
|
|
|
|
if( xTraceEventBeginRawOfflineBlocking( sizeof( TraceTimestampBuffer_t ), &xEventHandle ) == TRC_SUCCESS )
|
|
{
|
|
xTraceEventAddData( xEventHandle, &pxTraceRecorderData->xTimestampBuffer, sizeof( TraceTimestampBuffer_t ) );
|
|
xTraceEventEndOfflineBlocking( xEventHandle );
|
|
}
|
|
}
|
|
|
|
/* Stores the entry table on Start */
|
|
static void prvTraceStoreEntryTable( void )
|
|
{
|
|
uint32_t i = 0;
|
|
TraceEventHandle_t xEventHandle;
|
|
TraceEntryHandle_t xEntryHandle;
|
|
uint32_t uiEntryCount;
|
|
void * pvEntryAddress;
|
|
|
|
xTraceEntryGetCount( &uiEntryCount );
|
|
|
|
if( xTraceEventBeginRawOfflineBlocking( sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint32_t ), &xEventHandle ) == TRC_SUCCESS )
|
|
{
|
|
xTraceEventAdd32( xEventHandle, uiEntryCount );
|
|
xTraceEventAdd32( xEventHandle, TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE );
|
|
xTraceEventAdd32( xEventHandle, TRC_ENTRY_TABLE_STATE_COUNT );
|
|
xTraceEventEndOfflineBlocking( xEventHandle );
|
|
}
|
|
|
|
for( i = 0; i < ( TRC_ENTRY_TABLE_SLOTS ); i++ )
|
|
{
|
|
xTraceEntryGetAtIndex( i, &xEntryHandle );
|
|
xTraceEntryGetAddress( xEntryHandle, &pvEntryAddress );
|
|
|
|
/* We only send used entry slots */
|
|
if( pvEntryAddress != 0 )
|
|
{
|
|
/* Send entry */
|
|
if( xTraceEventBeginRawOfflineBlocking( sizeof( TraceEntry_t ), &xEventHandle ) == TRC_SUCCESS )
|
|
{
|
|
xTraceEventAddData( xEventHandle, ( void * ) xEntryHandle, sizeof( TraceEntry_t ) );
|
|
xTraceEventEndOfflineBlocking( xEventHandle );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* (TRC_EXTERNAL_BUFFERS == 0) */
|
|
|
|
static void prvTraceStoreStartEvent()
|
|
{
|
|
TraceEventHandle_t xEventHandle;
|
|
void * pvCurrentTask;
|
|
|
|
xTraceTaskGetCurrent( &pvCurrentTask );
|
|
|
|
if( xTraceEventBeginOffline( PSF_EVENT_TRACE_START, sizeof( uint32_t ), &xEventHandle ) == TRC_SUCCESS )
|
|
{
|
|
xTraceEventAdd32( xEventHandle, ( uint32_t ) pvCurrentTask );
|
|
xTraceEventEndOffline( xEventHandle );
|
|
}
|
|
}
|
|
|
|
/* Checks if the provided command is a valid command */
|
|
static int prvIsValidCommand( TraceCommand_t * cmd )
|
|
{
|
|
uint16_t checksum = ( uint16_t ) ( 0xFFFF - ( cmd->cmdCode +
|
|
cmd->param1 +
|
|
cmd->param2 +
|
|
cmd->param3 +
|
|
cmd->param4 +
|
|
cmd->param5 ) );
|
|
|
|
if( cmd->checksumMSB != ( unsigned char ) ( checksum >> 8 ) )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if( cmd->checksumLSB != ( unsigned char ) ( checksum & 0xFF ) )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if( cmd->cmdCode > CMD_LAST_COMMAND )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* Executed the received command (Start or Stop) */
|
|
static void prvProcessCommand( TraceCommand_t * cmd )
|
|
{
|
|
switch( cmd->cmdCode )
|
|
{
|
|
case CMD_SET_ACTIVE:
|
|
|
|
if( cmd->param1 == 1 )
|
|
{
|
|
prvSetRecorderEnabled();
|
|
}
|
|
else
|
|
{
|
|
prvSetRecorderDisabled();
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
|
|
|
|
#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
|