This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

RTC with 1ms resolution - YYYY-MM-DD HH:MM:SS.mmm


I would like to create a RTC for stamping log messages, with 1ms resolution and including time from year to millisecond, like: YYYY-MM-DD HH:MM:SS.mmm.

What would be the best solution?

The 32kHz clock is not divisible by 1000, which means that some special handling is needed for accurate results.

regards, Elm

  • Hi Elm,

    I guess that will happen with any source. The most straight forward solution seems to me using RTC with some reasonable accuracy and periodic correction (to synchronize native clocks of the MCU and strange clock we human beings use for time measurements;) and then some mid/long term synchronization with "world" clock (like every 12/24/48 hours or longer, depending on the RTC accuracy inside MCU, environment, chip to chip variance etc.) I doubt there is some code ready off-the-shelf but I've implemented something like this on nRF51 with 4ms step, periodic corrections (there is obviously no settings for RTC or TIMER on nRF5x to achieve 100% 4ms stepping) and then out of band configuration to synchronize with world time and correct the thing periodically, it worked pretty well. Note that you can even implement over the air synchronization (where each station listens to specific advertisement packet from time to time and when it is received it corrects internal RTC accordingly) but then you still need to maintain one station with very accurate RTC.

    Cheers Jan

  • I just wanted to point out some errors in the math here. The RTC is 32768Hz, which is the standard since it is divisible by 2^n. So, to get millisecond accuracy you won't be dividing by 1000. All you need to do here is divide by 32 to get 1/1024 of a second accuracy. Since this is better than millisecond accuracy you only need to do some floating point math and round up to get a millisecond accurate time stamp. Because of the way the prescaler is implemented on nRF it might be easiest to run the prescaler at 0 for systick of 32768Hz and then use one of the compare registers to generate software events every 1/1024 of a second.
    Similarly, you can just set a compare register to run freely and overflow every 32768 and capture the value of the compare register whenever your event occurs. Then floating point math gets you to your timestamp again.

  • Sure, you can use RTC to run 1ms clock on nRF5x platforms. Doing whatever float math on such deeply embedded system is pretty nice red flag that design is not optimal (except some specific operations where you really need to do some advanced math on the chip to get inputs to other routines, however running time in human-readable clock is clearly not this case;) but you can do it you want...

  • A colleauge suggested this: Set up a continually running application timer, using the 32kHz clock, and make it fire every 32 clocks. This results in a clock that ticks 1024 ticks per second. Let the handler be tick_1024(). let tick_ms() be a function to be called every ms, on average. Then:

    void tick_1024() {
        static uint16_t a;
        a += 1000;
        if( a>= 1024) {
            a -= 1024;

    Essentially, it multiples the tick frequency of 1024 Hz with 1000/1024.

    What do you think? //Elm

  • Probably not a good idea to run a millisecond process on interrupts with a 64MHz processor. Depending on how much other activity is going on this could create backlogs of interrupts to be serviced. And, since you are looking to do a quasi RTOS process it would be better to run seconds and milliseconds as counters set to restart at the correct interval. All of this can be done in hardware on PPI. In this manner you only need to capture the register values to get the fine resolution part of the timestamp. The rest of the timestamp can just be kept in software registers.

    You didn't say what type of event was being logged. If by chance it is a hardware event like a comparator or external gpio input, etc. then the entire process is hardware driven with only a minor reporting function occurring in code.