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

Issue with 2 hw timer interrupt collision

Hello, I am trying to use the timer peripheral via registers only, however I am running into issues when I setup two timers and they activate at the same time. Here are my interrupt handlers:

void TIMER1_IRQHandler(void)
{

NRF_TIMER1->EVENTS_COMPARE[0] = 0;
volatile uint32_t dummy = NRF_TIMER1->EVENTS_COMPARE[0];
(void)dummy;
event_handler_bank[0][0].event_handler(); //calls test_handler()
}

void TIMER2_IRQHandler(void)
{

NRF_TIMER2->EVENTS_COMPARE[0] = 0;
volatile uint32_t dummy = NRF_TIMER2->EVENTS_COMPARE[0];
(void)dummy;
event_handler_bank[1][0].event_handler(); //calls test_handler2()
}

The end goal is to allow for custom event handlers for each channel compare event, It appears to be that when the timers 'intersect', timer1's routine is performed twice which might be proven via this scope probing on the onboard leds:

The yellow trace is the led toggled from IRQ1's interrupt while the blue trace is the led toggled from IRQ2's itnerrupt.

However the strangest thing is that the lights will perform perfectly if I flash it a random amount of times with the exact same source code! Here is a trace whenever the lights/timer work as intended:

  

It seems that whenever the IRQ2 is triggered first it works fine but when IRQ1 is triggered first it get triggered twice.

I am really confused on how to reliably create a different callbacks from multiple timer instances. I looked through your HAL code and saw this snippet (from nrfx_timer.c) :

static void irq_handler(NRF_TIMER_Type        * p_reg,
                        timer_control_block_t * p_cb,
                        uint8_t                 channel_count)
{
    uint8_t i;
    for (i = 0; i < channel_count; ++i)
    {
        nrf_timer_event_t event = nrf_timer_compare_event_get(i);
        nrf_timer_int_mask_t int_mask = nrf_timer_compare_int_get(i);

        if (nrf_timer_event_check(p_reg, event) &&
            nrf_timer_int_enable_check(p_reg, int_mask))
        {
            nrf_timer_event_clear(p_reg, event);
            NRFX_LOG_DEBUG("Compare event, channel: %d.", i);
            p_cb->handler(event, p_cb->context);
        }
    }
}
I am confused as it seems I am really doing what is needed, clearing the event register and calling the custom callback. I would appreciate it if you guys could help me figure out what I am doing wrong. I have included the project folder I am using with the custom library calls, this folder was in the examples/peripheral directory in the sdk (i am using SES).
  • Hello,

    The first that I noticed was the compiler warning that said that you didn't have a type for y on line 61 in gpio.c. Please set it to e.g. uint8_t or uint32_t.

    It is actually not an interrupt issue. I ported your code to an example that had logging enabled, and the event handlers were called properly. The issue was in your function:

    // Set the output pin low
    void gpio_pin_clear(NRF_GPIO_Type *port, uint32_t pin_num)
    {
      port-> OUTCLR |= (1 << pin_num);
    }

    There is a space there between "port->" and "OUTCLR", but I don't think it caused any issues. Just wanted to let you know.

    The issue is the "|=". 

    I played around with the timer values, and noticed that whenever one pin is cleared (LED is turned on), both of them were turned on. The reason for this is that it takes some time to clear the OUTCLR register.

    Try to set it to:

    port->OUTCLR &= (1 << pin_num);

    So, we see that some people insist on using the registers directly, but we do have libraries for these kinds of tasks, that can save you a lot of time if you use them. I suggest that you consider it for the future Slight smile

    Best regards,

    Edvin

  • First of all thank you so much for helping me with this issue! You were right in that the issue was with the handling of the gpio registers. I changed it now to follow what the HAL does, which is just set the OUTSET and OUTCLEAR register equal to 1 << pinnum. Thanks again! PS. Ur libraries are good, I just like to know how it all works  Slight smile.

Related