How to enable HFCLK in ZephyrOS (nRF Connect SDK 1.9)

Hi,

I just want to learn if we can use high-freq clock to measure time in nanosecs precision. 

SoC: nRF52840

SDK: nRF Connect SDK (v1.9)

I know that it was not possible 2 years ago but I just wonder whether it can be enabled in nRF Connect SDK-v1.9 somehow.

https://devzone.nordicsemi.com/f/nordic-q-a/60049/configure-system-clock-faster-than-32768hz-in-ncs-zephyr

For example, this doesn't work properly:

static void heartbeat(void *p1, void *p2, void *p3)
{
	timing_t start_time = 0, end_time = 0;
	uint64_t total_cycles = 0;
	uint64_t total_ns = 0;

	timing_init();
	timing_start();

	while (1)
	{
		start_time = timing_counter_get();
		k_msleep(1000);
		end_time = timing_counter_get();
		total_cycles = timing_cycles_get(&start_time, &end_time);
		total_ns = timing_cycles_to_ns(total_cycles);
		gpio_pin_toggle(led1.port, led1.pin);
		printk("%s start=%llu end=%llu diff_ns=%llu\n", __func__, start_time, end_time, total_ns);
	}

	timing_stop();
}

Output:

heartbeat start=142232262 end=142238263 diff_ns=93765
heartbeat start=142539990 end=142545991 diff_ns=93765

The difference between start and end is around 6000 and the computed diff in ns is 93765, which is obviously wrong.

Any help with this example would be highly appreciated. Many thanks,

Ozan

Parents
  • Hello Vedat,

    Unfortunately, I don't think so. Though there was a bit of a hacky solution discussed here that might deserve a look.

    Regards,

    Elfving

  • Thanks for the link, Elfving. It sounds very promising but unfortunately I couldn't run my test app successfully. In my test app, I tried to add a simple k_timer and a periodic timeout handler in which led0 toggles. 

    The prj.conf file sets the config as in the link you've shared. (actually there is another one for nrf52840 here: github.com/.../28469

    CONFIG_NRF_RTC_TIMER=n
    CONFIG_CORTEX_M_SYSTICK=y
    CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=64000000
    CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000000

    And main.c:

    #include <zephyr.h>
    #include <sys/printk.h>
    #include <device.h>
    #include <drivers/gpio.h>
    
    static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios,
    													 {0});
    
    void my_timer_handler(struct k_timer *dummy)
    {
    	gpio_pin_toggle(led.port, led.pin);
    }
    
    K_TIMER_DEFINE(my_timer, my_timer_handler, NULL);
    
    void main(void)
    {
    	int ret = 0;
    	if (led.port && !device_is_ready(led.port))
    	{
    		printk("Error %d: LED device %s is not ready; ignoring it\n",
    			   ret, led.port->name);
    		led.port = NULL;
    	}
    	if (led.port)
    	{
    		ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
    		if (ret != 0)
    		{
    			printk("Error %d: failed to configure LED device %s pin %d\n",
    				   ret, led.port->name, led.pin);
    			led.port = NULL;
    		}
    		else
    		{
    			printk("Set up LED at %s pin %d\n", led.port->name, led.pin);
    		}
    	}
    
    	k_timer_start(&my_timer, K_SECONDS(1), K_SECONDS(1));
    }

    I see the led0 initialization is done on the serial output but I can't see led0 blinks. 

    When I comment out all prf.conf lines, which means when RTC is active as the clock source, the app starts to work as expected, ie led0 blinks. So apparently I'm missing something.

    In another application, I tested k_msleep(1) and this doesn't work either. The app never passes the sleep line, which suggests the underlying timer doesn't work.

    Any suggestion about how I can correct the configuration? Or anything else that can help with that?

    Many thanks,

    Ozan

Reply
  • Thanks for the link, Elfving. It sounds very promising but unfortunately I couldn't run my test app successfully. In my test app, I tried to add a simple k_timer and a periodic timeout handler in which led0 toggles. 

    The prj.conf file sets the config as in the link you've shared. (actually there is another one for nrf52840 here: github.com/.../28469

    CONFIG_NRF_RTC_TIMER=n
    CONFIG_CORTEX_M_SYSTICK=y
    CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=64000000
    CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000000

    And main.c:

    #include <zephyr.h>
    #include <sys/printk.h>
    #include <device.h>
    #include <drivers/gpio.h>
    
    static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios,
    													 {0});
    
    void my_timer_handler(struct k_timer *dummy)
    {
    	gpio_pin_toggle(led.port, led.pin);
    }
    
    K_TIMER_DEFINE(my_timer, my_timer_handler, NULL);
    
    void main(void)
    {
    	int ret = 0;
    	if (led.port && !device_is_ready(led.port))
    	{
    		printk("Error %d: LED device %s is not ready; ignoring it\n",
    			   ret, led.port->name);
    		led.port = NULL;
    	}
    	if (led.port)
    	{
    		ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
    		if (ret != 0)
    		{
    			printk("Error %d: failed to configure LED device %s pin %d\n",
    				   ret, led.port->name, led.pin);
    			led.port = NULL;
    		}
    		else
    		{
    			printk("Set up LED at %s pin %d\n", led.port->name, led.pin);
    		}
    	}
    
    	k_timer_start(&my_timer, K_SECONDS(1), K_SECONDS(1));
    }

    I see the led0 initialization is done on the serial output but I can't see led0 blinks. 

    When I comment out all prf.conf lines, which means when RTC is active as the clock source, the app starts to work as expected, ie led0 blinks. So apparently I'm missing something.

    In another application, I tested k_msleep(1) and this doesn't work either. The app never passes the sleep line, which suggests the underlying timer doesn't work.

    Any suggestion about how I can correct the configuration? Or anything else that can help with that?

    Many thanks,

    Ozan

Children
Related