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 Musadiq,

    As you are using the internal RC (LFRC) for low-frequency clock (LFCLK) source, this amount of drift seems normal.

    From the Clock section of the Product Specification, you can find that the LFRC is rated for 5% tolerance when not calibrated, and 500ppm when calibrated at least every 8 seconds. External conditions such as temperature will also negatively impact the tolerance as well.

    To translate that spec to the day-by-day drift perspective from your question:

    Tolerance Worst-case Drift in 1,000,000s
    (s)
    Worst-case Drift in 1 day, or 86,400s
    (s)
    LFRC, calibrated 500 ppm 500 43.2
    LFRC, not calibrated 5% 50,000 4,320

    If you actually have an external low frequency crystal clock source with better tolerance, then please use it.

    Please note that while many crystals, with a proper oscillator circuit, will give you significantly better tolerance, there will still be some tolerance and drifts. Depends on your timing accuracy requirement, you might need additional synching or processing to reduce the drift.

    Hieu

  • Hi Hieu,

    We were getting BLE connectivity issues while using the external oscillator that why we decided to use the internal LP RC. For external oscillator we were using the below config settings in both muc_boot.conf & proj.conf files. Kindly have a look if there is any thing wrong in config settings or missing?

     

    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=n
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM=y


    Moreover, if we use the internal RC oscillator then I think Calibration is ON by default to every 4s i.e. we don't need to add any config lines in proj.conf & mcu_boot.conf files to turn ON the Calibration. Isn't it?
  • Hi Musadiq,

    Musadiq said:

    For external oscillator we were using the below config settings in both muc_boot.conf & proj.conf files. Kindly have a look if there is any thing wrong in config settings or missing?

     

    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=n
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM=y

    You need to pick a choice of CONFIG_CLOCK_CONTROL_NRF_ACCURACY_PPM according to the tolerance of your oscillator circuit. Does your circuit actually have a 250PPM tolerance?

    Musadiq said:
    Moreover, if we use the internal RC oscillator then I think Calibration is ON by default to every 4s i.e. we don't need to add any config lines in proj.conf & mcu_boot.conf files to turn ON the Calibration. Isn't it?

    It should be on by default, yes. To be absolutely sure you can check the value of CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION and CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_LF_ALWAYS_ON in the compiled Kconfig. It shouldn't happen with these CLOCK_CONTROL Kconfigs, but sometimes, another Kconfig in the build system can affect their value. It usually results in a warning in the early stage of a pristine build (rebuild does not go through the Kconfig step unless configuration files were changed).

    The compiled Kconfig of the main app is in <build directory>/zephyr/.config.

    The compiled Kconfig of the mcuboot child image is in <build directory>/mcuboot/zephyr/.config.

    While you look at it, please also check all other CLOCK_CONTROL_* Kconfig.

  • Hi Hieu,

    Thanks for your reply. I checked the both compiled .config files of main app &  mucboot child image. In both files I can see below lines indicating that by default RC Calibration is ON and Calibration period is set to 4000 ms. Moreover 250PPM is selected for LPRC. So I have 2 questions now.

    1. As you can see RC calibration is ON but still I can see the time drift starting from seconds, minutes and then hours. Is it drift is normal even calibration is ON.

    2. My external oscillator has accuracy PPM of 20PPM, I checked the specs. Have a look at Config Setting and let me if anything missing that needs to be added. 


    I am expecting that using external oscillator solves the time drift issue and BLE connectivity issue will not come again after selecting the right PPM.


    .config file build

    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y
    CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_LF_ALWAYS_ON=y
    CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_PERIOD=4000
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM=y



    Config Settings in Proj.conf and muc_boot.conf files for External 32khz Oscillator 

    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:
    1. As you can see RC calibration is ON but still I can see the time drift starting from seconds, minutes and then hours. Is it drift is normal even calibration is ON.

    Does this drift happen with the change to 20 ppm external crystal or without?

    As mentioned in my previous answer, even with calibration, the tolerance of LFRC (internal RC clock) is still 500 ppm, which means a worst-case drift of 43.2 seconds a day.

    Musadiq said:
    2. My external oscillator has accuracy PPM of 20PPM, I checked the specs. Have a look at Config Setting and let me if anything missing that needs to be added. 

    Your build output config says the 250PPM choice was selected, but the input you listed has 20PPM. Which are you using? Please make sure to choose the correct one.

    Besides that, please make sure that the components of the oscillating circuit are appropriately selected. Incorrect component selections will add tolerance to your circuit, increasing the drift.

Related