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!

Parents
  • 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!

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

  • Hi 

    Dmitry's suggestion should do what you need. It will ensure that both timers start at exactly the same time. 

    You could also use this method to connect to the CLEAR task of the timers rather than the START task if the timers are running and you just want to reset them to 0. 

    When they are both reset they will obviously have the same value, and will run in sync from there (assuming the PRESCALER setting is identical). 

    Best regards
    Torbjørn

  • Whats is the meaning of this?

    NRF_PPI->CH[0].EEP = (uint32_t) &NRF_EGU0->EVENTS_TRIGGERED[0];

    I added something like this:

    NRF_PPI->CH[7].EEP   = (uint32_t)  &NRF_EGU3->EVENTS_TRIGGERED[0];
    NRF_PPI->CH[7].TEP   = (uint32_t) &NRF_TIMER4->TASKS_CLEAR;

    or should it be?

    NRF_PPI->CH[7].EEP   = (uint32_t)  &NRF_TIMER3->TASKS_CLEAR;
    NRF_PPI->CH[7].TEP   = (uint32_t) &NRF_TIMER4->TASKS_CLEAR;
    

  • Hi

    The whole purpose of the EGU in this example is to allow you to generate a hardware event indirectly from software. 

    The EGU is a relatively simple module that will set a hardware event every time the corresponding task is activated through software. 

    Essentially the NRF_EGU0->EVENTS_TRIGGERED[0] event will fire every time you activate the corresponding task like this:
    NRF_EGU0->TASKS_TRIGGER[0] = 1;

    The reason to do this is to allow the event to be connected to the PPI channel, so that two different tasks can be activated as a result of a single software command, without any delay between them.

    Your suggestion would not work as you are trying to assign a TASK to the event end point (EEP). The EEP is only for events and the TEP registers are for tasks.

    Best regards
    Torbjørn

Reply
  • Hi

    The whole purpose of the EGU in this example is to allow you to generate a hardware event indirectly from software. 

    The EGU is a relatively simple module that will set a hardware event every time the corresponding task is activated through software. 

    Essentially the NRF_EGU0->EVENTS_TRIGGERED[0] event will fire every time you activate the corresponding task like this:
    NRF_EGU0->TASKS_TRIGGER[0] = 1;

    The reason to do this is to allow the event to be connected to the PPI channel, so that two different tasks can be activated as a result of a single software command, without any delay between them.

    Your suggestion would not work as you are trying to assign a TASK to the event end point (EEP). The EEP is only for events and the TEP registers are for tasks.

    Best regards
    Torbjørn

Children
No Data
Related