/* * Trace Recorder for Tracealyzer v4.6.0 * Copyright 2021 Percepio AB * www.percepio.com * * SPDX-License-Identifier: Apache-2.0 * * The FreeRTOS specific parts of the trace recorder */ #include #include #if ( !defined( TRC_USE_TRACEALYZER_RECORDER ) && configUSE_TRACE_FACILITY == 1 ) #error Trace Recorder: You need to include trcRecorder.h at the end of your FreeRTOSConfig.h! #endif #if ( defined( TRC_USE_TRACEALYZER_RECORDER ) && TRC_USE_TRACEALYZER_RECORDER == 1 ) #ifndef TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS /* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS is missing in trcConfig.h. */ #error "TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS must be defined in trcConfig.h." #endif #ifndef TRC_CFG_INCLUDE_TIMER_EVENTS /* TRC_CFG_INCLUDE_TIMER_EVENTS is missing in trcConfig.h. */ #error "TRC_CFG_INCLUDE_TIMER_EVENTS must be defined in trcConfig.h." #endif #ifndef TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS /* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS is missing in trcConfig.h. */ #error "TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS must be defined in trcConfig.h." #endif #ifndef TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS /* TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS is missing in trcConfig.h. Define this as 1 if using FreeRTOS v10 or later and like to trace stream buffer or message buffer events, otherwise 0. */ #error "TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be defined in trcConfig.h." #endif #if ( configUSE_TICKLESS_IDLE != 0 && ( TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR ) ) /* * The below error message is to alert you on the following issue: * * The hardware port selected in trcConfig.h uses the operating system timer for the * timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt. * * When using "tickless idle" mode, the recorder needs an independent time source in * order to correctly record the durations of the idle times. Otherwise, the trace may appear * to have a different length than in reality, and the reported CPU load is also affected. * * You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING * macro in your trcConfig.h file. But then the time scale may be incorrect during * tickless idle periods. * * To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT * in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros * accordingly, using a free running counter or an independent periodic interrupt timer. * See trcHardwarePort.h for details. * * For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the * DWT cycle counter for timestamping in these cases. */ #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle. #endif #endif #include #include #if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING ) || ( defined( TRC_CFG_ENABLE_STACK_MONITOR ) && ( TRC_CFG_ENABLE_STACK_MONITOR == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) ) #if defined( configSUPPORT_STATIC_ALLOCATION ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 ) static StackType_t stackTzCtrl[ TRC_CFG_CTRL_TASK_STACK_SIZE ]; static StaticTask_t tcbTzCtrl; #else #error "configSUPPORT_STATIC_ALLOCATION not supported before FreeRTOS v9" #endif #endif /* if defined( configSUPPORT_STATIC_ALLOCATION ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /* The TzCtrl task - receives commands from Tracealyzer (start/stop) */ static portTASK_FUNCTION( TzCtrl, pvParameters ); #endif /* if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING ) || ( defined( TRC_CFG_ENABLE_STACK_MONITOR ) && ( TRC_CFG_ENABLE_STACK_MONITOR == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) ) */ #if ( TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X ) /* If the project does not include the FreeRTOS timers, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */ #include #endif #if ( TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X ) /* If the project does not include the FreeRTOS event groups, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */ #include #endif #if ( TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) /* If the project does not include the FreeRTOS stream buffers, TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be set to 0 */ #include #endif #if ( TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND != TRC_ACKNOWLEDGED ) && ( TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_0 || TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_1 ) && ( configUSE_QUEUE_SETS == 1 ) #error "When using FreeRTOS v10.3.0 or v10.3.1, please make sure that the trace point in prvNotifyQueueSetContainer() in queue.c is renamed from traceQUEUE_SEND to traceQUEUE_SET_SEND in order to tell them apart from other traceQUEUE_SEND trace points. Then set TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND in trcConfig.h to TRC_ACKNOWLEDGED to get rid of this error." #endif #if defined( TRC_CFG_ENABLE_STACK_MONITOR ) && ( TRC_CFG_ENABLE_STACK_MONITOR == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) traceResult xTraceKernelPortGetUnusedStack( void * pvTask, TraceUnsignedBaseType_t * puxUnusedStack ) { *puxUnusedStack = uxTaskGetStackHighWaterMark( pvTask ); return TRC_SUCCESS; } #endif traceResult xTraceKernelPortDelay( uint32_t uiTicks ) { vTaskDelay( uiTicks ); return TRC_SUCCESS; } unsigned char xTraceKernelPortIsSchedulerSuspended( void ) { /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs, * INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in * FreeRTOSConfig.h for this function to be available. */ return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED; } #if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING ) typedef struct TraceKernelPortData { TraceHeapHandle_t xSystemHeapHandle; TraceKernelPortTaskHandle_t xTzCtrlHandle; } TraceKernelPortData_t; static TraceKernelPortData_t * pxKernelPortData; #define TRC_PORT_MALLOC( size ) pvPortMalloc( size ) traceResult xTraceKernelPortInitialize( TraceKernelPortDataBuffer_t * pxBuffer ) { TRC_ASSERT_EQUAL_SIZE( TraceKernelPortDataBuffer_t, TraceKernelPortData_t ); if( pxBuffer == 0 ) { return TRC_FAIL; } pxKernelPortData = ( TraceKernelPortData_t * ) pxBuffer; pxKernelPortData->xSystemHeapHandle = 0; pxKernelPortData->xTzCtrlHandle = 0; return TRC_SUCCESS; } traceResult xTraceKernelPortEnable( void ) { HeapStats_t xHeapStats; void * pvAlloc; if( pxKernelPortData->xSystemHeapHandle == 0 ) { /* Some magic to make sure the heap has been initialized! */ pvAlloc = pvPortMalloc( 1 ); if( pvAlloc != 0 ) { vPortFree( pvAlloc ); } vPortGetHeapStats( &xHeapStats ); xTraceHeapCreate( "System Heap", configTOTAL_HEAP_SIZE - xHeapStats.xAvailableHeapSpaceInBytes, configTOTAL_HEAP_SIZE - xHeapStats.xMinimumEverFreeBytesRemaining, configTOTAL_HEAP_SIZE, &pxKernelPortData->xSystemHeapHandle ); } if( pxKernelPortData->xTzCtrlHandle == 0 ) { /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */ #if defined( configSUPPORT_STATIC_ALLOCATION ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) pxKernelPortData->xTzCtrlHandle = xTaskCreateStatic( TzCtrl, STRING_CAST( "TzCtrl" ), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl ); #else xTaskCreate( TzCtrl, STRING_CAST( "TzCtrl" ), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, &pxKernelPortData->xTzCtrlHandle ); #endif if( pxKernelPortData->xTzCtrlHandle == 0 ) { xTraceError( TRC_ERROR_TZCTRLTASK_NOT_CREATED ); return TRC_FAIL; } } return TRC_SUCCESS; } static portTASK_FUNCTION( TzCtrl, pvParameters ) { ( void ) pvParameters; while( 1 ) { xTraceTzCtrl(); vTaskDelay( TRC_CFG_CTRL_TASK_DELAY ); } } #if ( TRC_CFG_SCHEDULING_ONLY == 0 ) void vTraceSetQueueName( void * pvQueue, const char * szName ) { xTraceObjectSetNameWithoutHandle( pvQueue, szName ); } void vTraceSetSemaphoreName( void * pvSemaphore, const char * szName ) { xTraceObjectSetNameWithoutHandle( pvSemaphore, szName ); } void vTraceSetMutexName( void * pvMutex, const char * szName ) { xTraceObjectSetNameWithoutHandle( pvMutex, szName ); } #if ( TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X ) void vTraceSetEventGroupName( void * pvEventGroup, const char * szName ) { xTraceObjectSetNameWithoutHandle( pvEventGroup, szName ); } #endif #if ( TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) void vTraceSetStreamBufferName( void * pvStreamBuffer, const char * szName ) { xTraceObjectSetNameWithoutHandle( pvStreamBuffer, szName ); } void vTraceSetMessageBufferName( void * pvMessageBuffer, const char * szName ) { xTraceObjectSetNameWithoutHandle( pvMessageBuffer, szName ); } #endif /* if ( TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) */ #endif /* if ( TRC_CFG_SCHEDULING_ONLY == 0 ) */ TraceHeapHandle_t xTraceKernelPortGetSystemHeapHandle( void ) { return pxKernelPortData->xSystemHeapHandle; } #endif /* if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING ) */ #if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT ) uint32_t prvTraceGetQueueNumber( void * handle ); #if ( TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X_X ) extern unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue ); extern void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber ); extern unsigned char ucQueueGetQueueType( xQueueHandle pxQueue ); uint32_t prvTraceGetQueueNumber( void * handle ) { return ( uint32_t ) ucQueueGetQueueNumber( handle ); } #else /* if ( TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X_X ) */ uint32_t prvTraceGetQueueNumber( void * handle ) { return ( uint32_t ) uxQueueGetQueueNumber( handle ); } #endif /* if ( TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X_X ) */ uint8_t prvTraceGetQueueType( void * pvQueue ) { /* This is either declared in header file in FreeRTOS 8 and later, or as extern above */ return ucQueueGetQueueType( pvQueue ); } /* Tasks */ uint16_t prvTraceGetTaskNumberLow16( void * pvTask ) { return TRACE_GET_LOW16( uxTaskGetTaskNumber( pvTask ) ); } uint16_t prvTraceGetTaskNumberHigh16( void * pvTask ) { return TRACE_GET_HIGH16( uxTaskGetTaskNumber( pvTask ) ); } void prvTraceSetTaskNumberLow16( void * pvTask, uint16_t uiValue ) { vTaskSetTaskNumber( pvTask, TRACE_SET_LOW16( uxTaskGetTaskNumber( pvTask ), uiValue ) ); } void prvTraceSetTaskNumberHigh16( void * pvTask, uint16_t uiValue ) { vTaskSetTaskNumber( pvTask, TRACE_SET_HIGH16( uxTaskGetTaskNumber( pvTask ), uiValue ) ); } uint16_t prvTraceGetQueueNumberLow16( void * pvQueue ) { return TRACE_GET_LOW16( prvTraceGetQueueNumber( pvQueue ) ); } uint16_t prvTraceGetQueueNumberHigh16( void * pvQueue ) { return TRACE_GET_HIGH16( prvTraceGetQueueNumber( pvQueue ) ); } void prvTraceSetQueueNumberLow16( void * pvQueue, uint16_t uiValue ) { vQueueSetQueueNumber( pvQueue, TRACE_SET_LOW16( prvTraceGetQueueNumber( pvQueue ), uiValue ) ); } void prvTraceSetQueueNumberHigh16( void * pvQueue, uint16_t uiValue ) { vQueueSetQueueNumber( pvQueue, TRACE_SET_HIGH16( prvTraceGetQueueNumber( pvQueue ), uiValue ) ); } #if ( TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) uint16_t prvTraceGetTimerNumberLow16( void * pvTimer ) { return TRACE_GET_LOW16( uxTimerGetTimerNumber( pvTimer ) ); } uint16_t prvTraceGetTimerNumberHigh16( void * pvTimer ) { return TRACE_GET_HIGH16( uxTimerGetTimerNumber( pvTimer ) ); } void prvTraceSetTimerNumberLow16( void * pvTimer, uint16_t uiValue ) { vTimerSetTimerNumber( pvTimer, TRACE_SET_LOW16( uxTimerGetTimerNumber( pvTimer ), uiValue ) ); } void prvTraceSetTimerNumberHigh16( void * pvTimer, uint16_t uiValue ) { vTimerSetTimerNumber( pvTimer, TRACE_SET_HIGH16( uxTimerGetTimerNumber( pvTimer ), uiValue ) ); } #endif /* if ( TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) */ #if ( TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) uint16_t prvTraceGetEventGroupNumberLow16( void * pvEventGroup ) { return TRACE_GET_LOW16( uxEventGroupGetNumber( pvEventGroup ) ); } uint16_t prvTraceGetEventGroupNumberHigh16( void * pvEventGroup ) { return TRACE_GET_HIGH16( uxEventGroupGetNumber( pvEventGroup ) ); } void prvTraceSetEventGroupNumberLow16( void * pvEventGroup, uint16_t uiValue ) { vEventGroupSetNumber( pvEventGroup, TRACE_SET_LOW16( uxEventGroupGetNumber( pvEventGroup ), uiValue ) ); } void prvTraceSetEventGroupNumberHigh16( void * pvEventGroup, uint16_t uiValue ) { vEventGroupSetNumber( pvEventGroup, TRACE_SET_HIGH16( uxEventGroupGetNumber( pvEventGroup ), uiValue ) ); } #endif /* if ( TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) */ #if ( TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) uint16_t prvTraceGetStreamBufferNumberLow16( void * pvStreamBuffer ) { return TRACE_GET_LOW16( uxStreamBufferGetStreamBufferNumber( pvStreamBuffer ) ); } uint16_t prvTraceGetStreamBufferNumberHigh16( void * pvStreamBuffer ) { return TRACE_GET_HIGH16( uxStreamBufferGetStreamBufferNumber( pvStreamBuffer ) ); } void prvTraceSetStreamBufferNumberLow16( void * pvStreamBuffer, uint16_t uiValue ) { vStreamBufferSetStreamBufferNumber( pvStreamBuffer, TRACE_SET_LOW16( uxStreamBufferGetStreamBufferNumber( pvStreamBuffer ), uiValue ) ); } void prvTraceSetStreamBufferNumberHigh16( void * pvStreamBuffer, uint16_t uiValue ) { vStreamBufferSetStreamBufferNumber( pvStreamBuffer, TRACE_SET_HIGH16( uxStreamBufferGetStreamBufferNumber( pvStreamBuffer ), uiValue ) ); } #endif /* if ( TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) */ static TraceKernelPortTaskHandle_t xTzCtrlHandle = 0; /* TzCtrl task TCB */ /* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */ int uiInEventGroupSetBitsFromISR = 0; /** * @internal Class reference table */ traceObjectClass TraceQueueClassTable[ 5 ] = { TRACE_CLASS_QUEUE, TRACE_CLASS_MUTEX, TRACE_CLASS_SEMAPHORE, TRACE_CLASS_SEMAPHORE, TRACE_CLASS_MUTEX }; #if ( TRC_CFG_SCHEDULING_ONLY == 0 ) void vTraceSetQueueName( void * pvQueue, const char * szName ) { prvTraceSetObjectName( TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER( QUEUE, pvQueue ), szName ); } void vTraceSetSemaphoreName( void * pvSemaphore, const char * szName ) { prvTraceSetObjectName( TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER( QUEUE, pvSemaphore ), szName ); } void vTraceSetMutexName( void * pvMutex, const char * szName ) { prvTraceSetObjectName( TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER( QUEUE, pvMutex ), szName ); } #if ( TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X ) void vTraceSetEventGroupName( void * pvEventGroup, const char * szName ) { prvTraceSetObjectName( TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER( EVENTGROUP, pvEventGroup ), szName ); } #endif #if ( TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) void vTraceSetStreamBufferName( void * pvStreamBuffer, const char * szName ) { prvTraceSetObjectName( TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER( STREAMBUFFER, pvStreamBuffer ), szName ); } void vTraceSetMessageBufferName( void * pvStreamBuffer, const char * szName ) { prvTraceSetObjectName( TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER( STREAMBUFFER, pvStreamBuffer ), szName ); } #endif /* if ( TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0 ) */ #endif /* if ( TRC_CFG_SCHEDULING_ONLY == 0 ) */ void * prvTraceGetCurrentTaskHandle() { return xTaskGetCurrentTaskHandle(); } traceResult xTraceKernelPortInitialize( TraceKernelPortDataBuffer_t * pxBuffer ) { ( void ) pxBuffer; return TRC_SUCCESS; } traceResult xTraceKernelPortEnable( void ) { #if defined( TRC_CFG_ENABLE_STACK_MONITOR ) && ( TRC_CFG_ENABLE_STACK_MONITOR == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) if( xTzCtrlHandle == 0 ) { #if defined( configSUPPORT_STATIC_ALLOCATION ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) xTzCtrlHandle = xTaskCreateStatic( TzCtrl, STRING_CAST( "TzCtrl" ), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl ); #else xTaskCreate( TzCtrl, STRING_CAST( "TzCtrl" ), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, &xTzCtrlHandle ); #endif } #else ( void ) xTzCtrlHandle; #endif return TRC_SUCCESS; } #if defined( TRC_CFG_ENABLE_STACK_MONITOR ) && ( TRC_CFG_ENABLE_STACK_MONITOR == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) static portTASK_FUNCTION( TzCtrl, pvParameters ) { ( void ) pvParameters; while( 1 ) { if( xTraceIsRecorderEnabled() ) { prvReportStackUsage(); } vTaskDelay( TRC_CFG_CTRL_TASK_DELAY ); } } #endif /* if defined( TRC_CFG_ENABLE_STACK_MONITOR ) && ( TRC_CFG_ENABLE_STACK_MONITOR == 1 ) && ( TRC_CFG_SCHEDULING_ONLY == 0 ) */ traceResult xTraceKernelPortInitObjectPropertyTable() { RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 0 ] = TRC_CFG_NQUEUE; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 1 ] = TRC_CFG_NSEMAPHORE; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 2 ] = TRC_CFG_NMUTEX; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 3 ] = TRC_CFG_NTASK; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 4 ] = TRC_CFG_NISR; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 5 ] = TRC_CFG_NTIMER; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 6 ] = TRC_CFG_NEVENTGROUP; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 7 ] = TRC_CFG_NSTREAMBUFFER; RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[ 8 ] = TRC_CFG_NMESSAGEBUFFER; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 0 ] = TRC_CFG_NAME_LEN_QUEUE; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 1 ] = TRC_CFG_NAME_LEN_SEMAPHORE; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 2 ] = TRC_CFG_NAME_LEN_MUTEX; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 3 ] = TRC_CFG_NAME_LEN_TASK; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 4 ] = TRC_CFG_NAME_LEN_ISR; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 5 ] = TRC_CFG_NAME_LEN_TIMER; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 6 ] = TRC_CFG_NAME_LEN_EVENTGROUP; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 7 ] = TRC_CFG_NAME_LEN_STREAMBUFFER; RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ 8 ] = TRC_CFG_NAME_LEN_MESSAGEBUFFER; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 0 ] = PropertyTableSizeQueue; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 1 ] = PropertyTableSizeSemaphore; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 2 ] = PropertyTableSizeMutex; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 3 ] = PropertyTableSizeTask; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 4 ] = PropertyTableSizeISR; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 5 ] = PropertyTableSizeTimer; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 6 ] = PropertyTableSizeEventGroup; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 7 ] = PropertyTableSizeStreamBuffer; RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[ 8 ] = PropertyTableSizeMessageBuffer; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 0 ] = StartIndexQueue; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 1 ] = StartIndexSemaphore; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 2 ] = StartIndexMutex; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 3 ] = StartIndexTask; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 4 ] = StartIndexISR; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 5 ] = StartIndexTimer; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 6 ] = StartIndexEventGroup; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 7 ] = StartIndexStreamBuffer; RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[ 8 ] = StartIndexMessageBuffer; RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE; return TRC_SUCCESS; } traceResult xTraceKernelPortInitObjectHandleStack() { uint32_t i = 0; objectHandleStacks.indexOfNextAvailableHandle[ 0 ] = objectHandleStacks.lowestIndexOfClass[ 0 ] = 0; objectHandleStacks.indexOfNextAvailableHandle[ 1 ] = objectHandleStacks.lowestIndexOfClass[ 1 ] = ( TRC_CFG_NQUEUE ); objectHandleStacks.indexOfNextAvailableHandle[ 2 ] = objectHandleStacks.lowestIndexOfClass[ 2 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ); objectHandleStacks.indexOfNextAvailableHandle[ 3 ] = objectHandleStacks.lowestIndexOfClass[ 3 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ); objectHandleStacks.indexOfNextAvailableHandle[ 4 ] = objectHandleStacks.lowestIndexOfClass[ 4 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ); objectHandleStacks.indexOfNextAvailableHandle[ 5 ] = objectHandleStacks.lowestIndexOfClass[ 5 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ); objectHandleStacks.indexOfNextAvailableHandle[ 6 ] = objectHandleStacks.lowestIndexOfClass[ 6 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ) + ( TRC_CFG_NTIMER ); objectHandleStacks.indexOfNextAvailableHandle[ 7 ] = objectHandleStacks.lowestIndexOfClass[ 7 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ) + ( TRC_CFG_NTIMER ) + ( TRC_CFG_NEVENTGROUP ); objectHandleStacks.indexOfNextAvailableHandle[ 8 ] = objectHandleStacks.lowestIndexOfClass[ 8 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ) + ( TRC_CFG_NTIMER ) + ( TRC_CFG_NEVENTGROUP ) + ( TRC_CFG_NSTREAMBUFFER ); objectHandleStacks.highestIndexOfClass[ 0 ] = ( TRC_CFG_NQUEUE ) -1; objectHandleStacks.highestIndexOfClass[ 1 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) -1; objectHandleStacks.highestIndexOfClass[ 2 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) -1; objectHandleStacks.highestIndexOfClass[ 3 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) -1; objectHandleStacks.highestIndexOfClass[ 4 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ) -1; objectHandleStacks.highestIndexOfClass[ 5 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ) + ( TRC_CFG_NTIMER ) -1; objectHandleStacks.highestIndexOfClass[ 6 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ) + ( TRC_CFG_NTIMER ) + ( TRC_CFG_NEVENTGROUP ) -1; objectHandleStacks.highestIndexOfClass[ 7 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ) + ( TRC_CFG_NTIMER ) + ( TRC_CFG_NEVENTGROUP ) + ( TRC_CFG_NSTREAMBUFFER ) -1; objectHandleStacks.highestIndexOfClass[ 8 ] = ( TRC_CFG_NQUEUE ) + ( TRC_CFG_NSEMAPHORE ) + ( TRC_CFG_NMUTEX ) + ( TRC_CFG_NTASK ) + ( TRC_CFG_NISR ) + ( TRC_CFG_NTIMER ) + ( TRC_CFG_NEVENTGROUP ) + ( TRC_CFG_NSTREAMBUFFER ) + ( TRC_CFG_NMESSAGEBUFFER ) -1; for( i = 0; i < TRACE_NCLASSES; i++ ) { objectHandleStacks.handleCountWaterMarksOfClass[ i ] = 0; } for( i = 0; i < TRACE_KERNEL_OBJECT_COUNT; i++ ) { objectHandleStacks.objectHandles[ i ] = 0; } return TRC_SUCCESS; } const char * pszTraceGetErrorNotEnoughHandles( traceObjectClass objectclass ) { switch( objectclass ) { case TRACE_CLASS_TASK: return "Not enough TASK handles - increase TRC_CFG_NTASK in trcSnapshotConfig.h"; case TRACE_CLASS_ISR: return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h"; case TRACE_CLASS_SEMAPHORE: return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h"; case TRACE_CLASS_MUTEX: return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h"; case TRACE_CLASS_QUEUE: return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h"; case TRACE_CLASS_TIMER: return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h"; case TRACE_CLASS_EVENTGROUP: return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h"; case TRACE_CLASS_STREAMBUFFER: return "Not enough STREAMBUFFER handles - increase TRC_CFG_NSTREAMBUFFER in trcSnapshotConfig.h"; case TRACE_CLASS_MESSAGEBUFFER: return "Not enough MESSAGEBUFFER handles - increase TRC_CFG_NMESSAGEBUFFER in trcSnapshotConfig.h"; default: return "pszTraceGetErrorHandles: Invalid objectclass!"; } } #endif /* if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT ) */ #endif /* if ( defined( TRC_USE_TRACEALYZER_RECORDER ) && TRC_USE_TRACEALYZER_RECORDER == 1 ) */