Go Down

Topic: Timer Slow Start (using DueTimer) (Read 1 time) previous topic - next topic

mpex2006km

Hi to all, first time to write here (so prepare for newbie question). My problem is that if I use
Code: [Select]
Timer3.start(100); the function called by timer3 is called after 100us.

Now if I try to use two timers
Code: [Select]
Timer3.start(100);
Timer4.start(1000);
the function (timer3 callback) now is delayed by hundreds of us.

Now to be clear the callback functions of both of them are empty so no time spent there.
Konstantinos Beltsios
------------------------------------------------------
DIY fanatic

ard_newbie

#1
Jun 17, 2017, 04:30 pm Last Edit: Jun 17, 2017, 04:32 pm by ard_newbie
Use tc_lib from antodom or explore the Timer Counter section of Sam3x datasheet from page 856 to understand this snippet:

Code: [Select]

uint8_t led = LED_BUILTIN;
volatile boolean ledon;

int FREQ_1Hz = 1;

void TC3_Handler(){
    TC_GetStatus(TC1, 0);  // Read status register to clear it in order to
                           // repeat the call to Handler
    digitalWrite(LED_BUILTIN, ledon = !ledon);  
}

void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency){
  
      //Power ON the specified peripheral.
    pmc_enable_periph_clk((uint32_t)irq);  
    
    TC_Configure(tc, channel, TC_CMR_WAVE|TC_CMR_WAVSEL_UP_RC|TC_CMR_TCCLKS_TIMER_CLOCK4);
    uint32_t rc = VARIANT_MCK/128/frequency;
    
    TC_SetRA(tc, channel, rc/2);  // ra can be anything in between 1<ra<rc
    TC_SetRC(tc, channel, rc);    // F = 84000000/128/656250 Hz = 1 Hz
    TC_Start(tc, channel);
    
    tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPCS;
    
    NVIC_EnableIRQ(irq);
}

void setup() {
    pinMode(led, OUTPUT);
    Serial.begin(9600);
    // TC1 means Timer Counter 1
    // and Timer Counter 1 channel 0 is linked to TC3_Handler()
    startTimer(TC1, 0, TC3_IRQn, FREQ_1Hz);    
}



mpex2006km

Use tc_lib from antodom or explore the Timer Counter section of Sam3x datasheet from page 856 to understand this snippet:

Code: [Select]

uint8_t led = LED_BUILTIN;
volatile boolean ledon;

int FREQ_1Hz = 1;

void TC3_Handler(){
    TC_GetStatus(TC1, 0);  // Read status register to clear it in order to
                           // repeat the call to Handler
    digitalWrite(LED_BUILTIN, ledon = !ledon); 
}

void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency){
 
      //Power ON the specified peripheral.
    pmc_enable_periph_clk((uint32_t)irq); 
   
    TC_Configure(tc, channel, TC_CMR_WAVE|TC_CMR_WAVSEL_UP_RC|TC_CMR_TCCLKS_TIMER_CLOCK4);
    uint32_t rc = VARIANT_MCK/128/frequency;
   
    TC_SetRA(tc, channel, rc/2);  // ra can be anything in between 1<ra<rc
    TC_SetRC(tc, channel, rc);    // F = 84000000/128/656250 Hz = 1 Hz
    TC_Start(tc, channel);
   
    tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPCS;
   
    NVIC_EnableIRQ(irq);
}

void setup() {
    pinMode(led, OUTPUT);
    Serial.begin(9600);
    // TC1 means Timer Counter 1
    // and Timer Counter 1 channel 0 is linked to TC3_Handler()
    startTimer(TC1, 0, TC3_IRQn, FREQ_1Hz);   
}



I will look at this lib later tonight .
Thank you very much
Konstantinos Beltsios
------------------------------------------------------
DIY fanatic

mpex2006km

Ok I am almost read everything and I tried much without any luck. To explain what I want to do. I have an input pin and when this input is pulsed low an interrupt function is called. The function must calculate two delay times and call another two functions. Both functions must be called at the specific so delay and/or if(micros()>time+interval) does not work.

Now I use this code to trigger an interrupt from the input pin
Code: [Select]
attachInterrupt(digitalPinToInterrupt(pickup_pin), Pickup_Pulsed, RISING);

and I used this code to trigger the two output functions.

Code: [Select]
void Pickup_Pulsed () {
Timer4.start(calculated_delay_1);
Timer3.start(calculated_delay_0);
}


Any help is really welcomed.
Konstantinos Beltsios
------------------------------------------------------
DIY fanatic

ard_newbie


A few thoughts:

Write a flow chart of what your code should do, and then write a pseudo code mirroring your flow chart.

A good practice: make your ISRs as short as possible by setting only a few flags which will be processed within your loop() and run a finite state machine FSM.

See this tutorial for FSM implemenatation (use Google translate): http://forum.arduino.cc/index.php?topic=470879.0

If you call functions from inside an ISR, you will stay inside this ISR as long as your called functions are completed.
 
I wonder if you really need Timer counter interrupts (callback functions) to trigger some functions, certainly you could do that with micros() or millis().

mpex2006km

A good practice: make your ISRs as short as possible by setting only a few flags which will be processed within your loop() and run a finite state machine FSM.

This is why I didn't use any delay(). I want to just change the state of some pins without holding the processor back (which is what delay() does).


If you call functions from inside an ISR, you will stay inside this ISR as long as your called functions are completed.
I know that.

I wonder if you really need Timer counter interrupts (callback functions) to trigger some functions, certainly you could do that with micros() or millis().
I really need Timer counter because the timing of all the the pins are really important. I don't know of a method with micros() that will have a microsecond of absolute timing accuracy.
Konstantinos Beltsios
------------------------------------------------------
DIY fanatic

antodom

Hi there @mpex2006km,

Have a look to example action_test from tc_lib (available at https://github.com/antodom/tc_lib). It uses a tc_lib action_object, basically a function you can have called periodically using a hardware timer interrupt handler. As @ard_newbie mentions, the callback is called inside the interrupt handler, so the callback should be short and fast.

If in any doubt, just ask me.

I hope it helps.
------------
antodom

mpex2006km

Hi there @mpex2006km,

Have a look to example action_test from tc_lib (available at https://github.com/antodom/tc_lib). It uses a tc_lib action_object, basically a function you can have called periodically using a hardware timer interrupt handler. As @ard_newbie mentions, the callback is called inside the interrupt handler, so the callback should be short and fast.

If in any doubt, just ask me.

I hope it helps.
Hello and sorry for my late response but I am currently sitting exams. I will try to make it work with tc_lib and be sure (since I am a newbie) I will have a lot of stupid questions.

Thank you very much.
Konstantinos Beltsios
------------------------------------------------------
DIY fanatic

Go Up