Clock implementation with internal RTOS

Hi, I’ve implemented a 64-bit Unix epoch clock in FreeRTOS. Below is my implementation.

void vGetSystemTime(TimeType_t * const xpTimeToBeReturned) {
  taskENTER_CRITICAL();
  *xpTimeToBeReturned = uxTime64;
  taskEXIT_CRITICAL();
}

void vSetSystemTime(TimeType_t const * const xpTimeToBeSet) {
  taskENTER_CRITICAL();
  uxTime64 = *xpTimeToBeSet;
  taskEXIT_CRITICAL();
}

The way how to keep track of elapsed ms is by using the below implemenation.

BaseType_t xTaskIncrementTick( void ) {
.......
        const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
        const TimeType_t xTime64Const = uxTime64 + (TimeType_t) 1;

        /* Increment the RTOS tick, switching the delayed and overflowed
         * delayed lists if it wraps to 0. */
        xTickCount = xConstTickCount;
        uxTime64 = xTime64Const;
......
}

However, I’m getting a huge drift about 10 secs for every minute. My measurements theniques were a bit crude but the drift was clearly evident. Also, I have no interrupts other than the stick firing. Can someone point to me what could be the mistake here? Thanks in advance.

Hello Manish,

Does the drift of 10 secs for every minute mean 50 sec? or 70 sec?

If it is 50 sec, it may means that ((60 - 50) / 60) percent of ticks are masked by UNIX kernel.

Best regards,
NoMaY

How accurate is the chip’s clocking? Some internal oscillators are very inaccurate - external can be amazingly accurate.

Hello Manish,

Are your chnages here?

https://github.com/TummalaManish/FreeRTOS-Kernel/commits/main

My advice is:

Before your changes, does the original tick count value count up as you expect?

Best regards,
NoMaY

@NoMaY-jp Yes those are my changes, I haven’t tested it without my change. @rtel Yes, I was using the internal oscillator. I’ll check with an external oscillator.

For every 60 elapsed in the real world the clocking is ticking 70ish seconds. Its varies very.

I didn’t get the last part of your comment i.e. “masked by UNIX kernel”. Could you please elaborate. I’ve no experience how the things work in UNIX world. I know that UNIX will try to keep track of time by counting ms after Jan, 1st, 1970. I’ve tried implement the same within freeRTOS.

Hello Manish,

I notice one more possibility:

Is the tick interrupt configured correctly as 1ms interval?

I’m not sure what kind of FreeRTOS are you using. i.e. the FreeRTOS simulator on Linux? or FreeRTOS on STM32 board? Or FreeRTOS on other MCU (or FPGA) board? If you are using STM32 board or other MCU (or FPGA) board, I think that it is worth to check this possibility.

Regarding your question, I’d like to know what kind of FreeRTOS are you using. If you don’t use the FreeRTOS simulator on Linux, please ignore my first reply.

Best regards,
NoMaY

Hello Manish,

I have an impression that ‘Its varies very’ is more strange than inaccuracy. I guess that this means the following result. (The values such as 60 secs and 80 secs are my guess.) Is it right?

For every 60 elapsed in the real world,
the clocking is ticking around 70 secs, but sometimes 60 secs or sometimes 80 secs.

How do you get this result? I guess that:

For every 60 elapsed in the real world,
you push a button on the MCU board.
When the button is pushed,
your program send your 64bits tick count value from UART.

Is it right? (On the other hand, to be honest, if you use the FreeRTOS simulator on Linux, I cannot guess how do you get the result.)

By the way, why don’t you use the tick hook functionality of FreeRTOS kernel? If you use it, you don’t have to touch the FreeRTOS kernel source code.

Best regards,
NoMaY

I’m using STM32 blue pill. Yes, the configTICK_RATE_HZ is 1000. Also, I’m using an external 8Mhz as the base for the clock generation with the system clock at 72Mhz. I’m thinking to check this on a TI launchpad.

I could, but thought I wanted to keep this in the kernel. So, that my application code would never be mixed with the kernel.

One thing to note, FreeRTOS (if configured with 32 bit tick) already keeps a 64 bit tick counter as it keeps an overflow counter, and you can use the utility function vTaskSetTimeOutState to fill a struct that has the current tick counter and overflow count. You could then just build a function that you could call to get these and offset it by the epoch value.

You will still need to figure out why your tick interrupt is unstable (have your put something to toggle a GPIO every tick interrupt to see what is happening?

Hi, Yes I’ve to measure the tick interrupt. Unfortunately, I don’t have an oscilloscope to measure the clock. I’ll do some scale down for the tick interrupt and check with my Chinese logic analyzer.