[Top][All Lists]
[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