[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