nrf52840 RC Oscillator | k_uptime_get() | Time drift issue

Hi Nordic Team,

In one of our product we are using nrf-52840 microcontroller. As per our product requirement we are using k_uptime_get() to measure the time with below configurations in both muc_boot.conf and proj.conf files. The CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 is also set in proj.conf file. Initially the device time is synced with the server time through a command we receive through BLE which calls the set_time() method  and then to get current time at any instant get_time() method  is used. In this way our device time is tracked/synced with the current epoch time and that actually works but after some days if we don't sink the device time with the server time then our device time leads the current epoch time starting form secs then minutes and then upto hours and this is something we are surprised that how come device time leads the current time. In our initial investigation we come to know that the time we are getting through  k_uptime_get() is not correct actually its moving faster and that leads the device time move ahead then the current time. Then in order to slow it down we have set CONFIG_SYS_CLOCK_TICKS_PER_SEC=1024 and by doing this we tested the device for 2 days and get the time synced till we didn't enable the timely reboot of device that we are doing once a day at night (as our product) requirement. Kindly let me know what is missing from our end. We also have external oscillator but we are not currently using it. Your help in this will be appreciated.  

Below Config settings Set on both mcu_boot.conf & Proj.conf

CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n
CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM=y
Method to Set the Time with Server

void set_time(int32_t epoch)
{

    /**
     * @brief reset epoch_offset
     *
     */
    epoch_offset = k_uptime_get();

    /**
     * @brief give the new timestamp to last_saved_time_of_fs
     * this timestamp most likely have come from server
     *
     */
    last_saved_time_of_fs = epoch;
}

Method to get the Current Epoch time

int64_t get_time()
{
    /**
     * @brief Get current system time uptime.
     * Deduct the epoch_offset (since the last time set_time() method was called).
     * Convert it in seconds and add to last_saved_time_of_fs
     *
     */
    int64_t up_time_since_last_time_set_in_secs = (k_uptime_get() - epoch_offset) / 1000;

    LOG_WRN("k_uptime_get()  = %zu\n",k_uptime_get());

    /**
     * @brief return the timestamp
     *
     */
    return last_saved_time_of_fs + up_time_since_last_time_set_in_secs;
}


  • Hi Hieu,

    I was using internal LP RC Oscillator before with PPM 250 and 

    CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 and witnessed this drift.


    Now I moved to External 32.768 kHz Oscillator with below config setting and experienced time drift of half an hour in one day i.e. time is moving ahead of the current time. I think I need to change CONFIG_SYS_CLOCK_TICKS_PER_SEC value from 1000 to the value that comply with external oscillator. Isn't it? 

    CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000


    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=n
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_20PPM=y


  • Hi Musadiq,

    Musadiq said:

    I was using internal LP RC Oscillator before with PPM 250 and 

    CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 and witnessed this drift.

    I hope it is now clear that the drift is normal even with calibration, as noted in my first response. The LFRC is only that good.

    I am not an expert on the kernel topic, but I looked into it and looks like CONFIG_SYS_CLOCK_TICKS_PER_SEC is the number of Zephyr kernel system ticks per second. Looks like it is used in deriving k_uptime_get() result.

    As the time are derived from RTC, which is supposed to count 32768 times a second, the clock tick should be more accurate if it is a factor of 32768. You can use 1024, 2048, etc. However, I believe this would be minor.

    Once again, I am not an expert on kernel topics, but I think you might also want to review if changing the TICKS_PER_SEC configuration will affect other milisecond-based kernel APIs.

    Musadiq said:
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=n
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_20PPM=y

    These look correct.

Related