Timer Service Run-Time Counter Accessing

Hi,

I wished to display all of the freeRTOS tasks in the form below:

I included the idle task using:

rtosCountersNow.idle 			  	= ulTaskGetIdleRunTimeCounter();

But i also wished to include the timer service task. I worked out that it had the handle:

xTimerTaskHandle

But is has been defined as static viz:

/* A queue that is used to send commands to the timer service task. */
PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
PRIVILEGED_DATA TaskHandle_t xTimerTaskHandle = NULL;

So it is not available to use in order to get its RunTimeCounter field using:

#ifndef DRIVERS_FREERTOS_STATS_INC_FREERTOS_TASKS_C_ADDITIONS_H_
#define DRIVERS_FREERTOS_STATS_INC_FREERTOS_TASKS_C_ADDITIONS_H_

#include "FreeRTOS.h"
#include "task.h"

uint32_t TaskGetRunTimeCounter( TaskHandle_t xTask )
{
	TCB_t *pxTCB;
	uint32_t ulRunTimeCounter = 0;

	/* xTask is NULL then get the state of the calling task. */
	pxTCB = prvGetTCBFromHandle( xTask );


	#if ( configGENERATE_RUN_TIME_STATS == 1 )
	{
		ulRunTimeCounter = pxTCB->ulRunTimeCounter;
	}
	#endif

	return ulRunTimeCounter;
}

#endif /* DRIVERS_FREERTOS_STATS_INC_FREERTOS_TASKS_C_ADDITIONS_H_ */

I wasn’t sure what to do, so I did a naughty thing and changed the xTimerTaskHandle to global.

PRIVILEGED_DATA /* static */ TaskHandle_t xTimerTaskHandle = NULL;

This fixed my problem, but I feel dissatisfied as I’m sure there is a better way than me hacking the code.

Could someone advise me what I should do?

Best Regards
Rob.

PS I think someone did ask about this before, but a built in general per task
GetRuntime Counter function for individual tasks and the timer service would seem a useful feature.

Can you not use xTimerGetTimerDaemonTaskHandle?

One alternative would be to use xTaskGetHandle, which lets you get a task handle from the name of a task.

A Second would be to use uxTaskGetSystemState to get an array of task statuses, which includes the information you are looking for.

Hi GA

Thanks for that.

I must spend a bit more time browsing through the API so I get to know it better.

Regards
Rob

Hi Richard.

Thanks for that.

Will give it a try

Regards
Rob

Hi GA,

I took your advice - all good.

I ended up with the following code. I am posting it to help others who may wish to display or otherwise process counters.

I added a reset counter function to the code so the user can reset all counters without rebooting.

FreeRTOSConfig

...
#define configUSE_TRACE_FACILITY                 1
#define configGENERATE_RUN_TIME_STATS 			 1
#define configUSE_STATS_FORMATTING_FUNCTIONS     1
#define configRECORD_STACK_HIGH_ADDRESS          1
#define configUSE_16_BIT_TICKS                   0
#define configUSE_MUTEXES                        1
#define configQUEUE_REGISTRY_SIZE                8
#define configUSE_RECURSIVE_MUTEXES              1
#define configUSE_COUNTING_SEMAPHORES            1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION  0
#define configCHECK_FOR_STACK_OVERFLOW 			 0
#define configUSE_TASK_NOTIFICATIONS			 1
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1
...
#define INCLUDE_xTaskGetCurrentTaskHandle    1
#define INCLUDE_eTaskGetState                1
#define INCLUDE_xTaskGetIdleTaskHandle       1

freertos_tasks_c_additions.h

/*
******************************************************************************
* Project	   : STM32H7B3I_DISCO
* File Name    : freertos_tasks_c_additions.h
* File Path    : G:\ShorttClock_V2\ShorttClock_V2\STM32CubeIDE\Drivers\FreeRTOS Stats\Inc\freertos_tasks_c_additions.h
* File Wrk Spc : /STM32H7B3I_DISCO/Drivers/FreeRTOS Stats/Inc/freertos_tasks_c_additions.h
* Created On   : 25 Sep. 2022  3:37:48 pm
* Description  :
* Author	   : R J Garnett - Admin
******************************************************************************
*/

#ifndef DRIVERS_FREERTOS_STATS_INC_FREERTOS_TASKS_C_ADDITIONS_H_
#define DRIVERS_FREERTOS_STATS_INC_FREERTOS_TASKS_C_ADDITIONS_H_

#include "FreeRTOS.h"
#include "task.h"

uint32_t TaskGetRunTimeCounter(TaskHandle_t xTask)
{
	TCB_t *pxTCB;
	uint32_t ulRunTimeCounter = 0;

	/* xTask is NULL then get the state of the calling task. */
	pxTCB = prvGetTCBFromHandle( xTask );


	#if ( configGENERATE_RUN_TIME_STATS == 1 )
	{
		ulRunTimeCounter = pxTCB->ulRunTimeCounter;
	}
	#endif

	return ulRunTimeCounter;
}

/******************************************************************************/
void TaskResetRunTimeCounter(TaskHandle_t xTask)
{
	TCB_t *pxTCB;
	uint32_t ulRunTimeCounter = 0;

	/* xTask is NULL then get the state of the calling task. */
	pxTCB = prvGetTCBFromHandle( xTask );


	#if ( configGENERATE_RUN_TIME_STATS == 1 )
	{
		pxTCB->ulRunTimeCounter = 0;
	}
	#endif
}



#endif /* DRIVERS_FREERTOS_STATS_INC_FREERTOS_TASKS_C_ADDITIONS_H_ */



/*
******************************************************************************
* Project	   : STM32H7B3I_DISCO
* File Name    : freeRTOS_Stats.c
* File Path    : G:\ShorttClock_V2\ShorttClock_V2\STM32CubeIDE\Drivers\FreeRTOS Stats\Src\freeRTOS_Stats.c
* File Wrk Spc : /STM32H7B3I_DISCO/Drivers/FreeRTOS Stats/Src/freeRTOS_Stats.c
* Created On   : 25 Sep. 2022  2:07:24 pm
* Description  :
* Author	   : R J Garnett - Admin
******************************************************************************
*/
#pragma GCC optimize ("Ofast") /* rjg todo */
//#pragma GCC optimize ("O0") /* rjg todo */

#define USE_DTCM __attribute__((section (".DTCM_MISC")))
//#define USE_DTCM

#define USE_ITCM __attribute__((section(".ITCM_SECTION")))
//#define USE_ITCM

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "freeRTOS_Stats.h"

uint32_t TaskGetRunTimeCounter(TaskHandle_t xTask);
void 	 TaskResetRunTimeCounter(TaskHandle_t xTask);

volatile rtosCounter_t 		USE_DTCM rtosCountersNow;
volatile rtosCounter_t 		USE_DTCM rtosCountersSplit;
volatile rtosCounterPct_t	USE_DTCM rtosCountersPct;
//volatile bool 				USE_DTCM counterSplitFlag = false;
//bool 						USE_DTCM countCaptured = false;

extern volatile unsigned long ulStatsTimerTicks;
extern TaskHandle_t xHandleClkCont;
extern TaskHandle_t wiFiTskHandle;
extern TaskHandle_t printTaskHandle;
extern TaskHandle_t xHandleProx;
extern TaskHandle_t monitorTskHandle;
extern TaskHandle_t norFlashTskHandle;
extern TaskHandle_t dtmTskHandle;
extern TaskHandle_t xHandlePosStats;
extern TaskHandle_t xTimerTaskHandle;
extern osThreadId_t GUI_TaskHandle;


USE_ITCM inline void calcTaskUtilisation(void)
{
	float k;

	rtosCountersNow.ulStatsTimerTicks 	= ulStatsTimerTicks;
	rtosCountersNow.idle 			  	= ulTaskGetIdleRunTimeCounter();
	rtosCountersNow.I2C_task		  	= TaskGetRunTimeCounter(xHandleProx);
	rtosCountersNow.ClkContTsk			= TaskGetRunTimeCounter(xHandleClkCont);
	rtosCountersNow.GUI_Task			= TaskGetRunTimeCounter(GUI_TaskHandle);
	rtosCountersNow.dtmTask				= TaskGetRunTimeCounter(dtmTskHandle);
	rtosCountersNow.monTask				= TaskGetRunTimeCounter(monitorTskHandle);
	rtosCountersNow.tmrSrvc				= TaskGetRunTimeCounter(xTimerGetTimerDaemonTaskHandle());
	rtosCountersNow.wiFiTask			= TaskGetRunTimeCounter(wiFiTskHandle);
	rtosCountersNow.printTask			= TaskGetRunTimeCounter(printTaskHandle);
	rtosCountersNow.norFlashTask		= TaskGetRunTimeCounter(norFlashTskHandle);
	rtosCountersNow.PosStatsTsk			= TaskGetRunTimeCounter(xHandlePosStats);

	k = -0.002f;
	if(ulStatsTimerTicks > 0)
	{
		k = 100.0f / (float)ulStatsTimerTicks;
	}

	/* Now calc percentages */
	rtosCountersPct.idle			= (float)rtosCountersNow.idle 			* k;
	rtosCountersPct.I2C_task		= (float)rtosCountersNow.I2C_task 		* k;
	rtosCountersPct.ClkContTsk		= (float)rtosCountersNow.ClkContTsk 	* k;
	rtosCountersPct.GUI_Task		= (float)rtosCountersNow.GUI_Task 		* k;
	rtosCountersPct.dtmTask			= (float)rtosCountersNow.dtmTask 		* k;
	rtosCountersPct.monTask			= (float)rtosCountersNow.monTask 		* k;
	rtosCountersPct.tmrSrvc			= (float)rtosCountersNow.tmrSrvc 		* k;
	rtosCountersPct.wiFiTask		= (float)rtosCountersNow.wiFiTask 		* k;
	rtosCountersPct.printTask		= (float)rtosCountersNow.printTask 		* k;
	rtosCountersPct.norFlashTask	= (float)rtosCountersNow.norFlashTask 	* k;
	rtosCountersPct.PosStatsTsk		= (float)rtosCountersNow.PosStatsTsk 	* k;
}


USE_ITCM inline void resetRunTimeCounters(void)
{
//	rtosCountersNow.ulStatsTimerTicks 	= ulStatsTimerTicks;
//	rtosCountersNow.idle 			  	= ulTaskGetIdleRunTimeCounter();
//	rtosCountersNow.I2C_task		  	= TaskGetRunTimeCounter(xHandleProx);
//	rtosCountersNow.ClkContTsk			= TaskGetRunTimeCounter(xHandleClkCont);
//	rtosCountersNow.GUI_Task			= TaskGetRunTimeCounter(GUI_TaskHandle);
//	rtosCountersNow.dtmTask				= TaskGetRunTimeCounter(dtmTskHandle);
//	rtosCountersNow.monTask				= TaskGetRunTimeCounter(monitorTskHandle);
//	rtosCountersNow.tmrSrvc				= TaskGetRunTimeCounter(xTimerGetTimerDaemonTaskHandle());
//	rtosCountersNow.wiFiTask			= TaskGetRunTimeCounter(wiFiTskHandle);
//	rtosCountersNow.printTask			= TaskGetRunTimeCounter(printTaskHandle);
//	rtosCountersNow.norFlashTask		= TaskGetRunTimeCounter(norFlashTskHandle);
//	rtosCountersNow.PosStatsTsk			= TaskGetRunTimeCounter(xHandlePosStats);

	ulStatsTimerTicks = 0;
	TaskResetRunTimeCounter(xTaskGetIdleTaskHandle());
	TaskResetRunTimeCounter(xHandleProx);
	TaskResetRunTimeCounter(xHandleClkCont);
	TaskResetRunTimeCounter(GUI_TaskHandle);
	TaskResetRunTimeCounter(dtmTskHandle);
	TaskResetRunTimeCounter(monitorTskHandle);
	TaskResetRunTimeCounter(xTimerGetTimerDaemonTaskHandle());
	TaskResetRunTimeCounter(wiFiTskHandle);
	TaskResetRunTimeCounter(printTaskHandle);
	TaskResetRunTimeCounter(norFlashTskHandle);
	TaskResetRunTimeCounter(xHandlePosStats);

	/* Now calc percentages */
	rtosCountersPct.idle			= 0.0f;
	rtosCountersPct.I2C_task		= 0.0f;;
	rtosCountersPct.ClkContTsk		= 0.0f;;
	rtosCountersPct.GUI_Task		= 0.0f;;
	rtosCountersPct.dtmTask			= 0.0f;;
	rtosCountersPct.monTask			= 0.0f;;
	rtosCountersPct.tmrSrvc			= 0.0f;;
	rtosCountersPct.wiFiTask		= 0.0f;;
	rtosCountersPct.printTask		= 0.0f;;
	rtosCountersPct.norFlashTask	= 0.0f;;
	rtosCountersPct.PosStatsTsk		= 0.0f;;
}

Hope someone finds this useful.

Thank you for taking time to report your solution.