mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-08-06 18:24:41 +08:00

* * Percepio Trace Recorder v4.6.0 * Add space between inclusion of header and comment * Fix broken posix build - part 1 * Add percepio timer implementation * Remove delted trace recorder header file * Fix Networking demo build * Fix CLI demo * Fix visual studio version number * Fix core header check * Fix more core checks * Fix last of core checks Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Alfred Gedeon <alfred2g@hotmail.com>
430 lines
11 KiB
C
430 lines
11 KiB
C
/*
|
|
* Trace Recorder for Tracealyzer v4.6.0
|
|
* Copyright 2021 Percepio AB
|
|
* www.percepio.com
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* The implementation of the entry table.
|
|
*/
|
|
|
|
#include <trcRecorder.h>
|
|
|
|
#if (TRC_USE_TRACEALYZER_RECORDER == 1)
|
|
|
|
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
|
|
|
|
#define VALIDATE_ENTRY_HANDLE(xEntryHandle) ((((TraceUnsignedBaseType_t)(xEntryHandle) >= (TraceUnsignedBaseType_t)pxEntryTable) && ((TraceUnsignedBaseType_t)(xEntryHandle) < ((TraceUnsignedBaseType_t)pxEntryTable + sizeof(TraceEntryTable_t)))))
|
|
|
|
#define GIVE_ENTRY_INDEX(xIndex) xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = (xIndex); xIndexTable.uiFreeIndexCount++
|
|
|
|
#define GET_FREE_INDEX_COUNT() xIndexTable.uiFreeIndexCount
|
|
|
|
#define CALCULATE_ENTRY_INDEX(xEntryHandle) (TraceEntryIndex_t)(((TraceUnsignedBaseType_t)((TraceUnsignedBaseType_t)(xEntryHandle) - (TraceUnsignedBaseType_t)pxEntryTable) / sizeof(TraceEntry_t)))
|
|
|
|
#if (TRC_ENTRY_TABLE_SLOTS > 256)
|
|
typedef uint16_t TraceEntryIndex_t;
|
|
#else
|
|
typedef uint8_t TraceEntryIndex_t;
|
|
#endif /* (TRC_CFG_ENTRY_TABLE_SLOTS > 256) */
|
|
|
|
typedef struct EntryIndexTable
|
|
{
|
|
TraceEntryIndex_t axFreeIndexes[TRC_ENTRY_TABLE_SLOTS];
|
|
uint32_t uiFreeIndexCount;
|
|
} TraceEntryIndexTable_t;
|
|
|
|
typedef struct TraceEntryTable
|
|
{
|
|
uint32_t uiSlots;
|
|
uint32_t uiEntrySymbolLength;
|
|
uint32_t uiEntryStateCount;
|
|
TraceEntry_t axEntries[TRC_ENTRY_TABLE_SLOTS];
|
|
} TraceEntryTable_t;
|
|
|
|
/* Private function definitions */
|
|
traceResult prvEntryIndexInitialize(TraceEntryIndexTable_t *pxIndexTable);
|
|
traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex);
|
|
|
|
/* Variables */
|
|
static TraceEntryTable_t *pxEntryTable;
|
|
static TraceEntryIndexTable_t xIndexTable;
|
|
|
|
traceResult xTraceEntryTableInitialize(TraceEntryTableBuffer_t *pxBuffer)
|
|
{
|
|
uint32_t i, j;
|
|
|
|
TRC_ASSERT_EQUAL_SIZE(TraceEntryTableBuffer_t, TraceEntryTable_t);
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(pxBuffer != 0);
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT((TRC_ENTRY_TABLE_SLOTS) != 0);
|
|
|
|
pxEntryTable = (TraceEntryTable_t*)pxBuffer;
|
|
|
|
pxEntryTable->uiSlots = TRC_ENTRY_TABLE_SLOTS;
|
|
pxEntryTable->uiEntrySymbolLength = TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE;
|
|
pxEntryTable->uiEntryStateCount = TRC_ENTRY_TABLE_STATE_COUNT;
|
|
|
|
for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++)
|
|
{
|
|
pxEntryTable->axEntries[i].pvAddress = 0;
|
|
for (j = 0; j < TRC_ENTRY_TABLE_STATE_COUNT; j++)
|
|
{
|
|
pxEntryTable->axEntries[i].xStates[j] = 0;
|
|
}
|
|
pxEntryTable->axEntries[i].szSymbol[0] = 0;
|
|
}
|
|
|
|
prvEntryIndexInitialize(&xIndexTable);
|
|
|
|
xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY);
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceEntryCreate(TraceEntryHandle_t *pxEntryHandle)
|
|
{
|
|
uint32_t i;
|
|
TraceEntryIndex_t xIndex;
|
|
TraceEntry_t *pxEntry;
|
|
|
|
TRACE_ALLOC_CRITICAL_SECTION();
|
|
|
|
/* We always check this */
|
|
if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY))
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(pxEntryHandle != 0);
|
|
|
|
TRACE_ENTER_CRITICAL_SECTION();
|
|
|
|
if (prvEntryIndexTake(&xIndex) != TRC_SUCCESS)
|
|
{
|
|
xTraceDiagnosticsIncrease(TRC_DIAGNOSTICS_ENTRY_SLOTS_NO_ROOM);
|
|
|
|
TRACE_EXIT_CRITICAL_SECTION();
|
|
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
pxEntry = &pxEntryTable->axEntries[xIndex];
|
|
|
|
pxEntry->pvAddress = (void*)pxEntry; /* We set a temporary address */
|
|
|
|
for (i = 0; i < TRC_ENTRY_TABLE_STATE_COUNT; i++)
|
|
{
|
|
pxEntry->xStates[i] = 0;
|
|
}
|
|
|
|
pxEntry->uiOptions = 0;
|
|
pxEntry->szSymbol[0] = 0;
|
|
|
|
*pxEntryHandle = (TraceEntryHandle_t)pxEntry;
|
|
|
|
TRACE_EXIT_CRITICAL_SECTION();
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceEntryDelete(TraceEntryHandle_t xEntryHandle)
|
|
{
|
|
TraceEntryIndex_t xIndex;
|
|
|
|
TRACE_ALLOC_CRITICAL_SECTION();
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
/* Calculate the index based on the entry address */
|
|
/* Does not need to be locked. */
|
|
/* This should never fail */
|
|
xIndex = CALCULATE_ENTRY_INDEX(xEntryHandle);
|
|
|
|
TRC_ASSERT(xIndex < TRC_ENTRY_TABLE_SLOTS);
|
|
|
|
TRACE_ENTER_CRITICAL_SECTION();
|
|
|
|
if (((TraceEntry_t*)xEntryHandle)->pvAddress == 0)
|
|
{
|
|
/* Someone else has deleted this already? */
|
|
TRACE_EXIT_CRITICAL_SECTION();
|
|
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
/* A valid address, so we assume it is OK. */
|
|
/* For good measure, we clear the address field */
|
|
((TraceEntry_t*)xEntryHandle)->pvAddress = 0;
|
|
|
|
/* Give back the index */
|
|
GIVE_ENTRY_INDEX(xIndex);
|
|
|
|
TRACE_EXIT_CRITICAL_SECTION();
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceEntryFind(void* pvAddress, TraceEntryHandle_t* pxEntryHandle)
|
|
{
|
|
uint32_t i;
|
|
TraceEntry_t* pxEntry;
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(pxEntryHandle != 0);
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(pvAddress != 0);
|
|
|
|
for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++)
|
|
{
|
|
pxEntry = (TraceEntry_t*)(((uint32_t)pxEntryTable->axEntries) + (i * sizeof(TraceEntry_t)));
|
|
if (pxEntry->pvAddress == pvAddress)
|
|
{
|
|
*pxEntryHandle = (TraceEntryHandle_t)pxEntry;
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
traceResult xTraceEntrySetSymbol(TraceEntryHandle_t xEntryHandle, const char* szSymbol)
|
|
{
|
|
uint32_t i;
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
if (szSymbol == 0)
|
|
{
|
|
szSymbol = "";
|
|
}
|
|
|
|
/* Does not need to be locked. */
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
for (i = 0; i < (TRC_ENTRY_TABLE_SYMBOL_LENGTH); i++)
|
|
{
|
|
((TraceEntry_t*)xEntryHandle)->szSymbol[i] = szSymbol[i]; /* We do this first to ensure we also get the 0 termination, if there is one */
|
|
|
|
if (szSymbol[i] == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Check the length of "name", if longer than TRC_ENTRY_TABLE_SYMBOL_LENGTH */
|
|
while ((szSymbol[i] != 0) && i < 128)
|
|
{
|
|
i++;
|
|
}
|
|
|
|
/* Remember the longest symbol name */
|
|
xTraceDiagnosticsSetIfHigher(TRC_DIAGNOSTICS_ENTRY_SYMBOL_LONGEST_LENGTH, i);
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceEntryGetCount(uint32_t* puiCount)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(puiCount != 0);
|
|
|
|
*puiCount = TRC_ENTRY_TABLE_SLOTS - GET_FREE_INDEX_COUNT();
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult xTraceEntryGetAtIndex(uint32_t index, TraceEntryHandle_t* pxEntryHandle)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(index < TRC_ENTRY_TABLE_SLOTS);
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(pxEntryHandle != 0);
|
|
|
|
*pxEntryHandle = (TraceEntryHandle_t)((uint32_t)(pxEntryTable->axEntries) + (index * sizeof(TraceEntry_t)));
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
#if ((TRC_CFG_USE_TRACE_ASSERT) == 1)
|
|
|
|
traceResult xTraceEntryCreateWithAddress(void* pvAddress, TraceEntryHandle_t* pxEntryHandle)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(pvAddress != 0);
|
|
|
|
return TRC_ENTRY_CREATE_WITH_ADDRESS(pvAddress, pxEntryHandle);
|
|
}
|
|
|
|
traceResult xTraceEntrySetState(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex, TraceUnsignedBaseType_t uxState)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(uiStateIndex < (TRC_ENTRY_TABLE_STATE_COUNT));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
return TRC_ENTRY_SET_STATE(xEntryHandle, uiStateIndex, uxState);
|
|
}
|
|
|
|
traceResult xTraceEntrySetOptions(TraceEntryHandle_t xEntryHandle, uint32_t uiMask)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* Does not need to be locked. */
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
return TRC_ENTRY_SET_OPTIONS(xEntryHandle, uiMask);
|
|
}
|
|
|
|
traceResult xTraceEntryClearOptions(TraceEntryHandle_t xEntryHandle, uint32_t uiMask)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* Does not need to be locked. */
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
return TRC_ENTRY_CLEAR_OPTIONS(xEntryHandle, uiMask);
|
|
}
|
|
|
|
traceResult xTraceEntryGetAddress(TraceEntryHandle_t xEntryHandle, void **ppvAddress)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(ppvAddress != 0);
|
|
|
|
/* Does not need to be locked. */
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
return TRC_ENTRY_GET_ADDRESS(xEntryHandle, ppvAddress);
|
|
}
|
|
|
|
traceResult xTraceEntryGetSymbol(TraceEntryHandle_t xEntryHandle, const char** pszSymbol)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(pszSymbol != 0);
|
|
|
|
/* Does not need to be locked. */
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
return TRC_ENTRY_GET_SYMBOL(xEntryHandle, pszSymbol);
|
|
}
|
|
|
|
traceResult xTraceEntryGetState(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex, TraceUnsignedBaseType_t *puxState)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(puxState != 0);
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(uiStateIndex < TRC_ENTRY_TABLE_STATE_COUNT);
|
|
|
|
/* Does not need to be locked. */
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
return TRC_ENTRY_GET_STATE(xEntryHandle, uiStateIndex, puxState);
|
|
}
|
|
|
|
traceResult xTraceEntryGetOptions(TraceEntryHandle_t xEntryHandle, uint32_t *puiOptions)
|
|
{
|
|
/* This should never fail */
|
|
TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
|
|
|
|
/* This should never fail */
|
|
TRC_ASSERT(puiOptions != 0);
|
|
|
|
/* Does not need to be locked. */
|
|
/* This should never fail */
|
|
TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
|
|
|
|
return TRC_ENTRY_GET_OPTIONS(xEntryHandle, puiOptions);
|
|
}
|
|
|
|
#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */
|
|
|
|
/* PRIVATE FUNCTIONS */
|
|
|
|
traceResult prvEntryIndexInitialize(TraceEntryIndexTable_t* pxIndexTable)
|
|
{
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++)
|
|
{
|
|
pxIndexTable->axFreeIndexes[i] = (TraceEntryIndex_t)i;
|
|
}
|
|
|
|
xIndexTable.uiFreeIndexCount = TRC_ENTRY_TABLE_SLOTS;
|
|
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex)
|
|
{
|
|
/* Critical Section must be active! */
|
|
TraceEntryIndex_t xIndex;
|
|
|
|
if (xIndexTable.uiFreeIndexCount == 0)
|
|
{
|
|
return TRC_FAIL;
|
|
}
|
|
|
|
/* Always take the first item */
|
|
xIndex = xIndexTable.axFreeIndexes[0];
|
|
xIndexTable.uiFreeIndexCount--;
|
|
|
|
/* Move the last item to the first slot, to avoid holes */
|
|
xIndexTable.axFreeIndexes[0] = xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount];
|
|
|
|
#if (TRC_ENTRY_TABLE_SLOTS > 256)
|
|
xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = UINT16_MAX;
|
|
#else
|
|
xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = UINT8_MAX;
|
|
#endif
|
|
|
|
*pxIndex = xIndex;
|
|
return TRC_SUCCESS;
|
|
}
|
|
|
|
#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
|
|
|
|
#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
|