diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index 3fecbdd..b597ed9 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -2670,6 +2670,10 @@ #if ( configGENERATE_RUN_TIME_STATS == 1 ) + #ifndef configUSE_STATS_FORMATTING_FUNCTIONS + #define configUSE_STATS_FORMATTING_FUNCTIONS 1 + #endif + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ diff --git a/include/task.h b/include/task.h index 0414eb9..73b1657 100644 --- a/include/task.h +++ b/include/task.h @@ -169,6 +169,9 @@ typedef struct xTASK_STATUS UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See https://www.FreeRTOS.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulPeriodDeltaRunTime; /* Runtime counter delta within the sampling period */ +#endif StackType_t * pxStackBase; /* Points to the lowest address of the task's stack area. */ #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) StackType_t * pxTopOfStack; /* Points to the top address of the task's stack area. */ @@ -3769,6 +3772,15 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC #endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */ +#if ( configSUPPORT_CMBACKTRACE == 1 ) + /* Functions to support CmBacktrace */ + void* vTaskGetCurrentTCB( void ); + uint32_t* vTaskStackAddr( void ); + volatile uint32_t* vTaskStackTOPAddr( void ); + uint32_t vTaskStackSize( void ); + char* vTaskName( void ); +#endif + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/tasks.c b/tasks.c index 22e11f0..1cb956f 100644 --- a/tasks.c +++ b/tasks.c @@ -383,6 +383,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) StackType_t * pxEndOfStack; /**< Points to the highest valid address for the stack. */ + #else + UBaseType_t uxSizeOfStack; /* Support For CmBacktrace */ #endif #if ( portCRITICAL_NESTING_IN_TCB == 1 ) @@ -409,6 +411,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to #if ( configGENERATE_RUN_TIME_STATS == 1 ) configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /**< Stores the amount of time the task has spent in the Running state. */ + configRUN_TIME_COUNTER_TYPE ulStartRunTimeCounterOfPeriod; + configRUN_TIME_COUNTER_TYPE ulEndRunTimeCounterOfPeriod; #endif #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) @@ -522,6 +526,21 @@ PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime[ conf #endif +/* + * Defines the size, in words, of the stack allocated to the idle task. + */ +#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE + +#define RTL_PLACE_IDLE_STACK_IN_SRAM +#ifdef RTL_PLACE_IDLE_STACK_IN_SRAM + /* Place idle stack in SRAM to prevent hangs when SDRAM is suspended */ + #if ((defined CONFIG_PLATFORM_8195A) || (defined CONFIG_PLATFORM_8711B)) + #include "section_config.h" + SRAM_BF_DATA_SECTION + #endif + static unsigned char ucIdleTaskHeap[ tskIDLE_STACK_SIZE * sizeof( StackType_t ) ]; +#endif + /*-----------------------------------------------------------*/ /* File private functions. --------------------------------*/ @@ -4944,6 +4963,10 @@ BaseType_t xTaskIncrementTick( void ) #endif } + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + prvGetRunTimeStatsOfPeriodForTasksInList(xTickCount); + #endif + traceRETURN_xTaskIncrementTick( xSwitchRequired ); return xSwitchRequired; @@ -6929,6 +6952,30 @@ static void prvResetNextTaskUnblockTime( void ) #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ +void* vTaskGetCurrentTCB(void) { + return (void*)pxCurrentTCB; +} +/*-----------------------------------------------------------*/ +uint32_t* vTaskStackAddr(void) { + return pxCurrentTCB->pxStack; +} +/*-----------------------------------------------------------*/ +volatile uint32_t* vTaskStackTOPAddr(void) { + return pxCurrentTCB->pxTopOfStack; +} +/*-----------------------------------------------------------*/ +uint32_t vTaskStackSize(void) { + #if ( portSTACK_GROWTH > 0 ) + return (pxNewTCB->pxEndOfStack - pxNewTCB->pxStack + 1); + #else + return pxCurrentTCB->uxSizeOfStack; + #endif +} +/*-----------------------------------------------------------*/ +char* vTaskName(void) { + return pxCurrentTCB->pcTaskName; +} + #if ( configNUMBER_OF_CORES > 1 ) /* If not in a critical section then yield immediately. @@ -7602,6 +7649,52 @@ static void prvResetNextTaskUnblockTime( void ) #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ /*-----------------------------------------------------------*/ +#if ( configGENERATE_RUN_TIME_STATS == 1 ) +static void prvGetRunTimeStatsOfPeriodForTasksInList(portTickType tickTmp) { + if (tickTmp % portCONFIGURE_STATS_PERIOD_VALUE) { + return; + } + + // Iterate through task lists and collect stats + for (UBaseType_t uxQueue = configMAX_PRIORITIES; uxQueue > 0; uxQueue--) { + if (!listLIST_IS_EMPTY(&(pxReadyTasksLists[uxQueue-1]))) { + prvGenerateRunTimeOfPeriod(&(pxReadyTasksLists[uxQueue-1]), tickTmp); + } + } + + // Check delayed and suspended lists + if (!listLIST_IS_EMPTY(pxDelayedTaskList)) { + prvGenerateRunTimeOfPeriod(pxDelayedTaskList, tickTmp); + } + + if (!listLIST_IS_EMPTY(pxOverflowDelayedTaskList)) { + prvGenerateRunTimeOfPeriod(pxOverflowDelayedTaskList, tickTmp); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + if (!listLIST_IS_EMPTY(&xSuspendedTaskList)) { + prvGenerateRunTimeOfPeriod(&xSuspendedTaskList, tickTmp); + } + #endif +} + +static void prvGenerateRunTimeOfPeriod(xList *pxList, portTickType tickTmp) { + volatile TCB_t *pxNextTCB, *pxFirstTCB; + + listGET_OWNER_OF_NEXT_ENTRY(pxFirstTCB, pxList); + do { + listGET_OWNER_OF_NEXT_ENTRY(pxNextTCB, pxList); + + if (tickTmp%(2*portCONFIGURE_STATS_PERIOD_VALUE)) { + pxNextTCB->ulStartRunTimeCounterOfPeriod = pxNextTCB->ulRunTimeCounter; + } else { + pxNextTCB->ulEndRunTimeCounterOfPeriod = pxNextTCB->ulRunTimeCounter; + } + + } while (pxNextTCB != pxFirstTCB); +} +#endif +/*-----------------------------------------------------------*/ TickType_t uxTaskResetEventItemValue( void ) {