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

  • 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.

  • I know this thread is old, but currently nrfx interrupts are working very well if you use the following procedure. It is not necessary to manually reenable. I have tried it across multiple NRF52 and NRF53 hardware with consistent results, including Nordic and 3rd-party boards. Under nrf connect v2.0.0, interrupts do not get disabled. Perhaps something strange is going on with your handler. Here is everything...it works, it's tested, and it's quite up to date.

    void timer_event_handler(nrf_timer_event_t event_type, void *p_context)
    {
       switch (event_type) {

         case NRF_TIMER_EVENT_COMPARE0:
    /*
     * Be aware that this event handler callback function, not just the ISR, runs in an
     * interrupt context, so some architectures may behave differently due to varying
     * implementations. Found this out when an led function on thingy52 wouldn't work
     * because a series of improvements had turned a gpio toggle into i2c operations
     * on the thingy52's sx_1509b, which would block, so I had to defer those operations
     * to mainline processing.
     */
              /* Do stuff, turn on light, etc. */
              // Uncomment next line if you implemented ONE-SHOT below, but want to resume timer anyway
              // nrfx_timer_resume(&timer);
              break;

         default:
              break;
       }
    }
    nrfx_err_t err;

    err = nrfx_timer_init(&timer, &config, &timer_event_handler);
    if (err != NRFX_SUCCESS) {
    printk("nrfx_timer_init failed! err = %d\n", err);
    }
    /*
     * The following macro is *NECESSARY* to get an operational timer.
     * If you do not enable this ISR, the timer will not appear to be working.
     * The IRQ_PRIO should match roughly what you set up in the config
     * struct of the init call above (default lowest is a good starting point).
     * Note that the irq name matches exactly the function defined in nrfx_timer.c
     * It seems like that part could have been canned in another macro
     * (maybe it is and I just overlooked it). Unless I set interrupts to true, my
     * function never got triggered, and unless I ran this connect, the default
     * callback never got connected--the system would just crash as soon as
     * my trigger value hit.
     */
    IRQ_CONNECT(TIMER0_IRQn, IRQ_PRIO_LOWEST,
    nrfx_timer_0_irq_handler, NULL, 0);

    /* STOP (with clear) in the MASK below gives a ONE-SHOT timer */
    /* CLEAR (alone) in the MASK gives a REPEATING timer */

    nrfx_timer_extended_compare(&timer,
    NRF_TIMER_CC_CHANNEL0,
    3500U, // Time in ticks, use one of the functions if you wish to pass microseconds or milliseconds
    // NRF_TIMER_SHORT_COMPARE0_STOP_MASK |  // Uncommenting this makes a ONE-SHOT timer
    NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
    true);
    nrfx_timer_clear(&timer);
    nrfx_timer_enable(&timer);

    ............

    Hope this helps someone.

Related