Unexpected timing value behavior when using Zephyr timing functions.

I need to measure pulse widths with microsecond accuracy using a NRF7002DK. To do that I am using Zephyr Time Functions (CONFIG_TIMING_FUNCTIONS). My SDK is v2.6.0.

The pulses are routed to a GPIO interrupt that is configured GPIO_INT_LEVEL_ACTIVE to interrupt on a high and then GPIO_INT_LEVEL_INACTIVE on a low. The pulses are roughly 8400 microseconds wide +/- 300 microseconds.

My thread starts with:

wait_for_asserted = true;
gpio_pin_interrupt_configure_dt( &gpio, GPIO_INT_LEVEL_ACTIVE );

The GPIO interrupt callback is as follows:

static void gpio_callback(
   const struct device *dev,
   struct gpio_callback *cb,
   uint32_t pins )
{
   timing_t assert_time;
   timing_t deassert_time;
   uint64_t total_cycles;
   uint64_t total_time_in_us;
   uint32_t k_assert_time;
   uint32_t k_deassert_time;

   if ( wait_for_asserted )
   {
      timing_init();

      timing_start();
      assert_time = timing_counter_get();
      k_assert_time = k_uptime_get();

      wait_for_asserted = false;
      gpio_pin_interrupt_configure_dt( &gpio, GPIO_INT_LEVEL_INACTIVE );
   }
   else
   {
      deassert_time = timing_counter_get();
      k_deassert_time = k_uptime_get();
      timing_stop();

      wait_for_asserted = true;
      gpio_pin_interrupt_configure_dt( &gpio, GPIO_INT_LEVEL_ACTIVE );

      total_cycles = timing_cycles_get( &assert_time, &deassert_time );
      total_time_in_us = timing_cycles_to_ns( total_cycles ) / 1000;

      if ( total_time_in_us >= 2000 )
      {
         struct msg_item_s msg;

         msg.id = MSG_ID_ASSERTION;
         msg.time_in_us = total_time_in_us;
         msg.assert_time = assert_time;
         msg.deassert_time = deassert_time;
         msg.k_assert_time = k_assert_time;
         msg.k_deassert_time = k_deassert_time;

         k_msgq_put( &msgq, &msg, K_NO_WAIT );
      }
   }
}

When my thread receives the message I print the following:

printk( "time_in_us: %llu\n", msg.time_in_us );
printk( "assert_time: %llu\n", msg.assert_time );
printk( "deassert_time: %llu\n", msg.deassert_time );
printk( "k_assert_time: %u\n", msg.k_assert_time );
printk( "k_deassert_time: %u\n", msg.k_deassert_time );

Immediately after system reset, I run the routine and get the following debug:

ime_in_us: 8624
assert_time: 3747779501
deassert_time: 3748331488
k_assert_time: 61866
k_deassert_time: 61875

time_in_us: 8245
assert_time: 3760017779
deassert_time: 3760545462
k_assert_time: 62059
k_deassert_time: 62068

This is exactly what I would expect.

However after about a minute of system uptime, I see the following behavior until I reset the processor:

time_in_us: 3184
assert_time: 3856154728
deassert_time: 3856358507
k_assert_time: 64802
k_deassert_time: 64811

time_in_us: 3059
assert_time: 3858003423
deassert_time: 3858199205
k_assert_time: 64947
k_deassert_time: 64956

I have verified on my oscilloscope that that the pulse widths are still roughly 8400 microseconds and the k_uptime_get values confirm this, but the timing_cycle values are not correct.

I have tried many different combinations of using the timing functions but continue to see the same behavior.

Please advise. Thank you.

Related