🛠 Pont Linux ↔ Arduino : appeler des fonctions du sketch M4 depuis Python (RPC)
Objetivos
El núcleo de la arquitectura X8: hacer que Linux y Arduino dialoguen. El puente oficial es un msgpack-RPC: en el lado de Linux, el servicio systemd m4-proxy (preinstalado, escucha en el puerto 5001) actúa como broker; en el lado M4, la biblioteca RPC del core Mbed permite usar RPC.bind para exponer funciones C++ invocables desde contenedores, y RPC.call para llamar a funciones servidas por Linux. Vas a repetir el tutorial oficial «Python ↔ Arduino data exchange»: un sketch M4 que expone subtract, y un contenedor Python que lo llama — con el monitor serie del M4 proxyfiado en /dev/ttyGS0.
Material
- 1 × Arduino Portenta X8 + cable USB-C de datos
- Core «Arduino Mbed OS Portenta Boards», placa «Arduino Portenta X8»
- Imagen
arduino/python-rpc-serialcargada en la placa (tutorial Docker) - PC con adb + un segundo terminal
adb shellpara seguir los logs - Consola: los puertos RPC van de 5001 (broker) a 5020
Código completo
// rpc_server_m4.ino — pattern de l'exemple officiel PortentaX8_EchoServer
#include "SerialRPC.h" // proxy du moniteur serie vers Linux
#include "RPC.h" // msgpack-RPC M4 <-> Linux via m4-proxy
// Fonction tournee sur le M4, appelable depuis un conteneur Linux
int subtract(int a, int b) { return a - b; }
void setup {
Serial.begin(115200); // visible cote Linux via m4-proxy
pinMode(LED_BUILTIN, OUTPUT);
RPC.bind("subtract", subtract); // enregistre l'API pour Linux
}
void loop {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
// Appel vers Linux : « whoami » est servi par le service m4-proxy
if (Serial.available) {
String cmd = Serial.readStringUntil('\n');
if (cmd.startsWith("whoami")) {
auto res = RPC.call("whoami").as<std::string>;
Serial.println(res.c_str);
}
}
}
# cote Linux (conteneur arduino/python-rpc-serial) — appel du M4
# lance : adb shell puis docker exec -it python-rpc-serial python3
import rpc
client = rpc.Client("127.0.0.1", 5001) # le broker m4-proxy
print(client.call("subtract", 7, 4)) # -> 3, calcule sur le M4
Verificación esperada
Tras flashear el sketch M4 y lanzar el contenedor, la llamada Python subtract(7, 4) devuelve 3 — calculado físicamente en el Cortex-M4. Al escribir whoami en la serie proxyfiada, es el M4 quien interroga a Linux e imprime fio. El servicio broker se supervisa con sudo journalctl -fu m4-proxy: es el primer lugar donde mirar cuando el RPC no responde.
Errores frecuentes
- RPC mudo aunque todo compile: verifica primero que m4-proxy esté funcionando (
sudo journalctl -fu m4-proxy) — el lado Linux del puente es un servicio systemd, no una biblioteca enlazada en tu contenedor. - Problema conocido: «RPC doesn't seem to be working on X8» (arduino/ArduinoCore-mbed #960, abierto) — si nada pasa a pesar de tener un m4-proxy en verde, prueba con el ejemplo oficial PortentaX8_EchoServer antes de culpar a tu código.
- Llamar al puerto 5002 directamente en lugar del broker 5001: los servidores RPC de los contenedores se registran ante el broker; es 5001 lo que el M4 y los clientes interrogan (rango 5001-5020 reservado para RPC).
- Olvidar
--device /dev/ttyGS0y-p 5002-5020:5002-5020en eldocker run: sin ellos, el contenedor no ve ni la serie del M4 ni los puertos RPC. - Esperar el monitor serie USB clásico: en X8 la consola del M4 pasa por el proxy SerialRPC/m4-proxy — es una ruta diferente a la de la Portenta H7.
- >
- >
Otros tutoriales para esta placa
- Premiers pas : comprendre le monstre à 9 cœurs et entrer dans Linux via ADB
- Premier sketch sur le cœur M4 : le blink qui se flash par ADB
- Docker dès la sortie de l'emballage : premier conteneur sur le Linux embarqué
- Mettre la X8 en réseau : Wi-Fi du Murata 1DX et Gigabit Ethernet sur porteuse
- Nœud IoT de datalogging : capteurs sur le M4, stockage et transport en conteneur
- Le firmware caché : mettre à jour le bridge STM32H7 M7 qui expose les périphériques à Linux
Ejemplos de código para esta placa
etat-systeme.shBashgpio-libgpiod.shBashpython-gpio.pyPythondocker-hello.shBashflasher-core-arduino.shBashwifi-nmcli.shBash