jeudi 19 novembre 2015

Echo sur Arduino nano sans IDE

En utilisant le strict minimum, à partir de la datasheet de l'ATmega368 :
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
/*
** UART
*/
void uart_init(void)
    {
    UBRR0H = 0x00;
    UBRR0L = 103;  /* F_CPU/16/baud-1 for 9600 bps*/
    UCSR0C = (1<<USBS0) | (3<<UCSZ00); /* 8N1 */
    UCSR0B = (1<<RXEN0) | (1<<TXEN0); /* enable */
    }
char my_getc()
    {
    while (!(UCSR0A & (1<<RXC0)))
        ;
    return(UDR0);  /* should handle errors */
    }
void my_putc(char c)
    {
    while (!(UCSR0A & (1<<UDRE0)))
        ;
    UDR0 = c;
    }
/*-----------------------------------------------*/
int main(void)
    {
    uart_init();

    for (;;)
        my_putc(my_getc());
    }
Avec comme commandes :
$ avr-gcc  -mmcu=atmega328 -Os -o echo.elf echo.c
$ avrdude -c arduino -p atmega328P -P /dev/ttyUSB0 -b 57600 -U flash:w:echo.elf
On peut tester avec
$ minicom -D /dev/ttyUSB0 -b 9600

AVR libc

Intrigué par le fait que mes putc() et getc() entraient en conflit avec des 'built-in', j'ai fini par me rendre compte de l'existence d'une véritable libc pour AVR... Et c'est quand même vachement mieux fichu que l'API Arduino. Ouf! Notamment du côté de stdio. Adapté, le programme devient quelque chose comme :
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <stdio.h>
#include <string.h>
/*
** UART
*/
void uart_init(void)
    {
    UBRR0H = 0x00;
    UBRR0L = 103;  /* 9600 bps | F_CPU/16/baud-1 */
    UCSR0C = (1<<USBS0) | (3<<UCSZ00); /* 8N1 */
    UCSR0B = (1<<RXEN0) | (1<<TXEN0);
    }
int uart_getchar(FILE *stream)
    {
    while (!(UCSR0A & (1<<RXC0)))
        ;
    return(UDR0);
    }
int uart_putchar(char c, FILE *stream)
    {
    while (!(UCSR0A & (1<<UDRE0)))
        ;
    UDR0 = c;
    }
/*-----------------------------------------------*/
/* line input with minimal editing */
char *getline(char *cp, int n)
    {
    int    i=0;
    char    c;

    for(;;)
        {
        c = fgetc(stdin);
        if (c=='\n' || c=='\r' || i==(n-1))
            {
            cp[i] = '\0';
            return(cp);
            }
        if (c=='\b' && i>0)
            {
            fputc(c, stdout);
            fputc(' ', stdout);
            i -= 1;
            }
        else    cp[i++] = c;
        fputc(c, stdout);
        }
    }
int main(void)
    {
    char buf[32];

    uart_init();
    fdevopen(uart_putchar, uart_getchar);
    printf("Hello World\n\r");
    for (;;)
        {
        printf("\n\rReady> ");
        getline(buf, sizeof(buf));
        printf("\n\rstrlen('%s') is %d.\n\r", buf, strlen(buf));
        }
    }

Aucun commentaire: