How to reset vTaskGetRunTimeStats?

Hi! I’m using vTaskGetRunTimeStats() to see the relative CPU load of my tasks. I’m using a microsecond timer for portGETRUNTIMECOUNTERVALUE, so overflows happen every hour or so, making the output unusable. Also I’m usually interested in the short-time behavior instead of load-since-system-boot. So extending ulRunTimeCounter to 64 bit would only solve part of the problem. Ideally I’d like to have a vTaskInfoReset() function or a “reset” flag to vTaskGetRunTimeStats() to reset the ulRunTimeCounters of all tasks. What would be the best way to go ahead? (If I do it myself – would a patch be accepted?) best regards, Thomas

How to reset vTaskGetRunTimeStats?

I have a feeling that at some point there was experimentation with such a function, but it is evidently not in the code. For now what you can do is add in your own function without modifying the source files by using the freertostaskscadditions.h header file. If you create that header file and set configINCLUDEFREERTOSTASKCADDITIONSH to 1 in FreeRTOSConfig.h the header file will be included at the bottom of tasks.c, where you will then have access to the private data within that file.

How to reset vTaskGetRunTimeStats?

I work a freertostacksc_additions.h header file that does that shown below: Call vTaskClearUsage() to reset all the execution time stats. Hasn’t been thoughouly tested, but seems to work for me. (FreeRTOSAdditions.h is a header file to provide the prototype for vTaskClearUsage() so other files can call this.) ~~~

ifndef FREERTOSFREERTOSPPFREERTOSTASKSCADDITIONSH

define FREERTOSFREERTOSPPFREERTOSTASKSCADDITIONSH

include <FreeRTOSAdditions.h>

void vTaskClearUsageSingleList(Listt *pxList) { configLISTVOLATILE TCB_t *pxNextTCB, *pxFirstTCB;
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) {
    listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );

    /* Clear Usage for each task that is referenced from
    pxList.  See the definition of TaskStatus_t in task.h for the
    meaning of each TaskStatus_t structure member. */
    do {
        listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
        pxNextTCB->ulRunTimeCounter = 0;
    } while( pxNextTCB != pxFirstTCB );
}
} void vTaskClearUsage() { UBaseTypet uxQueue = configMAXPRIORITIES; vTaskSuspendAll(); /* Clear runtime counter for each task in the Ready State / do { uxQueue–; vTaskClearUsageSingleList(&( pxReadyTasksLists[ uxQueue ] )); } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Clear runtime counter for each task in the Blocked state. */
vTaskClearUsageSingleList(( List_t * ) pxDelayedTaskList);
vTaskClearUsageSingleList(( List_t * ) pxOverflowDelayedTaskList);

if( INCLUDE_vTaskDelete == 1 )

/* Clear runtime counter for each task that has been deleted but not yet cleaned up. */
vTaskClearUsageSingleList(&xTasksWaitingTermination);

endif

if ( INCLUDE_vTaskSuspend == 1 )

/* Clear runtime counter for each task in the Suspended state. */
vTaskClearUsageSingleList(&xSuspendedTaskList);

endif

ulTaskSwitchedInTime = 0;
ulTotalRunTime = 0;
vConfigureTimerForRunTimeStats();
xTaskResumeAll();
}

endif /* FREERTOSFREERTOSPPFREERTOSTASKSCADDITIONSH_ */

~~~

How to reset vTaskGetRunTimeStats?

I’m also interested to have this included in the standard package. In the mean time I have an alternative approch – based on Richard Damon’s suggestion. This is an additional function ‘vTaskGetCombinedRunTimeStats()’ – below – in ‘freertostacksc_additions.h’ that combines the output of ‘vTaskGetRunTimeStats()’ and ‘vTaskList()’ with the option to clear the counters on every call. The size of ‘pcWriteBuffer’ passed in needs to increase from 40 to 60 bytes per task. It basically works, but there are 2 issues. 1) when counters are not cleared, the total percentage adds up to 110-111% – not sure why. 2) when counters are cleared, the bulk of the execution time is recorded aganist the task calling this function instead of IDLE task (using hardware output this function takes 1% of CPU time – which is what is displayed when the counters are not cleared). Can anyone explain this? The ESC[ codes to format the output need more work. I was trying to use cursor save and restore – maybe not supported properly by my terminal application. void vTaskGetCombinedRunTimeStats( char* pcWriteBuffer, UBaseTypet uxClear) { TaskStatust *pxTaskStatusArray; UBaseType_t uxArraySize, x; uint32_t ulTotalTime, ulStatsAsPercentage; char cStatus; pcWriteBuffer += sprintf( pcWriteBuffer, “x1b[1;1HTsk# TaskNamet StatetPriot HWM CPUtime(us) CPUloadrn”); // Snapshot number of tasks // Allocate memory for the binary task data structure uxArraySize = uxTaskGetNumberOfTasks(); pxTaskStatusArray = pvPortMalloc(uxArraySize * sizeof(TaskStatus_t)); if( pxTaskStatusArray != NULL ) { /* Generate the (binary) data – returns the number of tasks */ uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, &ulTotalTime);
/* For percentage calculations. */
ulTotalTime /= 100UL;

/* Create a human readable table from the binary data. */
for( x = 0; x < uxArraySize; x++ )
{
  pcWriteBuffer += sprintf( pcWriteBuffer, "%3u  ", pxTaskStatusArray[ x ].xTaskNumber );
  sprintf(pcWriteBuffer, "%s            ", pxTaskStatusArray[ x ].pcTaskName);
  pcWriteBuffer += 14; // Assumes task name is less than 12 characters and more than 2
  switch(pxTaskStatusArray[ x ].eCurrentState )
  {
    case eRunning:
      cStatus = 'X';
      break;
    case eReady:
      cStatus = 'R';
      break;
    case eBlocked:
      cStatus = 'B';
      break;
    case eSuspended:
      cStatus = 'S';
      break;
    case eDeleted:
      cStatus = 'D';
      break;
    default:        /* Should not get here, but it is included to prevent static checking errors. */
      cStatus = 'I';
      break;
  }
  pcWriteBuffer += sprintf( pcWriteBuffer, " %c    %2i    %6i", cStatus, pxTaskStatusArray[ x ].uxCurrentPriority, pxTaskStatusArray[ x ].usStackHighWaterMark);

  if(ulTotalTime > 0UL)
  {
    ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;

    if( ulStatsAsPercentage > 0UL )
    {
      pcWriteBuffer += sprintf( pcWriteBuffer, "%13u    %3u%%", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
    }
    else
    {
      pcWriteBuffer += sprintf( pcWriteBuffer, "%13u     <1%%", pxTaskStatusArray[ x ].ulRunTimeCounter );
    }

    if(uxClear)
    {
      pxTaskStatusArray[ x ].xHandle->ulRunTimeCounter = 0;
    }
  }
  pcWriteBuffer += sprintf(pcWriteBuffer, "rnx1b[0K");
}

if(uxClear)
{
  ulTaskSwitchedInTime = 0;
  ulTotalRunTime = 0;
}

vPortFree( pxTaskStatusArray );
} else { mtCOVERAGETESTMARKER(); } }