🛠 Pont Linux ↔ Arduino : appeler des fonctions du sketch M4 depuis Python (RPC)
Objectifs
Le cœur de l'architecture X8 : faire dialoguer Linux et l'Arduino. Le pont officiel est un msgpack-RPC : côté Linux, le service systemd m4-proxy (préinstallé, écoute sur le port 5001) fait le broker ; côté M4, la bibliothèque RPC du core Mbed permet de RPC.bind des fonctions C++ appelables depuis des conteneurs, et RPC.call d'appeler des fonctions servies par Linux. Tu vas rejouer le tuto officiel « Python ↔ Arduino data exchange » : un sketch M4 qui expose subtract, et un conteneur Python qui l'appelle — avec le monitor série du M4 proxyfié sur /dev/ttyGS0.
Matériel
- 1 × Arduino Portenta X8 + câble USB-C data
- Core « Arduino Mbed OS Portenta Boards », carte « Arduino Portenta X8 »
- Image
arduino/python-rpc-serialtirée sur la carte (tuto Docker) - PC avec adb + un second terminal
adb shellpour suivre les logs - Console : les ports RPC vont de 5001 (broker) à 5020
Code complet
// rpc_server_m4.ino — pattern de l'exemple officiel PortentaX8_EchoServer
#include "SerialRPC.h" // proxy du moniteur série 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
Vérification attendue
Après flash du sketch M4 et lancement du conteneur, l'appel Python subtract(7, 4) renvoie 3 — calculé physiquement sur le Cortex-M4. En tapant whoami sur la série proxyfiée, c'est le M4 qui interroge Linux et imprime fio. Le service broker se surveille avec sudo journalctl -fu m4-proxy : c'est le premier endroit à regarder quand le RPC ne répond pas.
Erreurs fréquentes
- RPC muet alors que tout compile : vérifie d'abord que m4-proxy tourne (
sudo journalctl -fu m4-proxy) — le côté Linux du pont est un service systemd, pas une bibliothèque liée dans ton conteneur. - Issue connue : « RPC doesn't seem to be working on X8 » (arduino/ArduinoCore-mbed #960, ouverte) — si rien ne passe malgré un m4-proxy vert, teste avec l'exemple officiel PortentaX8_EchoServer avant d'accuser ton code.
- Appeler le port 5002 directement au lieu du broker 5001 : les serveurs RPC des conteneurs s'enregistrent auprès du broker ; c'est 5001 que le M4 et les clients interrogent (plage 5001-5020 réservée au RPC).
- Oublier
--device /dev/ttyGS0et-p 5002-5020:5002-5020audocker run: sans eux, le conteneur ne voit ni la série du M4 ni les ports RPC. - Attendre le moniteur série USB classique : sur X8 la console du M4 passe par le proxy SerialRPC/m4-proxy — c'est un chemin différent de la Portenta H7.
- >
- >
Autres tutoriels pour cette carte
- 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
Exemples de code pour cette carte
etat-systeme.shBashgpio-libgpiod.shBashpython-gpio.pyPythondocker-hello.shBashflasher-core-arduino.shBashwifi-nmcli.shBash