I'm trying to create a program that uses timer0 to fire off an interrupt every 70 microseconds and timer1 to fire off an interrupt every 60 microseconds. I'm using a 100Mhz system clock with a prescaler of 4 to end up with timer ticks being worth 40nS. In addition, autoreload is enabled for both timers.
The problem is, that despite section 1.6.3 of SPRUFX5D (System Guide) stating that if two timer interrupts occur simultaneously and the ISR decides to service one at a time (subsequently clearing the appropriate flag in TIAFR one at a time, the ISR should immediately fire again to service the remaining timers.
What I'm seeing is that my 70uS timer 0 is periodically being missed. Specifically, the code under the conditional statement seeing if TIAFR bit 0 is set is not executing. I've verified this by toggling a GPIO line in the ISR and periodically watching the missed pulses on an o-scope. In addition, if I increase the frequency of timer1, the likelihood increases that the timer0 code won't execute. Subsequently, lowering the timer1 frequency decreases the misses of timer 0.
The following is my ISR, with the non relevant parts removed. It seems that in the scenarios where timer 0 & 1 are firing simultaneously, the timer 0 flag isn't getting set/staying latched in the TIAFR or perhaps the ISR isn't being re-entered upon completion of timer 1 execution.
Any and all assistance is greatly appreciated. It's not clear, based on the documentation, why timer0 shouldn't be serviced each and every time in this ISR. I would at least expect to see some skew in the pulses if my timer1 code was too long, but not a complete miss of timer0.
Thanks!
Adam
-----------------------------------------------------------------------------------------------------------------------------------------------------
#define TIM_TIAFR_TIM0_BIT 0x0001
#define TIM_TIAFR_TIM1_BIT 0x0002
#define REG_TIAFR *(volatile ioport uint16_t*)(0x1c14)
interrupt void timer_isr(void)
{
uint16_t register_value = 0;
register_value = REG_TIAFR;
if(register_value & TIM_TIAFR_TIM0_BIT)
{
/* Clear Timer 0 flag in Timer Aggregate flag register*/
REG_TIAFR |= TIM_TIAFR_TIM0_BIT;
GPIO_IODATAOUT1 |= 0x0004; //For debugging
//******* do 1uS of work (setting flags, updating variables, etc) *******
GPIO_IODATAOUT1 &= ~0x0004; //For debugging
}
if(register_value & TIM_TIAFR_TIM1_BIT)
{
/* Clear Timer 1 flag in Timer Aggregate flag register*/
REG_TIAFR |= TIM_TIAFR_TIM1_BIT;
//******* do 1uS of work (setting flags, updating variables, etc) *******
}
}