This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRFX RTC Driver - How to stop compare interrupt handler disabling interrupts

I'm using the nrfx_rtc drivers on RTC2 to generate a regular interrupt once a second, using compare interrupts.

My problem is that the nrfx_rtc interrupt handler disables compare events and interrupts, so the interrupt only happens once. I want it to repeat by clearing the counter in the compare interrupt handler.

See nrfx_rtc.c irq_handler() which calls nrf_rtc_event_disable() and nrf_rtc_int_disable()

I can work around it by putting the following in the NRFX_RTC_INT_COMPARE0 handler

      NRF_RTC2->EVTENSET = (1UL << 16);
      NRF_RTC2->INTENSET = (1UL << 16);

but this is a real cludge, bypassing nrfx drivers. How should I do this properly, using nrfx drivers?

I'm using nRF52840 (PAN1780 module), SDK 17.0.2, Nordic SES 5.34a

Many thanks

Parents
  • Just to clarify, I am using a compare interrupt, and clearing the counter in the interrupt handler, so it should repeat. However the nrfx_rtc.c irq_handler() calls nrf_rtc_event_disable() and nrf_rtc_int_disable(), so I have to re-enable them in the interrupt handler

    Here's my init code

       nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
       config.prescaler = 4095;  // gives 8Hz (32kHz/(prescaler + 1)) - note 12 bit so this is max prescaler value
       err_code = nrfx_rtc_init(&rtc_inst, &config, rtc_handler);
       APP_ERROR_CHECK(err_code);
       err_code = nrfx_rtc_cc_set(&rtc_inst, 0, 8, true);    // Compare counter 
       APP_ERROR_CHECK(err_code);
       nrfx_rtc_enable(&rtc_inst);

    and my interrupt handler (with cludge)

    static void rtc_handler(nrfx_rtc_int_type_t int_type)
    {
       if (int_type == NRFX_RTC_INT_COMPARE0)
       {
          nrfx_rtc_counter_clear(&rtc_inst);        // clear counter
          NRF_RTC2->EVTENSET = (1UL << 16);         // cludge to re-enable event and interrupt
          NRF_RTC2->INTENSET = (1UL << 16);
          // 1 second tick timers....
          if (ben_timer)
             ben_timer--;
       }
    }

    My question is how I do this properly, either by persuading the nrfx driver to not disable interrupts, or by re-enabling them each time using nrfx calls rather than my cludge

    I must admit, this seems a really common application (generating a repeating 1 second interrupt), and I was a bit surprised that the nrfx driver behaves this way

Reply
  • Just to clarify, I am using a compare interrupt, and clearing the counter in the interrupt handler, so it should repeat. However the nrfx_rtc.c irq_handler() calls nrf_rtc_event_disable() and nrf_rtc_int_disable(), so I have to re-enable them in the interrupt handler

    Here's my init code

       nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
       config.prescaler = 4095;  // gives 8Hz (32kHz/(prescaler + 1)) - note 12 bit so this is max prescaler value
       err_code = nrfx_rtc_init(&rtc_inst, &config, rtc_handler);
       APP_ERROR_CHECK(err_code);
       err_code = nrfx_rtc_cc_set(&rtc_inst, 0, 8, true);    // Compare counter 
       APP_ERROR_CHECK(err_code);
       nrfx_rtc_enable(&rtc_inst);

    and my interrupt handler (with cludge)

    static void rtc_handler(nrfx_rtc_int_type_t int_type)
    {
       if (int_type == NRFX_RTC_INT_COMPARE0)
       {
          nrfx_rtc_counter_clear(&rtc_inst);        // clear counter
          NRF_RTC2->EVTENSET = (1UL << 16);         // cludge to re-enable event and interrupt
          NRF_RTC2->INTENSET = (1UL << 16);
          // 1 second tick timers....
          if (ben_timer)
             ben_timer--;
       }
    }

    My question is how I do this properly, either by persuading the nrfx driver to not disable interrupts, or by re-enabling them each time using nrfx calls rather than my cludge

    I must admit, this seems a really common application (generating a repeating 1 second interrupt), and I was a bit surprised that the nrfx driver behaves this way

Children
  • I was a bit suprised to see it implemented like this too. Typically you have to explitely disable interrupts when using the nRFX drivers. I will report this internally and ask if there is a particular reason for disabling the interrupt from the IRQ handler.

    benmack said:
    I must admit, this seems a really common application (generating a repeating 1 second interrupt), and I was a bit surprised that the nrfx driver behaves this way

     It's very common, but we generally recommend using the app timer library on top the RTC driver for this (Timer library). Is that something you have considered for your application?

  • Thanks Vidar, much appreciated :-)

    I did look at the app_timer stuff, but to be honest I struggled with the extra layer of abstraction. I'm an old school low-level programmer, much happier dealing direct with hardware registers...

    Cheers, Ben

  • I understand, it can be nice to work closer to the HW sometimes Slight smile The benefit of the timer library is that it makes it easy to set up multiple periodic and one-off timer interrupts with just a single RTC instance. However, in this case, when you only need one periodic interrupt source, it should be easy enough to just work directly with the driver.

    I haven't heard back from the driver team yet, but I think another approach you can use it to re-enable the interrupt from your application callback. This way you don't have to patch the driver code.

    /** @brief: Function for handling the RTC0 interrupts.
     * Triggered on TICK and COMPARE0 match.
     */
    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
        uint32_t err_code; 
    
        if (int_type == NRF_DRV_RTC_INT_COMPARE0)
        {
            nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
            
            nrf_drv_rtc_counter_clear(&rtc);
            err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 8,true);
            APP_ERROR_CHECK(err_code);
        }
    }

    Cheers,

    Vidar

  • Hi Vidar, thanks for that

    I did try that, but it is a heavy bit of code to call in every interrupt

    Call me old-school but I think I'll stick with my direct register writes for now, and hope they tweak the drivers in the future.

    Thanks again

  • Hi,

    I understand the concern , but I believe the overhead of re-enabling the interrupt from the driver callback should be negligible considering the CPU is running at 64 MHz. That said, I don't foresee any problems with patching the driver like you did either, it should be fine. I will update the thread once I hear back from the team.

Related