avr-gcc-list
[Top][All Lists]
Advanced

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

Re: [avr-gcc-list] patch to fix unbalanced 'cli' that causes interrupts


From: Marek Michalkiewicz
Subject: Re: [avr-gcc-list] patch to fix unbalanced 'cli' that causes interrupts to always be disabled
Date: Sun, 1 Dec 2002 16:48:41 +0100 (CET)

Hi,

> While trying to create an interrupt based uart driver for an AVR mega128 I
> discovered that interrupts were being turned off, almost randomly
> throughout the code. After objdump'ing the image I observed dozens of cli
> (global interrupt disable) opcodes. The cli opcodes are inserted prior to
> SP (stack pointer) modification by gcc to prevent an interrupt from
> corrupting the stack (which is not done atomically due to the 16 bit SP
> being accessed a byte at a time, a limitation of the AVR). The problem is
> that gcc doesn't always balance the cli with an sei (global interrupt
> enable). This patch balances the cli by ensuring that a sei is inserted
> after the SP modification whenever a cli was inserted. My application now
> works as expected.

It is not a bug that cli/sei are not balanced - before cli, SREG (which
includes the I flag) is saved to a temporary register, later restored.
Enabling interrupts unconditionally is wrong if they were not enabled
before the SP modification.

It is also not a bug that SREG is restored one instruction too early -
setting the I flag takes effect only after the next instruction, so we
get the shortest possible interrupt latency.  This fact was not clearly
documented by Atmel until recently, but all devices work this way.

So, the following code (without "sei") generated by GCC is correct:

        in r0,SREG
        cli
        out SPH,r29
        out SREG,r0
        out SPL,r28

Of course, if you can show a specific example of incorrect code
(interrupts disabled, and not restored later to previous state),
by all means please let me know.

Hope this helps,
Marek

avr-gcc-list at http://avr1.org



reply via email to

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