Hi all,
I use uxTaskGetSystemState to calculate a "cpu load" percentage which I need to report in my application. I use code very similar to the example in https://www.freertos.org/uxTaskGetSystemState.html. My question is: How do I know / handle when pulTotalRunTime overflows? This value is a uint32, and if my math is right, it will overflow every 71 minutes. When it does, my stats get all confused because the value is now counting from 0 again while the task run times may or may not have overflowed.
So, is there a good way to handle this? Or is there any way to reset the counters?
Thanks,
Jason
How to deal with overflow in uxTaskGetSystemState?
Re: How to deal with overflow in uxTaskGetSystemState?
This isn't exactly a solution to the overflow issue, but the following workaround function might be useful for your purposes. It essentially measures FreeRTOS Task CPU usage over a given period instead of over the total run time.
This goes in task.h
This goes in task.c
This goes in task.h
Code: Select all
/**
* Get the real time CPU usage statistics as a string
*
* This tasks measures the CPU usage of each task as a percentage over a given time.
* This function will block over the measurement duration, and CPU usage will be shown
* as a percentage of the overall measurement duration.
*
* @param pcWriteBuffer A buffer into which the execution times will be
* written, in ASCII form. This buffer is assumed to be large enough to
* contain the generated report. Approximately 40 bytes per task should
* be sufficient.
*
* @param xTicksToWait The number of ticks the CPU consumption should be measured over.
* This function will during the measurement, therefore the duration of measurement
* may be extended if a higher priority tasks prevents the calling task from unblocking.
*
* @note The stats of any tasks that are created or deleted whilst this function is
* blocked will not be shown.
*
* \ingroup TaskUtils
*/
BaseType_t vTaskGetRealTimeStats( char *pcWriteBuffer, TickType_t xTicksToWait );
Code: Select all
BaseType_t vTaskGetRealTimeStats( char *pcWriteBuffer, TickType_t xTicksToWait )
{
#if( configUSE_TRACE_FACILITY != 1 )
{
#error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
}
#endif
TaskStatus_t *pxTaskStatusArrayStart = NULL, *pxTaskStatusArrayEnd = NULL;
UBaseType_t uxArraySizeStart, uxArraySizeEnd;
uint32_t ulTimeStart, ulTimeEnd, ulStatsAsPercentage;
// Make sure the write buffer does not contain a string.
*pcWriteBuffer = 0x00;
//Allocate array to store the statuses of current tasks
uxArraySizeStart = uxCurrentNumberOfTasks;
pxTaskStatusArrayStart = pvPortMalloc( uxArraySizeStart * sizeof( TaskStatus_t ) );
if(pxTaskStatusArrayStart == NULL) {
//Failed to allocated starting task status arrays
goto err;
}
//Get starting statuses of tasks
uxArraySizeStart = uxTaskGetSystemState(pxTaskStatusArrayStart, uxArraySizeStart, &ulTimeStart);
if (uxArraySizeStart == 0) {
//Array was not large enough to store all task statuses
goto err;
}
//Wait for the specified amount of time
vTaskDelay(xTicksToWait);
uxArraySizeEnd = uxCurrentNumberOfTasks;
pxTaskStatusArrayEnd = pvPortMalloc( uxArraySizeEnd * sizeof( TaskStatus_t ) );
if(pxTaskStatusArrayEnd == NULL) {
//Failed to allocated ending task status arrays
goto err;
}
//Get end statuses of tasks
uxArraySizeEnd = uxTaskGetSystemState(pxTaskStatusArrayEnd, uxArraySizeEnd, &ulTimeEnd);
if (uxArraySizeEnd == 0){
//Array was not large enough to store all task statuses
goto err;
}
//Get measurement duration for real time stats. Check if total time has overflowed
uint32_t ulElapsedTime = (ulTimeStart <= ulTimeEnd) ? (ulTimeEnd - ulTimeStart) : (ulTimeStart - ulTimeEnd);
ulElapsedTime = (ulElapsedTime/100UL)*portNUM_PROCESSORS;
if (ulElapsedTime > 0) {
//Calculate and write stats to buffer
uint32_t ulTaskRunTime;
for (UBaseType_t i = 0; i < uxArraySizeStart; i++) {
//Before and After arrays may not store tasks in the same order
bool found = false;
for (UBaseType_t j = 0; j < uxArraySizeEnd; j++) {
if (pxTaskStatusArrayStart[i].xHandle == pxTaskStatusArrayEnd[j].xHandle) {
//Get duration task has run for. Check if duration has overflowed
ulTaskRunTime = (pxTaskStatusArrayStart[i].ulRunTimeCounter <= pxTaskStatusArrayEnd[j].ulRunTimeCounter) ?
(pxTaskStatusArrayEnd[j].ulRunTimeCounter - pxTaskStatusArrayStart[i].ulRunTimeCounter) :
(pxTaskStatusArrayStart[i].ulRunTimeCounter - pxTaskStatusArrayEnd[j].ulRunTimeCounter);
found = true;
break;
}
}
if (!found) {
//Could not find the same task in task status end array. Could have been deleted while this function blocked.
continue;
}
ulStatsAsPercentage = ulTaskRunTime / ulElapsedTime;
pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArrayStart[i].pcTaskName );
if( ulStatsAsPercentage > 0UL ){
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{
sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", ulTaskRunTime, ulStatsAsPercentage );
}
#else
{
/* sizeof( int ) == sizeof( long ) so a smaller
printf() library can be used. */
sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) ulTaskRunTime, ( unsigned int ) ulStatsAsPercentage );
}
#endif
} else {
/* If the percentage is zero here then the task has
consumed less than 1% of the total run time. */
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{
sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", ulTaskRunTime );
}
#else
{
/* sizeof( int ) == sizeof( long ) so a smaller
printf() library can be used. */
sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) ulTaskRunTime );
}
#endif
}
pcWriteBuffer += strlen( pcWriteBuffer );
}
}
//Free memory used
free(pxTaskStatusArrayStart);
free(pxTaskStatusArrayEnd);
return pdPASS;
err:
if (pxTaskStatusArrayStart != NULL) {
free(pxTaskStatusArrayStart);
}
if (pxTaskStatusArrayEnd != NULL) {
free(pxTaskStatusArrayEnd);
}
return pdFAIL;
}
Re: How to deal with overflow in uxTaskGetSystemState?
ESP_Dazz wrote:This isn't exactly a solution to the overflow issue, but the following workaround function might be useful for your purposes. It essentially measures FreeRTOS Task CPU usage over a given period instead of over the total run time.
Thanks ESP_Dazz! I had considered writing something like this myself, so thank you for saving me the trouble!
Jason
Who is online
Users browsing this forum: axellin, Bing [Bot], Majestic-12 [Bot] and 101 guests