Usar AVR en Linux

El propósito de este artículo es enseñar como configurar un sistema Linux para compilar y flashear microcontroladores AVR de ATMEL. En mi caso he podido hacer el prioceso usando Ubuntu 22.04 y Fedora 39, en este articulo se explicara como realizar el prioceso para un Micocontrolador AVR.

Instalación de los paquetes requeridos

El soporte para microcontroladores AVR de 8 bits ha estado disponible como software libre durante muchos años, y estas herramientas están accesibles en los repositorios de GNU Linux. Podemos instalar los paquetes necesarios usando el administrador de paquetes. En el caso de ubuntu:

  1. Instala paquetes relacionados con el desarrollo de software en C y el compilador AVR:
     sudo apt install -y gcc build-essential 
     sudo apt install -y avr-libc binutils-avr gcc-avr  gdb-avr 
    
  2. Instala avrdude, el software para flashear.
    sudo apt install -y libusb-dev avrdude 
    

Configuración del hardware

Si no tienes mucha experiencia con microcontroladores y hardware, este paso puede ser un poco complicado. Para este ejemplo, utilicé algunos transistores y resistencias como interruptores. La siguiente imagen muestra el esquemático del circuito, y el conector corresponde a un USBAsp programmer. Compré el programador en Aliexpress.

La vista en la protoboard se ve así:

Finalmente, el circuito construido incluyendo el programador en la vida real:

Como puedes ver, PB0, PB1 y PB2 se usan para controlar el LED RGB. El puerto SPI está conectado directamente a PB2 (MOSI), PB3 (MISO), PB4 (SCK) y PC6 (RESET). La fuente de alimentación proviene del USB, con los respectivos GND y VCC (5V).

Crea tu primer programa

Se realizó un código de prueba para controlar un LED RGB, implementado con una máquina de estados usando un arreglo de estructuras.
main.c:

//#define F_CPU 1000000 // Uncomment if you  define F_CPU when you compile with avr-gcc
#include <avr/io.h>
#include <util/delay.h>

void configureGPIO(void);
/*RGBState ENUM:
This values represents the pines in a RGB led with its respective colors R: Red, G: Green, B: Blue and its basic possible combinations:
*/
enum RGBState 
{   ALL_OFF = 0, // 000 All LEDs off
    RED,         // 001 Red LED on
    GREEN,       // 010 Green LED on
    RED_GREEN,   // 011 Red and Green LEDs on
    BLUE,        // 100 Blue LED on
    BLUE_RED,    // 101 Blue and Red LEDs on
    BLUE_GREEN,  // 110 Blue and Green LEDs on
    ALL_ON       // 111 All LEDs on
};
/*
LED_states struct contains two unsigned integers with to represents the RGB LED color in an actual state and the next state in a state machine. 
*/
typedef struct States{    
   uint8_t RGB_color ;
   uint8_t next_state;
} LED_states;

int main(void) {
    /*State machine is the representation of the RGB LED states with its actual state and next state to be set. */
    LED_states states_machine[8] = 
    {
        { ALL_OFF, RED},         
        { RED, GREEN},           
        { GREEN, BLUE},          
        { RED_GREEN, BLUE},      
        { BLUE, RED},       	 
        { BLUE_RED, BLUE_GREEN}, 
        { BLUE_GREEN, ALL_ON},   
        { ALL_ON, ALL_OFF}       
    }; 
    int state=ALL_OFF;
    configureGPIO();

    while(1)
    {        
        PORTB =  states_machine[state].RGB_color;           
        state = states_machine[state].next_state;
        _delay_ms(1000); 
        
    }
    return 0;
}

void configureGPIO(void)
{
    //PORTB configured has output
    DDRB = 0x0F;
    // PORTB with all pins in OFF status
    PORTB = 0x00;    
}
  1. Compila el sistema, en este ejemplo solo se usó un archivo para este proyecto, en este caso el proceso de compilación puede realizarse con un par de instrucciones para crear los binarios .elf y .hex:
    • Crea el archivo .elf. (F_CPU es un parámetro aquí, el valor por defecto es 1MHz)
        avr-gcc -mmcu=atmega328p -Wall -Os -DF_CPU=1000000 -o bin/RGB_control.elf main.c 
      
    • Crea el archivo .hex.
        avr-objcopy -j .text -j .data -O ihex bin/RGB_control.elf bin/RGB_control.hex -v  
      
  2. Para flashear al MCU usando avrdude
    avrdude -p su p m328p -c usbasp -P usb -U flash:w:bin/RGB_control.hex 
    

Crea un Makefile básico

Para automatizar el proceso, se puede crear un Makefile. El siguiente Makefile puede usarse para implementar los últimos pasos:

# Makefile for building and flashing ATMEGA328p

# Variables
MCU=atmega328p
F_CPU=1000000
SRC=main.c
BUILD_DIR=bin
BINARY_NAME=RGB_control
PROGRAMMER=usbasp
PORT=usb

# Compiler and linker flags
CFLAGS=-mmcu=$(MCU) -Wall -Os -DF_CPU=$(F_CPU)
LDFLAGS=

# Rules
all: $(BUILD_DIR)/$(BINARY_NAME).hex

$(BUILD_DIR)/$(BINARY_NAME).elf: $(SRC)
	@mkdir -p $(BUILD_DIR)
	avr-gcc $(CFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME).elf $(SRC)

$(BUILD_DIR)/$(BINARY_NAME).hex: $(BUILD_DIR)/$(BINARY_NAME).elf
	avr-objcopy -j .text -j .data -O ihex $(BUILD_DIR)/$(BINARY_NAME).elf $(BUILD_DIR)/$(BINARY_NAME).hex -v

flash: $(BUILD_DIR)/$(BINARY_NAME).hex
	avrdude -p $(MCU) -c $(PROGRAMMER) -P $(PORT) -U flash:w:$(BUILD_DIR)/$(BINARY_NAME).hex:i -v

clean:
	rm -rf $(BUILD_DIR)

.PHONY: all flash clean

Usando Visual Studio Code

Hay un par de extensiones disponibles para Visual Studio Code:

AVR Utils

Es una extensión simple que proporciona una forma de compilar proyectos AVR.

  1. Puedes encontrarla en la pestaña de extensiones en VS Code.

  2. Para crear un proyecto, presiona Ctrl+Shift+P y selecciona AVR Utils: Make Project. Selecciona/crea el directorio en el que trabajarás.
  3. Ingresa un nombre para tu proyecto, por ejemplo, “avrUtilsTest”. Este paso creará un nuevo directorio, y AVR Utils creará: un archivo main.c, una carpeta .vscode con archivos JSON, y una carpeta Debug.
  4. Haz clic en la parte inferior derecha en “Select AVR Device” y selecciona atmega328p.
  5. Selecciona el modo de lenguaje AVR C.
  6. Haz clic en el ícono de compilación. Si aparece un mensaje que dice “No toolchain found”, se recomienda seleccionar el toolchain proporcionada por Microchip (ATMEL).Descarga el toolchain, descomprímela en tu directorio preferido y haz referencia al directorio en la extensión.
  7. VS Code ahora puede compilar proyectos AVR.
  8. Usa avrdude para flashear los binarios al microcontrolador.

Nota: Personalmente, no prefiero esta extensión porque los compiladores están integrados de forma nativa en los sistemas Linux, y no puedes flashear directamente.

AVR Helper

Es una extensión más completa. Sigue estos pasos para instalar y configurar la extensión:

  1. Puedes encontrarla en la pestaña de extensiones en VS Code.
  2. Presiona Ctrl+Shift+P y selecciona AVR Helper: Perform initial setup, y presiona Enter para completar los 4 pasos de la extensión.
    • Escribe la ruta completa al ejecutable del compilador, usualmente: /usr/bin/avr-gcc y presiona Enter.
    • Escribe la ruta completa al ejecutable del programador: /usr/bin/avrdude y presiona Enter.
    • Escribe la ruta completa a las definiciones del programador: /etc/avrdude.conf y presiona Enter.
    • Deja la ruta de las bibliotecas de origen vacía y presiona Enter.
  3. El siguiente paso es configurar el programador, presiona Ctrl+Shift+P y selecciona AVR Helper: Select programmer.
    • Selecciona USBasp o tu dispositivo y presiona Enter.
    • Escribe usb para configurar el puerto y presiona Enter.
    • Deja el parámetro de velocidad vacío y presiona Enter.
  4. Finalmente configura el dispositivo, presiona Ctrl+Shift+P y selecciona AVR Helper: Select select device.
    • Selecciona atmega328p (o tu dispositivo) y presiona Enter.
    • Escribe la frecuencia del dispositivo, en este caso 1000000 (1MHz: valor por defecto en atmega328p de fábrica) y presiona Enter.
  5. VS Code ahora está listo para compilar y flashear un dispositivo. El plugin incluye tres botones para compilar y flashear:
    • Quick: Compila y flashea con opciones predeterminadas.
    • Build: Compila el código fuente.
    • Flash: Flashea el binario al dispositivo.

Conclusión

Es muy posible desarrollar software para microcontroladores AVR usando un entorno Linux. ¡No pagues por una licencia de Windows a menos que sea absolutamente necesario! Todo el proceso se resume en el siguiente video para explicar mejor los pasos.