vPortSuppressTicksAndSleep() Cortex M4 - time drift in tickless mode when there is a lot of IRQs

lantczak wrote on Friday, July 05, 2019:

I have a problem with time drift (~8 sec per day) when there is a lot of IRQs in the system (e.g. each 1ms) and tickless mode is used.
My CPU is SAM4E16C. I’m using port: \FreeRTOSv10.0.1\FreeRTOS\Source\portable\GCC\ARM_CM4F\port.c

I provide following changes in vPortSuppressTicksAndSleep() that decrease time error comparing to calendar time. The original implementation seems to be not rational, my changes:

Blow code was moved to else condition of if( eTaskConfirmSleepModeStatus() == eAbortSleep ).

       /* Stop the SysTick momentarily.  The time the SysTick is stopped for
		is accounted for as best it can be, but using the tickless mode will
		inevitably result in some tiny drift of the time maintained by the
		kernel with respect to calendar time. */
		portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;

		/* Calculate the reload value required to wait xExpectedIdleTime
		tick periods.  -1 is used because this code will execute part way
		through one of the tick periods. */
		ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
		if( ulReloadValue > ulStoppedTimerCompensation )
		{
			ulReloadValue -= ulStoppedTimerCompensation;
		}

It make no sense to stop systick and enable it again in if( eTaskConfirmSleepModeStatus() == eAbortSleep ).

Additionally variable ulReloadValue is used only in “else” so why we are calculating it here and provide additional drift.
Do you see any mistake in my changes?
Nevertheless after these changes + modification of portMISSED_COUNTS_FACTOR I was able to decrease time drift a lot but it is still present. I analyzed calculations made in code and it seems to be ok. The time of IRQ handler execution has no influence and is calculated properly. It seems like each interrupt that stops WFI is causing some error in systick content.
Has anyone expired problems with systick precision?

richarddamon wrote on Friday, July 05, 2019:

Almost be definition, a tickless mode that works by adjusting the tick counter is going to have some issues with drift.

8 Seconds a Day is less than 100 ppm, which isn’t much better than many crystals. If you really much better than that, you likely want to not use the tick for the long period timebase, but a true Real Time Clock that can be kept constantly running off a high accuracy 32,768 Hz crystal, so slight drift in the ticks due to tickless idle don’t matter.