Acabo de subir la revisión 1.7 de la placa del teclado. Uno de los cambios más importantes ha sido conectar una de las columnas del teclado desde el puerto PE2 al PB7. Para entender el motivo, primero necesitamos entender cómo es el proceso de arranque del Atmega32Ux.
El procesador Atmega32Ux permite añadir un bootloader y arrancarlo en determinadas circunstancias. Hay varias posibilidades:
- Llamarlo manualmente desde el programa principal (útil para cambiar a modo programación de manera «manual»)
- Llamarlo siempre que se resetee el procesador
- Llamarlo tras un reset si se da cierta condición externa
Y esta última es la clave: esa condición externa es que el pin PE2 esté a nivel bajo en el momento de ocurrir el reset. Esto permite que, por defecto, se arranque el código principal, pero si se desea arrancar el bootloader, sólo haya que conectar dicho pin a masa y pulsar reset.
Pues bien, hasta ahora yo utilizaba dicho pin para una de las columnas del teclado simplemente por comodidad de diseño: al hacer el enrutado de las pistas, era más sencillo utilizar ese pin que otro.
El problema es que la placa Teensy 2.0, que es la que lleva el mismo procesador, tiene ese pin permanentemente conectado a masa a través de un pull-down y, además, no está conectado al exterior. Eso significa que en las bibliotecas de teensyduino no está disponible la opción de utilizar dicho pin.
Por simplicidad, yo quería mantener la compatibilidad con la Teensy 2.0 porque me da un entorno de programación y bibliotecas listas para utilizar, lo que simplifica mucho el trabajo, pero este problema me obligaba a rediseñar la placa, algo que no me apetecía mucho porque ya mandé fabricarlas y, aunque la versión actual es mucho más avanzada que la que tengo físicamente, los cambios hechos hasta ahora eran cosméticos y no afectaban a la lógica en sí, mientras que éste sí implicaba un cambio en la lógica de funcionamiento.
Decidí ver qué alternativas tenía, y descubrí que las placas Arduino Leonardo y Arduino Micro también utilizaban el mismo micro, así que decidí echar un vistazo a ver si podía utilizarlas. Al principio tenía buena pinta porque el bootloader estaba disponible, por lo que podía convertir mi teclado en un Arduino «con todas las de la ley». Por desgracia, la alegría no duró mucho: en el caso del Micro, el pin PE2 tampoco estaba conectado al exterior, con lo que estaba en las mismas. Aún peor: otros dos de los pines que utilizo en el teclado están asignados a LEDs, con lo que probablemente no tendría mucha libertad a la hora de utilizarlos. En el caso del Leonardo, tres cuartos de lo mismo.
Al final no me quedó otra que cortar la pista que conectaba PE2, y añadir dos puentes: uno entre PB7 y la pista original, y otra entre masa y una resistencia conectada a PE2.
Probando otros bootloaders
A pesar de todo, decidí probar el bootloader de Arduino, por si era más cómodo que el ubaboot que estaba utilizando hasta ese momento. Arranqué el editor Arduino IDE, configuré una placa Leonardo, le indiqué que tenía un programador Bus Pirate, y le di a Quemar bootloader. Varios minutos (sí, sí… tarda un muy buen rato y no muestra nada en pantalla que indique progreso) finalizó la grabación. Lo primero que descubrí es que me había cambiado los fuses del Atmega, algo que no me gustó mucho porque algunos flags eran… raros. Por ejemplo, me activaba el divisor entre ocho del cuarzo, lo que supone que la CPU va más lenta. Pero lo más raro es que pone a cero los bits 4 y 5 del byte extendido, los cuales se supone que no se deben escribir, y deben estar siempre a 1. Lo peor es que no soy capaz de devolverlos a su estado normal.
Tras varias pruebas, no me acabó de convencer el bootloader, así que volví al ubaboot de nuevo, pero esta vez quería asegurarme de corregir un par de problemas que tenía, y es que al pulsar el botón de reset para entrar en modo programación, no siempre funcionaba, sino que normalmente tenía que darle dos o tres veces antes de que el identificador USB fuese el de OpenMoko en lugar del de Teensy. Por otro lado, al darle la orden de reiniciar desde el programador ubaboot, el USB dejaba de funcionar.
Al final, tras echar un vistazo al código fuente, me di cuenta de que este bootloader espera ser llamado siempre durante el arranque, lo que significa que hay que poner a cero el bit 0 del Fuse High Byte, el flag BOOTRST. De esta manera, siempre arrancará desde el bootloader, y si éste detecta que el procesador está arrancando por haber sido conectado a la corriente, saltará directamente al código principal, y sólo entrará en modo bootloader si se pulsó el botón de reset.
Con estos cambios ya puedo programar fácilmente la placa del teclado: simplemente tengo que instalar Teensyduino para disponer de todas las bibliotecas, indicar al IDE que tengo un Teensy 2.0, y cada vez que compile, fijarme en donde ha almacenado el fichero hex con el código objeto (normalmente en /tmp/arduino_build_XXXXXX, y utilizar el comando
sudo ubaboot.py write path_al_fichero.hex
para programarlo.