From ddc840fd28926ae68d150fd1f0a093eb704d1331 Mon Sep 17 00:00:00 2001 From: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Mon, 14 Jun 2021 12:17:41 -0700 Subject: [PATCH] Make the type used to hold run-time counter values configurable (#350) * Introduce configRUN_TIME_COUNTER_TYPE which enables developers to define the type used to hold run time statistic counters. Defaults to uint32_t for backward compatibility. #define configRUN_TIME_COUNTER_TYPE to a type (for example, uint64_t) in FreeRTOSConfig.h to override the default. Introduce ulTaskGetIdleRunTimePercent() to complement the pre-existing ulTaskGetIdleRunTimeCounter(). Whereas the pre-existing function returns the raw run time counter value, the new function returns the percentage of the entire run time consumed by the idle task. Note the amount of idle time is only a good measure of the slack time in a system if there are no other tasks executing at the idle priority, tickless idle is not used, and configIDLE_SHOULD_YIELD is set to 0. * Add ultaskgetidleruntimepercent to lexicon.txt. * Update History file. Add the MPU version of ulTaskGetIdleRunTimePercent(). * Update include/FreeRTOS.h to correct comment as per aggarg@ suggestion. * Fix alignment in mpu_wrappers.h. Commit changes to mpu_prototypes.h which were missed from the original commit. --- .github/lexicon.txt | 1 + History.txt | 31 ++++++++++++++++------ include/FreeRTOS.h | 9 ++++++- include/mpu_prototypes.h | 5 ++-- include/mpu_wrappers.h | 1 + include/task.h | 31 ++++++++++++++-------- portable/Common/mpu_wrappers.c | 19 +++++++++++--- tasks.c | 47 ++++++++++++++++++++++++++-------- 8 files changed, 109 insertions(+), 35 deletions(-) diff --git a/.github/lexicon.txt b/.github/lexicon.txt index 7bc3bd6e3..782e4ec3e 100644 --- a/.github/lexicon.txt +++ b/.github/lexicon.txt @@ -2332,6 +2332,7 @@ ulstatsaspercentage ulstoppedtimercompensation ultablebase ultaskgetidleruntimecounter +ultaskgetidleruntimepercent ultaskhasfpucontext ultasknotificationtakeindexed ultasknotifystateclear diff --git a/History.txt b/History.txt index 34fc6863c..c9d3a12c8 100644 --- a/History.txt +++ b/History.txt @@ -1,3 +1,18 @@ +Changes between FreeRTOS V10.4.4 and TBD + + + Introduce configRUN_TIME_COUNTER_TYPE which enables developers to define + the type used to hold run time statistic counters. Defaults to uint32_t + for backward compatibility. #define configRUN_TIME_COUNTER_TYPE to a type + (for example, uint64_t) in FreeRTOSConfig.h to override the default. + + Introduce ulTaskGetIdleRunTimePercent() to complement the pre-existing + ulTaskGetIdleRunTimeCounter(). Whereas the pre-existing function returns + the raw run time counter value, the new function returns the percentage of + the entire run time consumed by the idle task. Note the amount of idle + time is only a good measure of the slack time in a system if there are no + other tasks executing at the idle priority, tickless idle is not used, and + configIDLE_SHOULD_YIELD is set to 0. + + Documentation and download available at https://www.FreeRTOS.org/ Changes between FreeRTOS V10.4.3 and FreeRTOS V10.4.4 released May 28 2021 @@ -38,7 +53,7 @@ Changes between FreeRTOS V10.4.3 and FreeRTOS V10.4.4 released May 28 2021 correcting and improving code comments. + Go look at the smp branch to see the progress towards the Symetric Multiprocessing Kernel. https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/smp - + Changes between FreeRTOS V10.4.2 and FreeRTOS V10.4.3 released December 14 2020 V10.4.3 is included in the 202012.00 LTS release. Learn more at https:/freertos.org/lts-libraries.html @@ -54,14 +69,14 @@ Changes between FreeRTOS V10.4.2 and FreeRTOS V10.4.3 released December 14 2020 Changes between FreeRTOS V10.4.1 and FreeRTOS V10.4.2 released November 10 2020 - + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html - + Fix an issue in the ARMv8-M ports that caused BASEPRI to be masked - between the first task starting to execute and that task making + + Fix an issue in the ARMv8-M ports that caused BASEPRI to be masked + between the first task starting to execute and that task making a FreeRTOS API call. + Introduced xTaskDelayUntil(), which is functionally equivalent to - vTaskDelayUntil(), with the addition of returning a value to + vTaskDelayUntil(), with the addition of returning a value to indicating whether or not the function placed the calling task into the Blocked state or not. + Update WolfSSL to 4.5.0 and add the FIPS ready demo. @@ -75,8 +90,8 @@ Changes between FreeRTOS V10.4.0 and FreeRTOS V10.4.1 released September 17 2020 See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html - + Fixed an incorrectly named parameter that prevented the - ulTaskNotifyTakeIndexed macro compiling, and the name space clash in the + + Fixed an incorrectly named parameter that prevented the + ulTaskNotifyTakeIndexed macro compiling, and the name space clash in the test code that prevented this error causing test failures. @@ -117,7 +132,7 @@ Changes between FreeRTOS V10.3.1 and FreeRTOS V10.4.0 released September 10 2020 + Added new POSIX port layer that allows FreeRTOS to run on Linux hosts in the same way the Windows port layer enables FreeRTOS to run on Windows hosts. - + Many other minor optimisations and enhancements. For full details + + Many other minor optimisations and enhancements. For full details see https://github.com/FreeRTOS/FreeRTOS-Kernel/commits/main diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index 67ae791db..ffb1f74e7 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -905,6 +905,13 @@ #define configSTACK_DEPTH_TYPE uint16_t #endif +#ifndef configRUN_TIME_COUNTER_TYPE +/* Defaults to uint32_t for backward compatibility, but can be overridden in + * FreeRTOSConfig.h if uint32_t is too restrictive. */ + + #define configRUN_TIME_COUNTER_TYPE uint32_t +#endif + #ifndef configMESSAGE_BUFFER_LENGTH_TYPE /* Defaults to size_t for backward compatibility, but can be overridden @@ -1197,7 +1204,7 @@ typedef struct xSTATIC_TCB void * pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t ulDummy16; + configRUN_TIME_COUNTER_TYPE ulDummy16; #endif #if ( configUSE_NEWLIB_REENTRANT == 1 ) struct _reent xDummy17; diff --git a/include/mpu_prototypes.h b/include/mpu_prototypes.h index 7a0fafd41..4359ab62e 100644 --- a/include/mpu_prototypes.h +++ b/include/mpu_prototypes.h @@ -89,8 +89,9 @@ BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL; UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, - uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL; -uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL; + configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL; +configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL; +configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent( void ) FREERTOS_SYSTEM_CALL; void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; void MPU_vTaskGetRunTimeStats( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, diff --git a/include/mpu_wrappers.h b/include/mpu_wrappers.h index 7da760248..7f07d0001 100644 --- a/include/mpu_wrappers.h +++ b/include/mpu_wrappers.h @@ -77,6 +77,7 @@ #define vTaskList MPU_vTaskList #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats #define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter + #define ulTaskGetIdleRunTimePercent MPU_ulTaskGetIdleRunTimePercent #define xTaskGenericNotify MPU_xTaskGenericNotify #define xTaskGenericNotifyWait MPU_xTaskGenericNotifyWait #define ulTaskGenericNotifyTake MPU_ulTaskGenericNotifyTake diff --git a/include/task.h b/include/task.h index f1d020a46..b1e7b2340 100644 --- a/include/task.h +++ b/include/task.h @@ -52,7 +52,7 @@ * * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD * values will reflect the last released version number. - */ + */ #define tskKERNEL_VERSION_NUMBER "V10.4.4+" #define tskKERNEL_VERSION_MAJOR 10 #define tskKERNEL_VERSION_MINOR 4 @@ -159,7 +159,7 @@ typedef struct xTASK_STATUS eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ 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. */ - uint32_t 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. */ + 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. */ StackType_t * pxStackBase; /* Points to the lowest address of the task's stack area. */ configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ } TaskStatus_t; @@ -1723,7 +1723,7 @@ TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; * { * TaskStatus_t *pxTaskStatusArray; * volatile UBaseType_t uxArraySize, x; - * uint32_t ulTotalRunTime, ulStatsAsPercentage; + * configRUN_TIME_COUNTER_TYPE ulTotalRunTime, ulStatsAsPercentage; * * // Make sure the write buffer does not contain a string. * pcWriteBuffer = 0x00; @@ -1779,7 +1779,7 @@ TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; */ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, - uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION; + configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; /** * task. h @@ -1886,11 +1886,12 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin /** * task. h - *
uint32_t ulTaskGetIdleRunTimeCounter( void );
+ *
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void );
+ *
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void );
* - * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS - * must both be defined as 1 for this function to be available. The application - * must also then provide definitions for + * configGENERATE_RUN_TIME_STATS, configUSE_STATS_FORMATTING_FUNCTIONS and + * INCLUDE_xTaskGetIdleTaskHandle must all be defined as 1 for these functions + * to be available. The application must also then provide definitions for * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() * to configure a peripheral timer/counter and return the timers current count * value respectively. The counter should be at least 10 times the frequency of @@ -1902,9 +1903,16 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total * execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter() - * returns the total execution time of just the idle task. + * returns the total execution time of just the idle task and + * ulTaskGetIdleRunTimePercent() returns the percentage of the CPU time used by + * just the idle task. * - * @return The total run time of the idle task. This is the amount of time the + * Note the amount of idle time is only a good measure of the slack time in a + * system if there are no other tasks executing at the idle priority, tickless + * idle is not used, and configIDLE_SHOULD_YIELD is set to 0. + * + * @return The total run time of the idle task or the percentage of the total + * run time consumed by the idle task. This is the amount of time the * idle task has actually been executing. The unit of time is dependent on the * frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and * portGET_RUN_TIME_COUNTER_VALUE() macros. @@ -1912,7 +1920,8 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter * \ingroup TaskUtils */ -uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; +configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; +configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) PRIVILEGED_FUNCTION; /** * task. h diff --git a/portable/Common/mpu_wrappers.c b/portable/Common/mpu_wrappers.c index 34a4fce14..e9ed25f29 100644 --- a/portable/Common/mpu_wrappers.c +++ b/portable/Common/mpu_wrappers.c @@ -349,9 +349,22 @@ char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) /* FREERTOS_SYSTEM_CALL */ /*-----------------------------------------------------------*/ #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) - uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) /* FREERTOS_SYSTEM_CALL */ + configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent( void ) /* FREERTOS_SYSTEM_CALL */ { - uint32_t xReturn; + configRUN_TIME_COUNTER_TYPE xReturn; + BaseType_t xRunningPrivileged = xPortRaisePrivilege(); + + xReturn = ulTaskGetIdleRunTimePercent(); + vPortResetPrivilege( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) + configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter( void ) /* FREERTOS_SYSTEM_CALL */ + { + configRUN_TIME_COUNTER_TYPE xReturn; BaseType_t xRunningPrivileged = xPortRaisePrivilege(); xReturn = ulTaskGetIdleRunTimeCounter(); @@ -430,7 +443,7 @@ char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) /* FREERTOS_SYSTEM_CALL */ #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * pxTaskStatusArray, UBaseType_t uxArraySize, - uint32_t * pulTotalRunTime ) /* FREERTOS_SYSTEM_CALL */ + configRUN_TIME_COUNTER_TYPE * pulTotalRunTime ) /* FREERTOS_SYSTEM_CALL */ { UBaseType_t uxReturn; BaseType_t xRunningPrivileged = xPortRaisePrivilege(); diff --git a/tasks.c b/tasks.c index 28de63bdb..5314fccc7 100644 --- a/tasks.c +++ b/tasks.c @@ -293,7 +293,7 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ + configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ #endif #if ( configUSE_NEWLIB_REENTRANT == 1 ) @@ -399,8 +399,8 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t /* Do not move these variables to function scope as doing so prevents the * code working with debuggers that need to remove the static qualifier. */ - PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ - PRIVILEGED_DATA static volatile uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ + PRIVILEGED_DATA static configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ + PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ #endif @@ -958,7 +958,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, #if ( configGENERATE_RUN_TIME_STATS == 1 ) { - pxNewTCB->ulRunTimeCounter = 0UL; + pxNewTCB->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0; } #endif /* configGENERATE_RUN_TIME_STATS */ @@ -2523,7 +2523,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, - uint32_t * const pulTotalRunTime ) + configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) { UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; @@ -3748,7 +3748,7 @@ static void prvCheckTasksWaitingTermination( void ) } #else { - pxTaskStatus->ulRunTimeCounter = 0; + pxTaskStatus->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0; } #endif @@ -4538,7 +4538,7 @@ static void prvResetNextTaskUnblockTime( void ) { TaskStatus_t * pxTaskStatusArray; UBaseType_t uxArraySize, x; - uint32_t ulTotalTime, ulStatsAsPercentage; + configRUN_TIME_COUNTER_TYPE ulTotalTime, ulStatsAsPercentage; #if ( configUSE_TRACE_FACILITY != 1 ) { @@ -4599,7 +4599,7 @@ static void prvResetNextTaskUnblockTime( void ) { /* What percentage of the total run time has the task used? * This will always be rounded down to the nearest integer. - * ulTotalRunTimeDiv100 has already been divided by 100. */ + * ulTotalRunTime has already been divided by 100. */ ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; /* Write the task name to the string, padding with @@ -5263,7 +5263,7 @@ TickType_t uxTaskResetEventItemValue( void ) #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) - uint32_t ulTaskGetIdleRunTimeCounter( void ) + configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) { return xIdleTaskHandle->ulRunTimeCounter; } @@ -5271,7 +5271,34 @@ TickType_t uxTaskResetEventItemValue( void ) #endif /*-----------------------------------------------------------*/ -static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) + + configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) + { + configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn; + + ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE(); + + /* For percentage calculations. */ + ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100; + + /* Avoid divide by zero errors. */ + if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 ) + { + ulReturn = xIdleTaskHandle->ulRunTimeCounter / ulTotalTime; + } + else + { + ulReturn = 0; + } + + return ulReturn; + } + +#endif +/*-----------------------------------------------------------*/ + + static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) { TickType_t xTimeToWake;