Operating System stop watch type timer

anonymous wrote on Tuesday, October 25, 2011:

Hi, I was recently working on some code and wanted to measure how long a function took to execute.  I was surprised to find that freeRTOS doesn’t offer any functions that help with this need.  Seems it would be relatively trivial to add.  Essentially by looking at whatever timer the OS uses and then getting how far into the countdown you are as well as the OS ticks you can see how long something has taken.  Here is some source code I’ve written.  Is there anything similar that I missed?  Would it be useful to include this in freeRTOS?  I would imagine that if we put the function somewhere in the OS it would have better access to things like xTickCount.

#define portNVIC_SYSTICK_VALUE       ( ( volatile unsigned long *) 0xe000e018 ) // for cortex M3, add to port.c file
#define LONG_COUNT portNVIC_SYSTICK_VALUE + (xTickCount * (( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL))
// When start is TRUE and previously FALSE it will reset and start the timer.
// When start is FALSE and previusly TRUE it will stop the timer and the function then returns clock ticks
int timer(BOOLEAN start)
static BOOLEAN timerRunning = FALSE;
static long counter = 0;

if(timerRunning == FALSE){ // timer is stopped
if(start == TRUE){ // re-set the timer
counter = LONG_COUNT;
return 0;
} else {
return 0;
} else { // timerRunning == TRUE
if(start == TRUE){ // here we just re-set the timer
counter = LONG_COUNT;
return 0;
} else {
return LONG_COUNT - counter;

Here’s how to use:
runTime = timer(FALSE);

rtel wrote on Tuesday, October 25, 2011:

The recent run time stats examples on Cortex-M3 parts use the sys tick value.  For example (this code is not necessarily bullet proof!):

unsigned long ulMainGetRunTimeCounterValue( void )
unsigned long ulSysTickCounts, ulTickCount, ulReturn;
const unsigned long ulSysTickReloadValue = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
volatile unsigned long * const pulCurrentSysTickCount = ( ( volatile unsigned long *) 0xe000e018 );
volatile unsigned long * const pulInterruptCTRLState = ( ( volatile unsigned long *) 0xe000ed04 );
const unsigned long ulSysTickPendingBit = 0x04000000UL;
	/* NOTE: There are potentially race conditions here.  However, it is used
	anyway to keep the examples simple, and to avoid reliance on a separate
	timer peripheral. */
	/* The SysTick is a down counter.  How many clocks have passed since it was
	last reloaded? */
	ulSysTickCounts = ulSysTickReloadValue - *pulCurrentSysTickCount;
	/* How many times has it overflowed? */
	ulTickCount = xTaskGetTickCountFromISR();
	/* Is there a SysTick interrupt pending? */
	if( ( *pulInterruptCTRLState & ulSysTickPendingBit ) != 0UL )
		/* There is a SysTick interrupt pending, so the SysTick has overflowed
		but the tick count not yet incremented. */
		/* Read the SysTick again, as the overflow might have occurred since
		it was read last. */
		ulSysTickCounts = ulSysTickReloadValue - *pulCurrentSysTickCount;
	/* Convert the tick count into tenths of a millisecond.  THIS ASSUMES
	configTICK_RATE_HZ is 1000! */
	ulReturn = ( ulTickCount * 10UL ) ;
	/* Add on the number of tenths of a millisecond that have passed since the
	tick count last got updated. */
	ulReturn += ( ulSysTickCounts / ulClocksPer10thOfAMilliSecond );
	return ulReturn;	

That is very non-portable though, considering there are 28 cores supported.

If you just want millisecond resolution, and the tick interrupt is set to 1Khz, you can use xTaskGetTickCount() to return the current tick count value.


anonymous wrote on Wednesday, October 26, 2011:

I was hoping for anything from less than micro seconds to 100s of milliseconds.  I agree using xTaskGetTickCount is a little cleaner than xTickCount depending on which module this function would be compiled from. 

So sounds like you’re saying neither pulCurrentSysTickCount or my portNVIC_SYSTICK_VALUE are defined in any of those other ports?  If it was defined it seems what I have could be fairly portable.

The other obvious limitation is that if the code being timed was interrupted by other tasks then all bets are off.