k_uptime_get() drift way too much using LFXO.

Hi

This project is using nRF52840 and NCS 2.5.2, using LFXO as LFCLK source.

I added a code snippet which will be called once a button is pressed

#include <zephyr/drivers/clock_control.h>
void check_clock_calibration(void)
{
    static uint8_t first_enter = 1;
    if (first_enter) {
        first_enter = 0;
        if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
            LOG_ERR("LFRC calibration is enabled.");
        } else {
            LOG_ERR("LFRC calibration is disabled.");
        }
    }

    uint32_t lfclk_src = NRF_CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_SRC_Msk;
    if (lfclk_src == CLOCK_LFCLKSTAT_SRC_RC) {
        LOG_ERR("LFCLK is using LFRC.");
    } else if (lfclk_src == CLOCK_LFCLKSTAT_SRC_Xtal) {
        LOG_ERR("LFCLK is using external XTAL (LFXO).");
    } else if (lfclk_src == CLOCK_LFCLKSTAT_SRC_Synth) {
        LOG_ERR("LFCLK is using synthesized clock.");
    } else {
        LOG_ERR("LFCLK source is unknown or not set.");
    }

    LOG_ERR("NRF_CLOCK->LFCLKSTAT %d ", NRF_CLOCK->LFCLKSTAT);
    int64_t timestamp_ms = (int64_t)k_uptime_get();
    LOG_ERR("%s timestamp_ms %llu", __func__, timestamp_ms);
}

You can see that the delta between k_uptime_get() and RTT Viewer's timestamp increase to 738 ms within 30 seconds.

I double check the RTT Viewer's timestamp using a stop watch and it seems pretty accurate.

I continue this test for over 1 hour and the delta increase to over 90 seconds. Which is way too much.

00> [00:00:09.706,237] <err> sleekapp: LFRC calibration is disabled.
00> [00:00:09.706,268] <err> sleekapp: LFCLK is using external XTAL (LFXO).
00> [00:00:09.706,298] <err> sleekapp: NRF_CLOCK->LFCLKSTAT 65537 
00> [00:00:09.706,329] <err> sleekapp: check_clock_calibration timestamp_ms 9939 //delta:233
00> [00:00:11.357,482] <err> pal_run_loop: HAPPlatformRunLoopRun
00> [00:00:17.055,908] <err> sleekapp: LFCLK is using external XTAL (LFXO).
00> [00:00:17.055,938] <err> sleekapp: NRF_CLOCK->LFCLKSTAT 65537 
00> [00:00:17.055,969] <err> sleekapp: check_clock_calibration timestamp_ms 17465 //delta:409
00> [00:00:20.708,190] <err> sleekapp: LFCLK is using external XTAL (LFXO).
00> [00:00:20.708,221] <err> sleekapp: NRF_CLOCK->LFCLKSTAT 65537 
00> [00:00:20.708,251] <err> sleekapp: check_clock_calibration timestamp_ms 21205 //delta:497
00> [00:00:23.088,928] <err> pal_run_loop: HAPPlatformRunLoopRun
00> [00:00:23.586,120] <err> sleekapp: LFCLK is using external XTAL (LFXO).
00> [00:00:23.586,151] <err> sleekapp: NRF_CLOCK->LFCLKSTAT 65537 
00> [00:00:23.586,181] <err> sleekapp: check_clock_calibration timestamp_ms 24152 //delta:566
00> [00:00:25.461,120] <err> sleekapp: LFCLK is using external XTAL (LFXO).
00> [00:00:25.461,151] <err> sleekapp: NRF_CLOCK->LFCLKSTAT 65537 
00> [00:00:25.461,181] <err> sleekapp: check_clock_calibration timestamp_ms 26072 //delta:611
00> [00:00:27.160,339] <err> sleekapp: LFCLK is using external XTAL (LFXO).
00> [00:00:27.160,369] <err> sleekapp: NRF_CLOCK->LFCLKSTAT 65537 
00> [00:00:27.160,400] <err> sleekapp: check_clock_calibration timestamp_ms 27812 //delta:652
00> [00:00:30.735,534] <err> sleekapp: LFCLK is using external XTAL (LFXO).
00> [00:00:30.735,565] <err> sleekapp: NRF_CLOCK->LFCLKSTAT 65537 
00> [00:00:30.735,595] <err> sleekapp: check_clock_calibration timestamp_ms 31473 //delta:738

I use the same test scenario to add the same print on another project (different hardware, nRF52840 IC, different firmware using NCS 2.3.0).

The delta between k_uptime_get() and RTT Viewer's timestamp is less than 1 second after 1 hour test.

Could you kindly help me locate this issue to see is it hardware related?

Regards,

Anthony Yuan

Parents
  • Hi,

     

    Now you are introducing uncertainty in the RTT process itself, so this is not a very reliable way of checking the accuracy.

    What I would recommend is to check the timestamp against a known stable high speed timer on the nRF itself, as this is sourced from the HFCLK.

    What is important then is to first start the HFXO, either via clock_control API, or by just running this:

    NRF_CLOCK->TASKS_HFCLKSTART=1;
    while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;

     

    Kind regards,

    Håkon 

  • Hi Håkon,

    Just tested with CONFIG_SYS_CLOCK_TICKS_PER_SEC=1024 in .conf file

    And now the k_uptime_get() matching with RTT log and matching with my stop watch.

    I am not quite familiar with zephyr/kernel, I have 2 questions about CONFIG_SYS_CLOCK_TICKS_PER_SEC:

    1. I can't find out why NCS 2.3.0 and NCS 2.5.2 use the same CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 but have different result.

    2. I change CONFIG_SYS_CLOCK_TICKS_PER_SEC=2048 and the k_uptime_get() works properly too, as my understanding that it will make zephyr kernel more accurate if I set CONFIG_SYS_CLOCK_TICKS_PER_SEC=32768, but is there any side effects?

    Regards,

    Anthony Yuan

Reply
  • Hi Håkon,

    Just tested with CONFIG_SYS_CLOCK_TICKS_PER_SEC=1024 in .conf file

    And now the k_uptime_get() matching with RTT log and matching with my stop watch.

    I am not quite familiar with zephyr/kernel, I have 2 questions about CONFIG_SYS_CLOCK_TICKS_PER_SEC:

    1. I can't find out why NCS 2.3.0 and NCS 2.5.2 use the same CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 but have different result.

    2. I change CONFIG_SYS_CLOCK_TICKS_PER_SEC=2048 and the k_uptime_get() works properly too, as my understanding that it will make zephyr kernel more accurate if I set CONFIG_SYS_CLOCK_TICKS_PER_SEC=32768, but is there any side effects?

    Regards,

    Anthony Yuan

Children
No Data
Related