« Return to Thread: AT91SAM7X256 TC1 Timer being disabled

Re: AT91SAM7X256 TC1 Timer being disabled

by Tim DeBaillie :: Rate this Message:

Reply to Author | View in Thread

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
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion

 « Return to Thread: AT91SAM7X256 TC1 Timer being disabled