Hi,
I am using an nrf5340 with nrf connect sdk v1.9.1.
I need to calculate the duration of an event with nanosecond precision, so I am using an nrfx_timer at a frequency of 16MHz, so that I have a tick period of 62.5 ns.
Only for testing purposes, the event has a duration of milliseconds, but I realised that the duration calculated with the timer was always 5-8ms too early.
To investigate further I wrote the following code, in which I trivially use a zephyr timer that periodically (every 2 seconds) reads and cleans the nrfx timer.
#define TIMER_TEST_PERIOD 2000000 #define NRFX_TIMER_PERIOD_AT_16MHz 62500 static const nrfx_timer_t timer = NRFX_TIMER_INSTANCE(1); void timer_test_exp() { uint64_t timer_count = nrfx_timer_capture(&timer, NRF_TIMER_CC_CHANNEL1); uint64_t ns = timer_count * NRFX_TIMER_PERIOD_AT_16MHz / 1000; LOG_ERR("Timer count %d, %dns, err %d ns", timer_count, ns, TIMER_TEST_PERIOD*1000 - ns); nrfx_timer_clear(&timer); } static void timer_handler(nrf_timer_event_t event_type, void *context) { /*empty*/ } void rb_timer_init() { // Configure TIMER nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG; timer_cfg.interrupt_priority = 0; timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32; err_code = nrfx_timer_init(&timer, &timer_cfg, timer_handler); if (err_code != NRFX_SUCCESS) { LOG_ERR("[rb_timer_init] nrfx_timer_init error: %08x", err_code); return; } k_timer_init(&timer_test, timer_test_exp, NULL); nrfx_timer_enable(&timer); k_timer_start(&timer_test, K_NO_WAIT, K_USEC(TIMER_TEST_PERIOD)); LOG_WRN("[rb_timer_init] --- timer init ---"); }
With the following output:
Again, I get an error of 6-7ms in advance. I would expect the nrfx timer to give me a value of 2'000'000'000 ns or something more, due to the delay of the k_timer handler call.
It seems really strange to me that the calculation comes out ahead of the period of the k_timer.
By calculating the duration using system ticks (k_cycle_get_32()), I paradoxically get closer to the actual duration. However, since the kernel has a frequency of 32kHz, I cannot go below 30.52 us per tick and for my purposes this is not sufficient.
I have tried various instances and channels of the nrfx_timer, with the same result.
How do I use the nrfx_timer accurately?
Regards,
APochiero