#include "uart.h"

void uart_putchar(char c, FILE *stream) {
    if( c == '\n' )
        uart_putchar('\r', stream);
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;
}

static FILE uart_out = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

void uart_init(void) {
    UBRR0L = BAUDRATE&0xFF;
    UBRR0H = (BAUDRATE>>8);

#if USE_2X
    UCSR0A |= _BV(U2X0);
#else
    UCSR0A &= ~(_BV(U2X0));
#endif

    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */
    stdout = &uart_out;
}

#include "uart.h"

void uart_putchar(char c, FILE *stream) {
    if( c == '\n' )
        uart_putchar( '\r', stream );
    UDR0 = c;
    loop_until_bit_is_set(UCSR0A, TXC0);
}

static FILE uart_out = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

void uart_init(void) {
    UBRR0L = BAUDRATE&0xFF;
    UBRR0H = (BAUDRATE>>8);

#if USE_2X
    UCSR0A |= _BV(U2X0);
#else
    UCSR0A &= ~(_BV(U2X0));
#endif

    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */
    stdout = &uart_out;
}

--- 
+++ 
@@ -2,9 +2,9 @@
 
 void uart_putchar(char c, FILE *stream) {
     if( c == '\n' )
-        uart_putchar( '\r', stream );
+        uart_putchar('\r', stream);
+    loop_until_bit_is_set(UCSR0A, UDRE0);
     UDR0 = c;
-    loop_until_bit_is_set(UCSR0A, TXC0);
 }
 
 static FILE uart_out = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
Reorder UART transmission. Instead of waiting for cache to be empty and then sending the value, we first add the value to cache and then wait for transmission. This way no characters are lost during transmission
