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

Two timers with same value

Is it possible to have 2 timers (TIMER3 and TIMER4) with the exact  timer value? 

I need to have two gpios toggeling at a difference time frequency but based on the same clock. How can I update the value of a timer arbitrarly or how can I have two timers with the same value? 

This question is related with: https://devzone.nordicsemi.com/f/nordic-q-a/53417/two-different-cc-timer-for-2-gpio-tasks 

Thanks!

  • Hi

    It should be possible to have two timers running with the same timer value, yes, but I don't understand why that is necessary. 

    If the two GPIO's should toggle at different time frequencies wouldn't the two timers need to have different reload values?

    If they have different reload values the timers will eventually run out of sync, even if you start them at the same time. 

    What will the two pins be used to control?

    Best regards
    Torbjørn

  • Let's say that i want to used TIMER3, and i want to enable two counters to toggle two gpios. 

    If i used the next code: 

    nrf_ppi_channel_endpoint_setup(  NRF_PPI_CHANNEL2,  (uint32_t) nrf_timer_event_address_get(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE4), nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_3));
        nrf_ppi_channel_enable(NRF_PPI_CHANNEL2); 
        
        nrf_ppi_channel_endpoint_setup(   NRF_PPI_CHANNEL3, (uint32_t) nrf_timer_event_address_get(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE0), nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_4));
          nrf_ppi_channel_enable(NRF_PPI_CHANNEL3);        
      
        NRF_TIMER3->TASKS_STOP  = 1;
        NRF_TIMER3->TASKS_CLEAR = 1;
        NRF_TIMER3->PRESCALER   = 0;
        NRF_TIMER3->BITMODE     = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
        NRF_TIMER3->CC[0]       = 2000;
        NRF_TIMER3->CC[4]       = 4000 ;
    
        NRF_TIMER3->SHORTS     = TIMER_SHORTS_COMPARE4_CLEAR_Msk ;
        NRF_TIMER3->SHORTS     |= TIMER_SHORTS_COMPARE0_CLEAR_Msk;
        
        NRF_TIMER3->TASKS_START = 1;  

    With the above code, it will always count up to 2000 (NRF_TIMER_EVENT_COMPARE0) and restart again, the NRF_TIMER_EVENT_COMPARE4 will never happen.

    Therefore i want to have a TIMER4 with the exact same value as TIMER3 and putting there another compare event so both events can happen. Is there any smarter way of doing this? 

    Thanks!

  • Hi 

    What is the smallest interval in microseconds that you need to update the pins?

    If the pins need to be updated very quickly then setting up two separate timers is probably the best option. Then you can assign them different CC values, and have them run independently of each other. 

    If the CC value of one timer is the multiple of the other, and you want to run them synchronized, you can use a PPI channel to have the compare event of one timer clear the other timer so that they will both be cleared at the same time. 

    If the pins don't need to be updated very often then it is also possible to use the timer in a free running mode, and simply update the value of the CC register for every event in an interrupt handler, similar to this:

    void TIMER3_IRQHandler(void)
    {
        if(NRF_TIMER3->EVENTS_COMPARE[0])
        {
            NRF_TIMER3->EVENTS_COMPARE[0] = 0;
            NRF_TIMER3->CC[0] += 2000;
        }
        if(NRF_TIMER3->EVENTS_COMPARE[4])
        {
            NRF_TIMER3->EVENTS_COMPARE[4] = 0;
            NRF_TIMER3->CC[4] += 4000;
        }
    }

    For this to work you have to remove the CAPTURE -> CLEAR shortcut, so that the timer doesn't reset when you hit the compare value, but keeps running. 

    The drawback of this method is that you need to respond to a short interrupt for every pin toggle, but the advantage is that you only need a single hardware timer module, and you could in theory control as many pins as you have CC registers. 

    Best regards
    Torbjørn

  • Unfortunately, this approach does not work for my case, I need to find a way that TIMER4 has the same value as TIMER3. I'm using a timer synchronization, therefore, every 2.5ms TIMER3 is modified, clearing tasks and compare events on TIMER3 .

    If you could help me to find a way to have TIMER4 exact as TIMER3, I could use any compare event on TIMER4 without the changes in the sync method.

  • Hi,

    you can do this with PPI, for example

    NRF_PPI->CH[0].EEP = (uint32_t) &NRF_EGU0->EVENTS_TRIGGERED[0];
    NRF_PPI->CH[0].TEP = (uint32_t) &NRF_TIMER3->TASKS_START;
    NRF_PPI->FORK[0].TEP = (uint32_t) &NRF_TIMER4->TASKS_START;
    NRF_PPI->CHENSET = (1 << 0);

    then start both timers by one task:

    NRF_EGU0->TASKS_TRIGGER[0] = 1;

Related