FreeRTOS-Kernel/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEventBuffer.c
Soren Ptak 3a2f6646f0
Use CI-CD-Github-Actions for spelling and formatting, add in the bot formatting action, update the CI-CD workflow files. Fix incorrect spelling and formatting on files. (#1083)
* 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.
2023-09-06 12:35:37 -07:00

260 lines
9.6 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 the event buffer.
*/
#include <trcRecorder.h>
#if ( TRC_USE_TRACEALYZER_RECORDER == 1 )
#if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING )
traceResult xTraceEventBufferInitialize( TraceEventBuffer_t * pxTraceEventBuffer,
uint32_t uiOptions,
uint8_t * puiBuffer,
uint32_t uiSize )
{
/* This should never fail */
TRC_ASSERT( pxTraceEventBuffer != 0 );
/* This should never fail */
TRC_ASSERT( puiBuffer != 0 );
pxTraceEventBuffer->uiOptions = uiOptions;
pxTraceEventBuffer->uiHead = 0;
pxTraceEventBuffer->uiTail = 0;
pxTraceEventBuffer->uiSize = uiSize;
pxTraceEventBuffer->uiFree = uiSize;
pxTraceEventBuffer->puiBuffer = puiBuffer;
pxTraceEventBuffer->uiTimerWraparounds = 0;
xTraceSetComponentInitialized( TRC_RECORDER_COMPONENT_EVENT_BUFFER );
return TRC_SUCCESS;
}
/**
* @brief Pops the oldest event from the Event Buffer.
*
* @param[in] pxTraceEventBuffer Pointer to initialized trace event buffer.
*
* @retval TRC_FAIL Failure
* @retval TRC_SUCCESS Success
*/
static traceResult prvTraceEventBufferPop( TraceEventBuffer_t * pxTraceEventBuffer )
{
uint32_t uiFreeSize = 0;
/* Get size of event we are freeing */
/* This should never fail */
TRC_ASSERT_ALWAYS_EVALUATE( xTraceEventGetSize( ( ( void * ) &( pxTraceEventBuffer->puiBuffer[ pxTraceEventBuffer->uiTail ] ) ), &uiFreeSize ) == TRC_SUCCESS );
pxTraceEventBuffer->uiFree += uiFreeSize;
/* Update tail to point to the new last event */
pxTraceEventBuffer->uiTail = ( pxTraceEventBuffer->uiTail + uiFreeSize ) % pxTraceEventBuffer->uiSize;
return TRC_SUCCESS;
}
traceResult xTraceEventBufferPush( TraceEventBuffer_t * pxTraceEventBuffer,
void * pxData,
uint32_t uiDataSize,
int32_t * piBytesWritten )
{
uint32_t uiBufferSize;
/* This should never fail */
TRC_ASSERT( pxTraceEventBuffer != 0 );
/* This should never fail */
TRC_ASSERT( pxData != 0 );
uiBufferSize = pxTraceEventBuffer->uiSize;
/* Check if the data size is larger than the buffer */
/* This should never fail */
TRC_ASSERT( uiDataSize <= uiBufferSize );
/* Check byte alignment */
/* This should never fail */
TRC_ASSERT( ( uiDataSize % 4 ) == 0 );
/* Ensure bytes written start at 0 */
/* This should never fail */
TRC_ASSERT( piBytesWritten != 0 );
*piBytesWritten = 0;
/* This should never fail */
TRC_ASSERT_ALWAYS_EVALUATE( xTraceTimestampGetWraparounds( &pxTraceEventBuffer->uiTimerWraparounds ) == TRC_SUCCESS );
/* In ring buffer mode we cannot provide lock free access since the producer modified
* the head and tail variables in the same call. This option is only safe when used
* with an internal buffer (streaming snapshot) which no consumer accesses.
*/
switch( pxTraceEventBuffer->uiOptions )
{
case TRC_EVENT_BUFFER_OPTION_OVERWRITE:
{
uint32_t uiHead = pxTraceEventBuffer->uiHead;
/* If there isn't enough space in the buffer pop events until there is */
while( pxTraceEventBuffer->uiFree < uiDataSize )
{
prvTraceEventBufferPop( pxTraceEventBuffer );
}
/* Copy data */
if( ( uiBufferSize - uiHead ) > uiDataSize )
{
TRC_MEMCPY( &pxTraceEventBuffer->puiBuffer[ uiHead ], pxData, uiDataSize );
}
else
{
TRC_MEMCPY( &pxTraceEventBuffer->puiBuffer[ uiHead ], pxData, uiBufferSize - uiHead );
TRC_MEMCPY( pxTraceEventBuffer->puiBuffer,
( void * ) ( &( ( uint8_t * ) pxData )[ ( uiBufferSize - uiHead ) ] ),
uiDataSize - ( uiBufferSize - uiHead ) );
}
pxTraceEventBuffer->uiFree -= uiDataSize;
pxTraceEventBuffer->uiHead = ( uiHead + uiDataSize ) % uiBufferSize;
*piBytesWritten = uiDataSize;
break;
}
case TRC_EVENT_BUFFER_OPTION_SKIP:
{
/* Since a consumer could potentially update tail (free) during the procedure
* we have to save it here to avoid problems with the push algorithm.
*/
uint32_t uiHead = pxTraceEventBuffer->uiHead;
uint32_t uiTail = pxTraceEventBuffer->uiTail;
if( uiHead >= uiTail )
{
uint32_t uiFreeSpace = ( uiBufferSize - uiHead - sizeof( uint32_t ) ) + uiTail;
if( uiFreeSpace < uiDataSize )
{
*piBytesWritten = 0;
return TRC_SUCCESS;
}
/* Copy data */
if( ( uiBufferSize - uiHead ) > uiDataSize )
{
TRC_MEMCPY( &pxTraceEventBuffer->puiBuffer[ pxTraceEventBuffer->uiHead ], pxData, uiDataSize );
}
else
{
TRC_MEMCPY( &pxTraceEventBuffer->puiBuffer[ uiHead ], pxData, uiBufferSize - uiHead );
TRC_MEMCPY( pxTraceEventBuffer->puiBuffer,
( void * ) ( &( ( uint8_t * ) pxData )[ ( uiBufferSize - uiHead ) ] ),
uiDataSize - ( uiBufferSize - uiHead ) );
}
pxTraceEventBuffer->uiHead = ( uiHead + uiDataSize ) % uiBufferSize;
}
else
{
uint32_t uiFreeSpace = uiTail - uiHead - sizeof( uint32_t );
if( uiFreeSpace < uiDataSize )
{
*piBytesWritten = 0;
return TRC_SUCCESS;
}
/* Copy data */
TRC_MEMCPY( &pxTraceEventBuffer->puiBuffer[ pxTraceEventBuffer->uiHead ], pxData, uiDataSize );
pxTraceEventBuffer->uiHead = ( uiHead + uiDataSize );
}
*piBytesWritten = uiDataSize;
break;
}
default:
return TRC_FAIL;
}
return TRC_SUCCESS;
}
traceResult xTraceEventBufferTransfer( TraceEventBuffer_t * pxTraceEventBuffer,
int32_t * piBytesWritten )
{
int32_t iBytesWritten = 0;
int32_t iSumBytesWritten = 0;
uint32_t uiHead;
uint32_t uiTail;
/* This should never fail */
TRC_ASSERT( pxTraceEventBuffer != 0 );
/* This should never fail */
TRC_ASSERT( piBytesWritten != 0 );
uiHead = pxTraceEventBuffer->uiHead;
uiTail = pxTraceEventBuffer->uiTail;
/* Check if core event buffer is empty */
if( uiHead == uiTail )
{
return TRC_SUCCESS;
}
/* Check if we can do a direct write or if we have to handle wrapping */
if( uiHead > uiTail )
{
xTraceStreamPortWriteData( &pxTraceEventBuffer->puiBuffer[ uiTail ], ( uiHead - uiTail ), &iBytesWritten );
pxTraceEventBuffer->uiTail = uiHead;
}
else
{
xTraceStreamPortWriteData( &pxTraceEventBuffer->puiBuffer[ uiTail ], ( pxTraceEventBuffer->uiSize - uiTail ), &iBytesWritten );
iSumBytesWritten += iBytesWritten;
xTraceStreamPortWriteData( pxTraceEventBuffer->puiBuffer, uiHead, &iBytesWritten );
pxTraceEventBuffer->uiTail = uiHead;
}
iSumBytesWritten += iBytesWritten;
*piBytesWritten = iSumBytesWritten;
return TRC_SUCCESS;
}
traceResult xTraceEventBufferClear( TraceEventBuffer_t * pxTraceEventBuffer )
{
/* This should never fail */
TRC_ASSERT( pxTraceEventBuffer != 0 );
pxTraceEventBuffer->uiHead = 0;
pxTraceEventBuffer->uiTail = 0;
pxTraceEventBuffer->uiFree = pxTraceEventBuffer->uiSize;
return TRC_SUCCESS;
}
#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */