[En-Nut-Discussion] AT91SAM7X256 TC1 Timer being disabled
Timothy M. De Baillie
debaillie at ciholas.com
Fri Jul 10 18:12:41 CEST 2009
Coleman Brumley wrote:
> What I'm finding, though, is that after some amount of time (several hours,
> for instance) the TC1 interrupt is being disabled. If I toggle a PIO pin in
> TC1TimerIntr and the app gets in this state, then the PIO pin is not longer
> being toggled. I can find no reference to NutIrqDisable for sig_TC1 in the
> code though.
>
>
>
> Has anyone else come across this type of scenario? I'm using Nut/OS v4.6.4.
>
This is a problem we have seen on many occasions. The problem lies in
that Ethernut does not allow re-entrance of IRQs. If you are to get two
interrupts on your timer before you are able to handle them, then it
causes the timer to just stop.
The REAL solution is to rewrite the IRQ_ENTRY and IRQ_EXIT to allow for
re-entrance of IRQs (and not disable IRQs).
Our temporary solution involves using a wrapping timer instead of a
resetting timer. Additionally, if the timer's accuracy is highly
important, you should check for overflow and handle it (ie: two
interrupts before handler, should be detectable by amount in TC1_CV)
// CODE
#define COMPARE_ADDER 0xdc8
signed short compare_value = COMPARE_ADDER;
static void RealTimeClock(void *arg){
local_clock++;
//you could check for overflow here
//increase compare value to next interrupt value
//(signed short allows for overflow wrapping)
compare_value += COMPARE_ADDER;
outr(TC1_RC, compare_value);
}
void InitTimer1(void){
//change the AIC to allow handle of TC1 interrupt
outr(AIC_IECR, _BV(TC1_ID));
//enable timer1 clock
outr(PMC_PCER, _BV(TC1_ID));
//disable the timer
outr(TC1_CCR, TC_CLKDIS);
//disable interrupts on the timer
outr(TC1_IDR, 0xFFFFFFFF);
//reading the status register will clear any pending interrupt
inr(TC1_SR);
//Select MCK/32, inc on + edge (45.1584MHz/32 = 1.4112MHz)
outr(TC1_CMR, TC_CLKS_MCK32);
//set compare value to 2.50ms (.0025 * 1411200) = 3528 (0xdc8)
outr(TC1_RC, COMPARE_ADDER);
//enable the timer
outr(TC1_CCR, TC_CLKEN);
//enable the rc compare interrupts
outr(TC1_IER, TC_CPCS);
//register the interrupt
NutRegisterIrqHandler(&sig_TC1, RealTimeClock, 0);
//set to highest priority (7)
NutIrqSetPriority(&sig_TC1, 7);
//enable the interrupt
NutIrqEnable(&sig_TC1);
//reset the counter and start the clock
outr(TC1_CCR, TC_SWTRG);
}
//END CODE
Hope this helps,
Tim DeBaillie
More information about the En-Nut-Discussion
mailing list