[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