This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Two interrupt events on TIMER0

Hi,

This may be a silly question but I'm trying to generate two timed interrupt events using only TIMER0 (the MCU is nrf51822). My code is:


#define TIMEOUT1 3000    //3s
#define TIMEOUT1 5000    //5s

  NRF_TIMER0->TASKS_STOP = 1;
  // Create an Event-Task shortcut to clear TIMER0 on COMPARE[0] event
  NRF_TIMER0->MODE        = TIMER_MODE_MODE_Timer;
  NRF_TIMER0->BITMODE     = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
  NRF_TIMER0->PRESCALER   = 4;  // 1us resolution

  NRF_TIMER0->TASKS_CLEAR = 1;               // clear the task first to be usable for later
  NRF_TIMER0->CC[0] = TIMEOUT1 * 1000; //first timeout
//  NRF_TIMER0->CC[1] = TIMEOUT2 * 1000;   //second timeout

  NRF_TIMER0->INTENSET    = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;
  /* Create an Event-Task shortcut to clear TIMER0 on COMPARE[0] event. */
  NRF_TIMER0->SHORTS      = (TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos);

The irq handler function then is: {code} void TIMER0_IRQHandler(void) { if( (NRF_TIMER0->EVENTS_COMPARE[0] != 0) && (NRF_TIMER0->INTENSET | (TIMER_INTENSET_COMPARE0_Set << TIMER_INTENSET_COMPARE0_Msk))) { NRF_TIMER0->EVENTS_COMPARE[0] = 0; } if( (NRF_TIMER0->EVENTS_COMPARE[1] != 0) && (NRF_TIMER0->INTENSET | (TIMER_INTENSET_COMPARE0_Set << TIMER_INTENSET_COMPARE0_Msk))) { NRF_TIMER0->EVENTS_COMPARE[1] = 0; } } {/code}

When I run the code, I only see an interrupt when TIMEOUT1 is met. I've probably misunderstood how the timer mechanism works. One theory I have is because I use the SHORTS, the counter is reset to 0 so only the first timeout is triggered followed by a counter reset repeatedly. I tried to disable SHORTS but then I noticed that an interrupt is triggered quite unpredictably and with long pauses. So the question is: is it possible to have TIMER0 triggering two interrupts at different intervals? If so then what am I doing wrong?

To solve my problem I use now TIMER0 and TIMER1 which works fine.

  • Hi,

    Tested your code, and it seems that you forgot to enable interrupt on COMPARE1. Here's my test code:

    
    void init_timer(void)
    {
        NRF_TIMER0->TASKS_STOP = 1;
        // Create an Event-Task shortcut to clear TIMER0 on COMPARE[0] event
        NRF_TIMER0->MODE        = TIMER_MODE_MODE_Timer;
        NRF_TIMER0->BITMODE     = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
        NRF_TIMER0->PRESCALER   = 4;  // 1us resolution
    
        NRF_TIMER0->TASKS_CLEAR = 1;               // clear the task first to be usable for later
        NRF_TIMER0->CC[0] = TIMEOUT1 * 1000; //first timeout
        NRF_TIMER0->CC[1] = TIMEOUT2 * 1000;   //second timeout
    
        NRF_TIMER0->INTENSET    = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;
        NRF_TIMER0->INTENSET    = TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos;
        /* Create an Event-Task shortcut to clear TIMER0 on COMPARE[0] event. */
        NRF_TIMER0->SHORTS      = (TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos);
        NRF_TIMER0->TASKS_START = 1;
    }
    
    int main(void)
    {
        NVIC_EnableIRQ(TIMER0_IRQn);
        init_timer();
        while(1);
    }
    
    void TIMER0_IRQHandler(void) 
    {
        if (NRF_TIMER0->EVENTS_COMPARE[0] != 0)
        {
            NRF_TIMER0->EVENTS_COMPARE[0] = 0;
        }
        if (NRF_TIMER0->EVENTS_COMPARE[1] != 0)
        {
            NRF_TIMER0->EVENTS_COMPARE[1] = 0;
        }
    }
    
    

    BR Håkon

  • It works now, good catch.

    Thanks! florin

  • Hmm, I'm afraid it still doesn't work... On the code above, try to change the timeouts to: #define TIMEOUT1 2000 //2s #define TIMEOUT2 10000 //10s

    Timeout1 should fire every 2s and TIMEOUT2 every 10s. What I observed is that Timeout2 fires first followed by Timeout1 after 2s, followed by 8s of pause. The cycle then repeats. Is this expected?

    Best, florin

  • Hi,

    This is to be expected. If you want them to fire every time, do like this in your interrupt: if (NRF_TIMER0->EVENTS_COMPARE[0] != 0) { static uint32_t cc_0 = TIMEOUT1 * 1000; cc_0 += TIMEOUT1 * 1000; NRF_TIMER0->CC[0] = cc_0; }

    And the same for CC[1].

    BR Håkon

  • NRF_TIMER0->SHORTS = (TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos);

    Why only clear the COMPARE1? Do COMPARE0 need be cleared?

    Do need add the code NRF_TIMER0->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); ?

Related