[En-Nut-Discussion] AT91SAM7X256 TC1 Timer being disabled
Bernd Walter
enut at cicely.de
Sun Jul 12 19:19:54 CEST 2009
On Sun, Jul 12, 2009 at 11:37:55AM -0400, Coleman Brumley wrote:
>
> > I fail to see how a missed interrupt can lead to timer stopping.
>
> What was really peculiar was not only did the TC1 interrupt stop, but also
> the TC0 interrupt which is the main Nut/OS timer. This, of course, was
> REALLY bad and caused all sorts of other cascading failures (threads failing
> to execute, etc.).
Strange.
> > This sounds like a design failure somewhere else.
>
> The version posted by Timothy works as expected, i.e. the timer interrupt
> doesn't stop working. This version has now been running for almost 48 hours
> without fail, whereas the sample posted at
> http://www.ethernut.de/en/documents/at91-timer-irq.html, which is what my
> code was using fails usually after a couple of hours.
>
> The only differences between the two register functions are:
>
> -/* Select divider and compare trigger */
> -outr(TC1_CMR, TC_CLKS_MCK32 | TC_CPCTRG);
>
> +/* Select divider and compare trigger */
> +outr(TC1_CMR, TC_CLKS_MCK32);
>
> -/* set to lowest priority (0) */
> -NutIrqSetPriority(&sig_TC1, 0);
>
> +/* set to highest priority (7) */
> +NutIrqSetPriority(&sig_TC1, 7);
>
> And, there's the addition of the code to increment the compare register in
> the handler:
>
> +//increase compare value to next interrupt value
> +//(signed short allows for overflow wrapping)
> +#ifndef NUT_TICK_FREQ
> +#define NUT_TICK_FREQ 1000UL
> +#endif
> +#if defined(AT91_PLL_MAINCK)
> + #define COMPARE_ADDER (At91GetMasterClock() / (32 * NUT_TICK_FREQ))
>
> +#else
> + #define COMPARE_ADDER (NutGetCpuClock() / (32 * NUT_TICK_FREQ))
> +#endif
> + compare_value += COMPARE_ADDER;
> + outr(TC1_RC, compare_value); //new compare value
>
> > Reenabling interrupts adds more complexity, because interrupt routines
> > are not safe to modify global tables anymore - e.g. for posting an
> > event.
>
> It's seems like this bug is in IRQ_ENTRY and IRQ_EXIT for the ARM7. I'm not
> an ARM assembly expert by any means, so this was out of my realm of comfort
> for trying to address.
There is nothing unusual.
It just does the normal things.
Save/restore some values and notify the AIC about processing.
I wonder if NutRegisterIrqHandler() registers level or edge.
I personally don't use it in my code and always register level, unless I
have special external hardware to care about.
Edge interrupts are always sensible to handle.
On the other hand: TC0 is a different vector than TC1, so it shouldn't
stop if you lock out TC1 interrupt.
But I never used an ARM TC for interrupts.
I've only used TC to generate external clocks.
I use a timer for RS485 on AVR, but since the ARM USART can handle
timeouts themself I had no use for my own timer interrupt anymore.
So far all interrupt rpbolems turned out to be my fault.
--
B.Walter <bernd at bwct.de> http://www.bwct.de
Modbus/TCP Ethernet I/O Baugruppen, ARM basierte FreeBSD Rechner uvm.
More information about the En-Nut-Discussion
mailing list