I need to execute a procedure at constant time intervals. The procedure takes a long to execute and during that time other interrupt must be active. Also, it is critical that the procedure is executed at each timer overflow.
Take a look at this pseudo-code:
ISR(timer_overflow)
{
timer_flag = 1;
}
main_loop()
{
if (timer_flag)
{
long_time_consuming_procedure();
timer_flag = 0;
}
(* if a timer interrupt fires here, will the procedure be executed? *)
sleep();
}
If the above won't work, will the below code make things rock-solid?
main_loop()
{
cli();
if (timer_flag)
{
sei();
long_time_consuming_procedure();
timer_flag = 0;
}
sei();
sleep();
}
Or maybe this will be better, as other interrupt are handled very quickly:
ISR(timer_overflow)
{
sei();
long_time_consuming_procedure();
}
main_loop()
{
sleep();
}
I'm using avr-gcc
EDIT
Looks like I shared too little detail. I'm afraid of this worst-case scenario:
- some interrupt (other than timer overflow) wakes up the uc
- long_time_consuming_procedure is not called as there was no timer overflow
- just before the moment cpu goes back to sleep (betwen
if (timerflag)
andsleep()
) the timer overflows - timer interrupt is executed correctly
- after returning from ISR cpu goes to sleep without executing
long_time_consuming_procedure
, because we've already passedif (timerflag)
- there are no other interrupts in the following timer cycle, thus cpu is woken up after the next overflow
This way there are two timer interrupts and only one long_time_consuming_procedure
execution. There is a very small chance for that to happen, but if something can go wrong it'll go even worse.