🛠 Dual-core M7 ↔ M4 : appels de fonctions distants avec la bibliothèque RPC
Objectives
Leverage the true superpower of the Portenta H7: its two physical cores (Cortex-M7 up to 480 MHz + Cortex-M4 up to 240 MHz) that share all internal peripherals. The RPC library of the Mbed core, built on OpenAMP/rpmsg, allows calling a function bound on one core from the other core using RPC.bind / RPC.call — including MicroPython code on one core and C++ on the other (see the OpenMV tutorial). You will adapt the official Basic_AddSub example.
Hardware
- 1 × Arduino Portenta H7 + USB-C data cable
- "Arduino Mbed OS Portenta Boards" core
- ⚠️ The same sketch must be flashed on both cores: target M7 then target M4 (IDE ports/targets menu)
- Serial console at 115200 baud
Complete Code
// rpc_addsub.ino — identique sur M7 et M4 ; RPC les relie.
// (adapte de l'exemple officiel Basic_AddSub, ArduinoCore-mbed)
#include "RPC.h"
int add(int a, int b) { return a + b; } // fonctions appelables
int sub(int a, int b) { return a - b; } // depuis l'autre coeur
void setup {
Serial.begin(115200);
while (!Serial) {}
RPC.begin; // sur M7, demarre aussi le coeur M4
RPC.bind("add", add); // expose la fonction sous un nom
RPC.bind("sub", sub);
if (RPC.cpu_id == CM7_CPUID) {
delay(100); // laisse le M4 binder ses fonctions
}
pinMode(LEDG, OUTPUT);
}
void loop {
// L'appel part sur le coeur qui a bindé la fonction, le
// résultat revient typé via .as<int>.
int res = RPC.call("add", 1, 2).as<int>;
if (RPC.cpu_id == CM7_CPUID) {
Serial.println("add(1, 2) = " + String(res));
res = RPC.call("sub", res, 1).as<int>;
Serial.println("sub(3, 1) = " + String(res));
}
delay(250);
}
Expected Verification
Flash on M7 → nothing is displayed (the M4 is not yet present); flash the same sketch on M4 → the console displays add(1, 2) = 3 then sub(3, 1) = 2 in a loop. This proves that the M7 executed code physically on the M4. The official RPC_m4 variant adds SerialRPC (the M4 prints via the M7's USB serial) and an Mbed Thread making non-blocking remote calls.
Common Errors
- Flashing only one core: RPC examples only work if the same sketch is on both cores — this is THE #1 pitfall, documented in the official examples.
- Forgetting the
delay(100)afterRPC.beginon the M7 side: official examples insert it specifically to give the M4 time to bind its functions; without it, the firstRPC.callattempts fail. - Calling a function that was never bound: the call does not "crash" loudly, it returns a silent error — bind on the core that must execute it.
- Believing that the M4 sees the USB console: the M4 does not have its own USB serial — use
SerialRPCto print from the M4 through the M7. - Mixing IDE targets: when switching from a single-core blink to RPC, remember to select the M4 target for the second flash.
- >
Other tutorials for this board
- Premier programme : installer le core et faire clignoter la LED (M7 à 480 MHz !)
- Se connecter au Wi-Fi avec le module Murata 1DX (station WPA2)
- Apprivoiser les connecteurs 80 broches : bouton, LED et entrée analogique
- Client HTTPS/TLS : interroger une API sécurisée via le Murata 1DX
- Serveur web sur le port Ethernet 10/100 embarqué
- MicroPython + machine vision : le firmware OpenMV sur un cœur, C++ sur l'autre
Code examples for this board
clignotante.inoArduinobouton-poussoir.inoArduinopwm-respiration.inoArduinoentree-analogique.inoArduinomulti-uart.inoArduinocapteur-i2c-bmp280.inoArduino