🛠 Pont Linux ↔ Arduino : appeler des fonctions du sketch M4 depuis Python (RPC)
Objectives
The core of the X8 architecture: making Linux and Arduino talk to each other. The official bridge is a msgpack-RPC: on the Linux side, the systemd service m4-proxy (preinstalled, listening on port 5001) acts as the broker; on the M4 side, the RPC library from the Mbed core allows you to RPC.bind C++ functions callable from containers, and RPC.call to call functions served by Linux. You will replay the official tutorial "Python ↔ Arduino data exchange": an M4 sketch that exposes subtract, and a Python container that calls it — with the M4 serial monitor proxied on /dev/ttyGS0.
Hardware
- 1 × Arduino Portenta X8 + USB-C data cable
- "Arduino Mbed OS Portenta Boards" core, "Arduino Portenta X8" board
arduino/python-rpc-serialimage pulled onto the board (Docker tutorial)- PC with adb + a second
adb shellterminal to follow logs - Console: RPC ports range from 5001 (broker) to 5020
Complete Code
// 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
Expected Verification
After flashing the M4 sketch and launching the container, the Python call subtract(7, 4) returns 3 — computed physically on the Cortex-M4. By typing whoami on the proxied serial port, it is the M4 that queries Linux and prints fio. The broker service is monitored with sudo journalctl -fu m4-proxy: this is the first place to look when RPC is not responding.
Common Errors
- RPC is silent even though everything compiles: first check that m4-proxy is running (
sudo journalctl -fu m4-proxy) — the Linux side of the bridge is a systemd service, not a library linked into your container. - Known issue: "RPC doesn't seem to be working on X8" (arduino/ArduinoCore-mbed #960, open) — if nothing works despite a healthy m4-proxy, test with the official PortentaX8_EchoServer example before blaming your code.
- Calling port 5002 directly instead of the broker 5001: RPC servers from containers register with the broker; it is 5001 that the M4 and clients query (range 5001-5020 reserved for RPC).
- Forgetting
--device /dev/ttyGS0and-p 5002-5020:5002-5020in thedocker runcommand: without them, the container sees neither the M4 serial port nor the RPC ports. - Expecting the classic USB serial monitor: on the X8, the M4 console goes through the SerialRPC/m4-proxy proxy — this is a different path than on the Portenta H7.
- >
- >
Other tutorials for this board
- 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
Code examples for this board
etat-systeme.shBashgpio-libgpiod.shBashpython-gpio.pyPythondocker-hello.shBashflasher-core-arduino.shBashwifi-nmcli.shBash