[En-Nut-Discussion] AT91SAM7X256 TC1 Timer being disabled

Coleman Brumley cbrumley at gopolar.com
Fri Jul 10 20:03:35 CEST 2009


Tim,

Thank you.  I'm testing this code now in my application...so far so good.  

The last test took almost 12 hours to fail though, so I won't know for sure
until tomorrow.

- Coleman


> -----Original Message-----
> From: en-nut-discussion-bounces at egnite.de [mailto:en-nut-discussion-
> bounces at egnite.de] On Behalf Of Timothy M. De Baillie
> Sent: Friday, July 10, 2009 12:13 PM
> To: Ethernut User Chat (English)
> Subject: Re: [En-Nut-Discussion] AT91SAM7X256 TC1 Timer being disabled
> 
> 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




More information about the En-Nut-Discussion mailing list