[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [avr-gcc-list] interrupts and signals (again)

From: Larry Barello
Subject: RE: [avr-gcc-list] interrupts and signals (again)
Date: Sat, 26 Mar 2005 09:07:30 -0800

Priority only matters when two or more interrupts are pending when the I bit
is set.  If both SIG_SPI and SIG_OVERFLOW1 are pending, then when you enable
global interrupts, SIG_OVERFLOW1 will be executed, the flag reset and the I
bit cleared.  When you set the I bit (either as the first instruction of an
INTERRUPT routine, or iret or explicitly) the next pending interrupt will
occur regardless of what your code is doing.

Enabling interrupts in an interrupt routine can be powerful, but it also can
be a waste of time.  You have to understand what is happening.  Since all
interrupt routines must complete, sometimes it is best to just let them
complete before enabling global interrupts.  However, there are other
equally valid situations where one interrupt routine takes a long time to
process (for whatever reason) and another one needs to be speedy.  in that
case the first one should re-enable interrupts while it is busy (perhaps
masking off it's own interrupt source, or maybe just tracking the number of
interrupts with a counter so it can unwind properly).

For example: I have a servo with interrupt driven encoders, serial I/O, ADC
and a timer.  The encoder inputs are hand coded and written as SIGNALS -
they need to be very fast (~ 2x50k interrupts/sec on an 8mhz AVR...).
Essentially all other interrupts have to be run as INTERRUPT to prevent
delaying the encoders as they have to be able to respond within 2-3 us of
each interrupt in order to function properly.  They take only 5us to execute
for each tick.

The timer routine ticks over at 1ms, but runs tasks every 10 and 100 ticks.
Those tasks can take a long time (particularly when encoders are moving fast
:), so I run it as INTERRUPT so the 1ms ticker can keep on ticking while the
tasks are running.  I have a flag to prevent it from re-running the 10
and/or 100ms tasks while it is running them - that would be a disaster!  The
ADC is also run as INTERRUPT.  The ADC and Timer stuff is normal C code.

Finally the serial I/O stuff is pretty zippy, but can't be run as INTERRUPT
since the code needs to clear the interrupt (read/write data) before
enabling the I bit.  I could run them as SIGNAL and re-enable global
interrupts just after masking the source of the serial interrupt (DATA,
RECV), but I had to hand code; if you look at the generated code for SIGNAL
the soonest you can re-enable interrupts is after all the registers are
saved which is way too slow for my encoders.  So I wrote my own.  Note the
entire routine, except for the first two lines, runs with the global
interrupts enabled for a total interrupt latency of about 8 cycles (1us)
(INTERRUPT latency is 7 cycles, SIGNAL latency is on the order of 20-30
cycles).  Latency is NOT the total time to run, just the time the interrupts
are off.

        cbi     _SFR_IO_ADDR(UCR), UDRIE
        push    R20
        in      R20, _SFR_IO_ADDR(SREG)
        push    R1
        clr     R1              ; R0 = 0 register
        push    R24
        push    R25
        push    R26
        push    R27
        push    R30
        push    R31
        ldi     R24, lo8(TxBuf)
        ldi     R25, hi8(TxBuf)
        rcall   PullFifo        ; ret -1 when empty
        cpi     R25, 0xFF
        breq    1f
        out     _SFR_IO_ADDR(UDR), R24
        sbi     _SFR_IO_ADDR(UCR), UDRIE
        pop     R31
        pop     R30
        pop     R27
        pop     R26
        pop     R25
        pop     R24
        pop     R1
        out     _SFR_IO_ADDR(SREG), R20
        pop     R20

Hope this gives you some good ideas!

-----Original Message-----
From: address@hidden
[mailto:address@hidden Behalf
Of Jamie Morken
Sent: Friday, March 25, 2005 11:39 PM
To: avr-gcc-list
Subject: Re: [avr-gcc-list] interrupts and signals (again)


I just checked that an INTERRUPT can be interrupted by any other interrupt
or signal, no matter its priority.. so this must mean that the INTERRUPTS
mask bit is being cleared when the ISR is entered.  I think it would be a
good idea to be able to clear the interrupts mask bit when the ISR completes
as well.. that way maybe only ISR's with higher priority would be able to
interrupt it.  Or maybe I am on the wrong track here..


reply via email to

[Prev in Thread] Current Thread [Next in Thread]