Using avr-gcc 4.8.0 and avr-libc 1.8.0 on Arch Linux. Trying to get UART RX interrupts working on an ATtiny2313 with this simple code which should echo the received byte:

#define F_CPU 14745600

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define USART_BAUDRATE 9600 
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

int main(){
  DDRD |= _BV(PD6);

  UCSRB = (1 << RXEN) | (1 << TXEN);
  UCSRC = (1 << UCSZ0) | (1 << UCSZ1);


  UCSRB |= (1 << RXCIE);

  for (;;){ 
    PORTD ^= _BV(PD6);

  return 0;

   char b;
   b = UDR;
   UDR = b;

I upload this with avrdude and the LED fails to pulse. If I comment out the ISR, it works as I'd expect it to. UART polling also works normally, so I'm quite sure that it is configured correctly. I've been able to reproduce this with an ATmega162 and an ATmega328p.

Other strange behavior: if I compile without optimization, the LED will pulse until I send a byte, then it stops pulsing.

I've really got no idea where the problem lies as every tutorial I've seen uses almost this exact code.

  • \$\begingroup\$ Do you need to clear the interrupt flag inside the ISR? You might be stuck in an interrupt loop. \$\endgroup\$
    – Samuel
    Commented Oct 16, 2013 at 2:45
  • \$\begingroup\$ @Samuel: The interrupt flag is automatically cleared when UDR is read. However, maybe something with the optimization goes wrong and UDR is not read? Andrew: What happens if you comment out "UDR = b"? \$\endgroup\$
    – Rev
    Commented Oct 16, 2013 at 7:47
  • \$\begingroup\$ Check avr-gcc version 4.7.2. I have trouble finding a reference for latest stable version of avr-gcc, but most sources I checked are still on 4.7.2. \$\endgroup\$
    – jippie
    Commented Oct 16, 2013 at 8:44
  • \$\begingroup\$ @Rev1.0: Same thing. I can comment out all three lines inside the ISR, but as long as there's an ISR defined, the problem still occurs. \$\endgroup\$
    – Andrew
    Commented Oct 16, 2013 at 12:50
  • \$\begingroup\$ @jippie: I was afraid of that. Gonna try to compile 4.7.2 and see what happens. \$\endgroup\$
    – Andrew
    Commented Oct 16, 2013 at 12:51

1 Answer 1


I hate myself for this. How I was compiling:

avr-gcc -o build/src/main.o -c -Wall -g -Os -mmcu=attiny2313 src/main.c 
avr-gcc -o build/main.elf build/src/main.o

How I should have been:

avr-gcc -o build/src/main.o -c -Wall -Os -mmcu=attiny2313 -std=c99 -ffunction-sections -fdata-sections src/main.c
avr-gcc -o build/main.elf -mmcu=attiny2313 build/src/main.o

The actual culprit was not passing the -mmcu flag to the linker, but adding -ffunction-sections and -fdata-sections also cured some weird problems I was having when using external header files.

  • \$\begingroup\$ GLad to hear you fixed it. But I would investigate why using "-ffunction-sections and -fdata-sections" just "cured some weird [other] problems". Maybe due to code size? Because the linker is able to remove unused functions (sections) this way. \$\endgroup\$
    – Rev
    Commented Oct 16, 2013 at 19:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.