I'm having trouble getting input from a UART into a circular buffer and then out again. The circular buffer code is from <http://www.fourwalledcubicle.com/files/LightweightRingBuff.h>, which I've used successfully before, but not within an interrupt service. In this project I was able to get things working by polling the UART, but I realize now that I need to use interrupts. So, I rejiggered things to what I thought would work as an interrupt service, but I get nothing useful from `uart_getchar()`. With debugging `printf()s` I found that it gets called twice, but never actually returns.

Here's the minimal working example:

```
/* A proof of concept implementation of a command line on an AVR */
/*
 * Compile/build/program with:
 * avr-gcc -Os -DF_CPU=16000000UL -std=gnu99 -mmcu=atmega164p -o linetest.elf linetest.c
 * avr-objcopy -j .text -j .data -O ihex linetest.elf linetest.hex
 * avrdude -c usbtiny -p m164p -U flash:w:linetest.hex:i
 *
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

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

#define UART_BAUD 9600
#define BAUDRATE F_CPU/16/BAUD-1
#define BUFFER_SIZE 80

int uart_putchar(char, FILE *);
int uart_getchar(FILE *);
void uart_init(unsigned int);

typedef uint8_t rbuf_data_t;
typedef uint8_t rbuf_count_t;

typedef struct {
    rbuf_data_t buffer[80];
    rbuf_data_t *in;
    rbuf_data_t *out;
    rbuf_count_t    count;
} rbuf_t;

void rbuf_init(rbuf_t* const);
rbuf_count_t rbuf_getcount(rbuf_t* const);
bool rbuf_isempty(rbuf_t*);
void rbuf_insert(rbuf_t* const, const rbuf_data_t);
rbuf_data_t rbuf_remove(rbuf_t* const);

rbuf_t  rbuf;
char line[BUFFER_SIZE];
FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);

int main(void)
{
    int i;

    sei();
    uart_init(UART_BAUD);
    printf_P(PSTR("\n\nHello World!\nType a line and see it printed back.\n"));
    for (;;) {
        printf_P(PSTR("> "));
        if (fgets(line, sizeof(line) - 1, stdin) == NULL) {
            putchar('\n');
            continue;
        }

        if (strlen(line) <= 1) continue;
        printf_P(PSTR("\n- "));

        for (i = 0; i < strlen(line); i++) {
            putchar(line[i]);
            _delay_ms(300);
        }
        printf_P(PSTR("\n"));
    }
    printf_P(PSTR("\nSomething barfed.\n"));
    return 0;
}

void rbuf_init(rbuf_t* const buffer)
{
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        buffer->in    = buffer->buffer;
        buffer->out   = buffer->buffer;
        buffer->count = 0;
    }
    return;
}

rbuf_count_t rbuf_getcount(rbuf_t* const buffer)
{
    rbuf_count_t count;
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        count = buffer->count;
    }
    return count;
}

bool rbuf_isempty(rbuf_t* buffer)
{
    return (rbuf_getcount(buffer) == 0);
}

void rbuf_insert(rbuf_t* const buffer, const rbuf_data_t data)
{
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        if ((buffer->in) == &buffer->buffer[sizeof(buffer)])
            return;
        *buffer->in = data;
        ++buffer->in;
        buffer->count++;
    }
    return;
}

rbuf_data_t rbuf_remove(rbuf_t* const buffer)
{
    rbuf_data_t data;
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        data = *buffer->out;
        if (++buffer->out == &buffer->buffer[sizeof(buffer)])
            buffer->out = buffer->buffer;
        buffer->count--;
    }
    return data;
}

ISR (USART0_RX_vect)
{
    uint8_t c;

//  if (UCSR0A & _BV(FE0))
//      return;
//  if (UCSR0A & _BV(DOR0))
//      return;
    c = UDR0;
    rbuf_insert(&rbuf, (rbuf_data_t) c);

    return;
}

/*
 * Receive a character from the UART Rx.
 *
 */
int uart_getchar(FILE *stream)
{
    uint8_t c;

    while (rbuf_isempty(&rbuf)); /* block until something's there */

    c = rbuf_remove(&rbuf);

    /* this executes twice then nothing more seen */
    printf_P(PSTR("+%c"), c);
    return c;
}

/*
 * Initialize the UART to baud/bps, tx/rx, 8N1.
 */
void uart_init(unsigned int baud)
{
    rbuf_init(&rbuf);
    stdout = stdin = &uart_str;

#if F_CPU < 2000000UL && defined(U2X)
    UCSR0A = _BV(U2X);  /* improve baud rate error by using 2x clk */
    UBRR0L = (F_CPU / (8UL * baud)) - 1;
#else
    UBRR0L = (F_CPU / (16UL * baud)) - 1;
#endif
    /* Clear error flags, MODbus protocol: */
    UCSR0A=0x00;
    /* Enable TX, RX, and RX interrupt */
    UCSR0B = (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0);

    return;
}

/*
 * Send character c down the UART Tx, wait until tx holding register
 * is empty.
 */
int uart_putchar(char c, FILE *stream)
{
    if (c == '\a') {
        fputs("*ring*\n", stderr);
        return 0;
    }

    if (c == '\n')
        uart_putchar('\r', stream);
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;

    return 0;
}

```