TinyGo 0.42 añade soporte para 87 variantes de MCU Puya PY32 y dos placas EmbedFire

CNXSoft: esta es una publicación invitada de Pavel Burgr, que ha añadido recientemente soporte para los MCU Puya PY32 a TinyGo 0.42, la última versión del compilador de Go para microcontroladores. Ya hablamos de TinyGo en 2019, y el proyecto sigue muy activo, con 17 700 estrellas, 1 100 forks y 243 colaboradores. Solo hemos hecho algunas correcciones y hemos añadido ilustraciones y un par de enlaces al artículo.

TinyGo 0.42 añade soporte para la familia Puya PY32 de microcontroladores Arm de 32 bits. El nuevo port incluye código de arranque, definiciones generadas de los registros del dispositivo, scripts de enlazado (linker), soporte para GPIO y UART, y targets para 87 configuraciones distintas de MCU. También incorpora definiciones de placa para dos placas de desarrollo EmbedFire económicas que se venden en AliExpress.

El port lo ha aportado Pavel Burgr y se ha integrado mediante la pull request n.º 5106 de TinyGo. Una de sus motivaciones era establecer una plataforma de firmware sólida y fácil de usar para pequeños dispositivos IoT construidos en torno al servicio Registry y al protocolo de radio de bajo consumo BleRiot (hablaremos de ello al final del artículo). Estos proyectos son independientes de TinyGo, pero muestran el tipo de aplicaciones con recursos limitados que pretenden habilitar los nuevos targets.

TinyGo 0.42 con soporte para los MCU Puya PY32

Amplia cobertura de targets PY32

TinyGo es un compilador de Go para microcontroladores, WebAssembly y otros sistemas con recursos limitados. Utiliza LLVM para generar binarios nativos compactos y ofrece una capa de abstracción de hardware a través de paquetes como machine, conservando la sintaxis y las herramientas habituales de Go. Ejecutar Go en un chip con solo 2 KB de SRAM puede sonar casi a una provocación, pero precisamente para esa clase de retos se creó TinyGo.

El port de PY32 cubre tanto dispositivos Cortex-M0+ como Cortex-M4. La tabla de targets contiene 87 configuraciones concretas de memoria repartidas en 40 familias de definición de dispositivos, desde chips con 8 KB de flash y 2 KB de SRAM hasta modelos con 512 KB de flash y 144 KB de SRAM.

Las series compatibles incluyen:

  • PY32E407
  • PY32F001, F002, F003, F021, F030, F031, F032, F040, F071, F072, F403 y F410
  • PY32L020 y L090
  • PY32M010, M020, M030, M031 y M070
  • PY32MD310, MD320, MD410, MD420 y MD430
  • PY32T020, T090 y T092

Cada target de chip selecciona el mapa de flash y SRAM correcto. Las definiciones de periféricos se generan a partir de los datos CMSIS de Puya mediante el repositorio py32-svd de apoyo, lo que ofrece a quienes escriben drivers nombres de registro con tipos en device/py32 en lugar de tablas de direcciones privadas.

La API machine de TinyGo 0.42 cubre el arranque del reloj y de los temporizadores, GPIO y UART, incluida una segunda UART en determinados modelos. ADC, I2C, SPI y PWM todavía no disponen de drivers machine portables, pero sus registros generados están disponibles para el código de bajo nivel.

Dos placas EmbedFire compatibles

Placas de desarrollo Puya PY32 de bajo coste (EmbedFire)

Dos pequeñas placas de desarrollo Puya32 cuentan con targets y alias de pines dedicados, lo que las convierte en la forma más sencilla de probar el port. Ambas están disponibles por menos de 2 dólares en AliExpress, y la placa PY32F030 se vende por 7 dólares o más en Amazon.

Placa EmbedFire PY32F030 EmbedFire PY32F002B
MCU PY32F030K28U6TR PY32F002BF15U6TR
Núcleo y memoria Cortex-M0+, 64 KB flash, 8 KB SRAM Cortex-M0+ hasta 24 MHz, 24 KB flash, 3 KB SRAM
Alias integrados 3 LED, 2 botones, UART predeterminada 3 LED, 2 botones, UART predeterminada
Target de TinyGo embedfire-py32f030 embedfire-py32f002b

En la placa PY32F030, LED1, LED2 y LED3 están asignados a PA2, PA3 y PA4, y sus dos botones a PA5 y PA6. Su UART predeterminada utiliza PA7 para TX y PA8 para RX. En la placa más pequeña, la PY32F002B, los LED están asignados a PA1, PA5 y PA4, los botones a PA3 y PA0, y la UART predeterminada a PA6 y PA7.

Ambas placas definen machine.LED como alias del segundo LED integrado. Como manda la tradición en el mundo embebido, el mismo primer programa puede ejecutar el parpadeo ceremonial en cualquiera de los dos targets:

package main

import (
	"machine"
	"time"
)

func main() {
	led := machine.LED
	led.Configure(machine.PinConfig{Mode: machine.PinOutput})

	for {
		led.Set(true)
		time.Sleep(500 * time.Millisecond)
		led.Set(false)
		time.Sleep(500 * time.Millisecond)
	}
}

Con una sonda SWD compatible conectada y pyOCD configurado para el dispositivo Puya elegido, el programa se compila y se graba con un solo comando, sin necesidad de hacer arqueología de Makefiles:

tinygo flash -target=embedfire-py32f030 .

Para la placa más pequeña solo cambia el target:

tinygo flash -target=embedfire-py32f002b .

Los targets de placa heredan exactamente los mapas de memoria py32f030x8 y py32f002bx5 e invocan el target de pyOCD correspondiente durante el grabado. También hay targets de chip desnudo (bare-chip) para placas personalizadas. Una pequeña plantilla de proyecto TinyGo PY32 ofrece ejemplos adicionales de parpadeo y un Makefile de partida.

Plantilla de proyecto TinyGo PY32

De un MCU de bajo coste a un nodo IoT conectado a Registry

Dejando atrás el clásico parpadeo, la motivación práctica que hay detrás del port resulta más interesante. Pavel desarrolló el soporte para PY32 mientras construía BleRiot, un protocolo de petición/respuesta sencillo y fiable para nodos de radio de bajo consumo.

Cada nodo expone registros de 32 bits con signo y solo entiende dos operaciones: GET y SET. Ese es todo su vocabulario, y es una virtud, no una carencia. El hub Linux consulta los registros periódicamente y se encarga de los nombres, las conversiones de unidades, los reintentos y los tiempos de espera. Esta interfaz pequeña y predecible mantiene el firmware compacto, y la recuperación tras la pérdida de una trama se resuelve una sola vez en el hub, en lugar de hacerlo en cada aplicación.

Un hub se comunica con muchos nodos a través de un enlace de radio GFSK personalizado de 250 kbps con tramado de paquetes compatible con BLE, aunque no se trata de Bluetooth LE ni de GATT. El nodo de referencia combina un PY32F030x8 con una radio de 2,4 GHz PAN211x, mientras que el hub utiliza un sencillo dongle de radio USB.

BleRiot publica los valores de los nodos en Registry, un servicio local ligero que asigna a cada registro un nombre, su valor actual, metadatos opcionales y un tiempo de vida (TTL). Los valores obsoletos caducan automáticamente. Las aplicaciones pueden usar directamente su API HTTP/JSON; los nodos Node-RED incluidos se combinan con los nodos MQTT estándar para actuar de puente, y un endpoint Prometheus integrado expone los registros numéricos como gauges listos para los paneles de Grafana. En otras palabras, no hace falta enseñarle a un MCU de 3 KB qué es Grafana para ver una temperatura en un panel.

Un controlador recorre ese mismo camino en sentido inverso cuando solicita un cambio. BleRiot comparte los tipos de dispositivo y las definiciones de registros entre el firmware TinyGo y el hub Linux, y sus herramientas pueden generar una identidad de nodo, compilar el firmware con TinyGo y grabarlo por SWD.

Ni Registry ni BleRiot son necesarios para usar TinyGo en PY32, y el soporte de PY32 no está ligado a ninguna radio concreta. Son ejemplos útiles de por qué los microcontroladores de bajo coste se benefician de un compilador con mantenimiento activo, de targets de chip reproducibles y de una API de hardware estándar orientada a Go.

Disponibilidad y próximos pasos

El soporte para PY32 está disponible en TinyGo 0.42.0. Los dos targets de EmbedFire son el punto de entrada más directo, mientras que la lista más amplia de chips proporciona a los desarrolladores una base para placas personalizadas, desde pequeños nodos de sensores hasta controladores Cortex-M4 de mayor tamaño.

TinyGo 0.42 hace hincapié en la estabilidad del runtime, en unos mapas de memoria correctos, en GPIO y en la comunicación serie, sin pretender una cobertura completa de periféricos. Futuras contribuciones podrán añadir ADC, I2C, SPI y PWM portables, así como definiciones de placa, sobre la capa de registros generada en device/py32. Para quienes ya utilizan Go en el lado host de un sistema IoT, el port convierte a la económica familia de MCU de Puya en un endpoint mucho más accesible.

Nota de CNXSoft: al parecer, lo próximo será el soporte de TinyGo para los MCU AT32.

Traducido del artículo en inglés «TinyGo 0.42 adds support for 87 Puya PY32 MCU variants and two EmbedFire boards» de Jean-Luc Aufranc (CNXSoft).