Dec 21, 2013

Create a printf logic in arduino uno for debugging - avr-gcc

If you are using arduino uno board with avr-gcc compiler. You can have a printf printing system for better debugging.
This I tried in debian system and used avr-gcc toolchain.

print.c

#include stdio.h
#include avr/io.h

#ifndef F_CPU
#define F_CPU 16000000UL
#endif

#ifndef BAUD
#define BAUD 38400
#endif

int uart_putch ( char ch, FILE *stream );
int uart_getch ( FILE *stream );

FILE uart_str = FDEV_SETUP_STREAM ( uart_putch, uart_getch, _FDEV_SETUP_RW );

void uart_init ( void )
{
        UBRR0H = (((F_CPU/BAUD)/16)-1)>>8;
        UBRR0L = (((F_CPU/BAUD)/16)-1);
        UCSR0B = (1<<RXEN0)|(1<<TXEN0);
        UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}

void ansi_clear_screen ( void )
{
        putchar(27);
        putchar('[');
        putchar('H');
        putchar(27);
        putchar('[');
        putchar('J');
}

void ansi_me(void)
{
        putchar(27);
        putchar('[');
        putchar('0');
        putchar('m');
}

void uart_flush ( void )
{
        unsigned char dummy;
        while ( UCSR0A & (1<<RXC0) )
               dummy =  UDR0;
}

int uart_putch ( char ch, FILE *stream )
{
        if ( ch == '\n' )
                uart_putch ( '\r', stream );
        while (!(UCSR0A & (1<<UDRE0)));
        UDR0=ch;
        return 0;
}

int uart_getch ( FILE *stream )
{
        unsigned char ch = '\0';
        while ( !(UCSR0A & (1<<RXC0)));
        ch = UDR0;

        return ch;
}

void init_print ( void )
{
  stdout = stdin = &uart_str;
  uart_init ();
  ansi_me ();
  ansi_clear_screen ();
  ansi_me ();
  ansi_clear_screen ();
  uart_flush ();
}


compile it.

In the your .c file add  ( for example consider demo.c as your c file )

#include stdio.h
extern void init_print ( void );

then add printf ("Example\n"); anywhere in the demo.c code.

A part of Makefile.

demo.o: $(SRC)/demo.c
        avr-gcc -g -mmcu=atmega328p -c $(SRC)/demo.c -o demo.o

print.o: $(SRC)/print.c
        avr-gcc -g -mmcu=atmega328p -c $(SRC)/print.c -o print.o

demo.elf: demo.o print.o
        avr-gcc -g -mmcu=atmega328p -o demo.elf demo.o print.o

convert the demo.elf to hex and burn to arduino uno with avrdude.

Now open a minicom ( sudo minicom -s ). Install minicom if you don't have. apt-get install minicom.
Update serial port setup to 38400, 8N1 - save as dfl and exit.

You can see the printf messages in the minicom terminal.

For Web Developer

  open -a "Google Chrome" --args --disable-web-security