Programando el ATTiny40 con TPI y USBasp

Final blink - ATTiny40

¿Qué hay mejor en el mundillo de la electrónica que trastear con microcontroladores? Sí, trastear con microcontroladores baratos como el ATTiny40. De hecho estos me han salido tan baratos que ni siquiera el fabricante los tiene tan baratos en precio por volumen de 5000 unidades. En mi caso los he comprado por Arrow a 18 céntimos cada uno, que debe ser que además con alguna promoción que tenía he conseguido también que me lo envíen gratis desde Estados Unidos hasta España. Ha habido momentos que lo he visto sensiblemente más caro, pero aquí está la prueba:

Página de Arrow con el ATTiny40 en venta por 0.18 USD
Todavía parece estar disponible…

Pero… Ay pobre de mí que no sabía qué estaba comprando… Ya al poco de hacer el pago es cuando los chorretones de sudor me empezaron a caer viendo la hoja técnica. Era la primera vez que sacaba los pies del tiesto del mundo Arduino e, ingenuo de mí, pensé que todo tendría una cómoda interfaz serial con la que poder interactuar con cualquier USB-TTL baratillo de Aliexpress… Pero nada más lejos de la realidad. La única interfaz disponible era Tiny Programming Interface: TPI.

Mira que las circunstancias me podrían haber sonreído un poco más: rascando he visto que la familia de ATTiny series 0 y 1 tienen una interfaz de un sólo cable (Unified Programming and Debugging Interface: UPDI) de la que es, aparentemente, infinitamente más fácil encontrar tutoriales y cosas funcionando. Pero no, TPI únicamente. Para esa otra interfaz, aunque es relativamente nueva, es fácil encontrar numerosos proyectos como placas con programador incluido y una interfaz jtag en la que se basan muchos otros desarrollos.

¿Qué hay para TPI? Pues no mucho, la verdad. Y lo peor es que todo está centrado principalmente en el ATTiny10, un microcontrolador del tamaño de un grano de arroz que ha dado bastante juego para algunos en la comunidad maker. Hay varios artículos donde hablan de cómo desarrollar software para él, o donde han creado un tipo de firmware para un adaptador USB-TTL, y lo que mejor pinta tenía: un sketch de arduino que simulaba la interfaz TPI para el ATTiny10.

Salida del script al conectar un ATTiny40 en el programador TPI
Salida del script al conectar un ATTiny40 en el programador TPI

Ese script era el más prometedor que vi hasta la fecha: reconocía el controlador y podía hacer un dump de la memoria, aunque como podéis observar, todo a unos. Sin embargo, a la hora de mandar un fichero .hex compiñad para el chip, era del todo imposible: la memoria no se escribía correctamente. Después de intentar arreglar el sketch original y adecuarlo al protocolo dictado por el datasheet del ATtiny40, decidí desistir por ser totalmente imposible para mí.

Así que después de tanto tiempo perdido con este tema se presentaban unas cuantas opciones: rendirme y dejar abandonados los ATtiny40, comprar un programador oficial de Microchip con soporte para TPI, o lanzarme por la versión extraoficial con un programador baratejo de Aliexpress.

Estuve considerando seriamente la opción de comprar el programador oficial: el MPLAB snap no es nada caro (~30€) para lo que suelen ser estas cosas y así me quito de problemas futuros. Pero me dolía gastarme 150 veces más de lo que me costaba un solo chip en un programador. Así que tiré por la opción rata de buscar un programador barato como un usbasp. La última versión de firmware de este programador soporta la interfaz TPI perfectamente, pero aquí están las malas noticias: los chinos normalmente se venden con versiones de firmware aún más antiguas, así que toca actualizarlo antes.

Actualización de USBasp

Manos a la obra: toca ponerse a actualizar el firmware USBasp antes de continuar. Como de lo único que disponía era de un Arduino, las posibilidades se reducían aún más, aunque fue bastante más sencillo encontrar una guía adaptada a esta particular situación. Como referencia, os dejo el modelo de programador que tenía yo y os confirmo que en mi caso también me tocó conectarle los dos jumpers JP2 para cortocircuitarlos con el cable para poder reprogramarlo.

El programador USBasp después de soldar los jumpers en JP2

Reconozco que no es trivial actualizarlo, pero prefiero centrar el artículo en otros temas más específicos con el ATTiny40, así que sólo dejo el enlace a la guía para que lo sigáis vosotros. Sólo lo comento por confirmaros que este método a mí me funcionó usando el avrdude de los repositorios (sudo apt install avrdude) y este fichero de configuración que me lo descargué con wget. En mi caso tuve que modificar ligeramente el comando para que apuntase correctamente a la ruta del USB a /dev/ttyUSB0 donde estaba conectado el Arduino (la misma que reconoce el IDE de Arduino):

avrdude -C avrdude.conf -p m8 -c avrisp -P /dev/ttyUSB0 -b 19200 -U flash:w:usbasp.atmega8.2011-05-28.hex:i

Programación con USBasp al ATTiny40

Lo siguiente, si todo nos ha ido bien como vemos en la terminal anterior, es configurar el USBasp y conectar los pines adecuados al ATTiny40.

Programación de ATTiny40 con USBASP
Esquema de conexiones del ATTiny40 y USBasp para programación TPI

Pero nos falta la parte más importante de todas. Un programa que escribir en el dispositivo y poder comprobar que realmente estamos programándolo correctamente. Lo realmente importante es cómo subir código al ATTiny40 usando avrdude.

Cogeremos un pequeño código de ejemplo que guardaremos en un archivo main.c:

#include <util/delay.h>
#include <avr/io.h>
 
int main() {
    DDRB |= _BV(DDB2); // set as output
 
    while (1) {
        PORTB &= ~_BV(PORTB2); // turn off
        _delay_ms(1000);
 
        PORTB |= _BV(PORTB2); // turn on
        _delay_ms(1000);
    }
 
    return 0;
}

Y ahora lo compilamos con:

avr-gcc -std=c99 -Wall -g -O2 -mmcu=attiny40 -DF_CPU=1200000 -I. -o main.bin main.c

Para subirlo al AVR necesitaremos un archivo .hex, que lo generamos de esta forma:

avr-objcopy -j .text -j .data -O ihex main.bin main.hex

Y por último, una vez tengamos todo funcionando, podremos subir nuestro programa de ejemplo con avrdude:

avrdude -p attiny40 -c usbasp -U flash:w:main.hex:i -F -P usb

Para comprobar que el programa está haciendo algo conectamos un un led de esta forma: el ánodo a VCC y el cátodo al pin 19 (PB2 en el datasheet). Y si todo ha ido bien ¡lo veremos parpadear!

Esquema de conexiones para el programa de prueba

Tienes un repositorio en gitlab con todo este código, incluido un Makefile que facilita la tarea de desarrollo.

¡Un saludo!

PD: Si alguien con responsabilidad en Arrow o Aliexpress está leyendo esto, que los enlaces los tenga en cuenta como promocionados. A la derecha hay un enlace con donaciones donde pueden realizar el pago :P.

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.