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

  • 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 

  • Thanks for your reply Håkon,

    I will try your suggestion tomorrow.

    And I realize that there is a pattern in the data:

    I use the RTT timestamp as "total" and you can see the "delta/total" is linear relative and close to 0.024

    total delta delta/total
    9706 233 0.02400577
    17055 409 0.02398124
    20708 497 0.02400039
    23586 566 0.02399729
    25461 611 0.02399749
    27160 652 0.02400589
    30735 738 0.02401171

    0.024 == (1024 -1000)/1000

    Maybe I should change

    CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000

    to

    CONFIG_SYS_CLOCK_TICKS_PER_SEC=1024

Related