🛠 Dual-core M7 ↔ M4 : appels de fonctions distants avec la bibliothèque RPC
Objectifs
Exploiter le vrai superpouvoir de la Portenta H7 : ses deux coeurs physiques (Cortex-M7 jusqu'à 480 MHz + Cortex-M4 jusqu'à 240 MHz) qui partagent toutes les périphériques internes. La bibliothèque RPC du core Mbed, bâtie sur OpenAMP/rpmsg, permet d'appeler une fonction bindée sur un coeur depuis l'autre cœur avec RPC.bind / RPC.call — y compris un code MicroPython sur un cœur et du C++ sur l'autre (voir le tuto OpenMV). Tu vas adapter l'exemple officiel Basic_AddSub.
Matériel
- 1 × Arduino Portenta H7 + câble USB-C data
- Core « Arduino Mbed OS Portenta Boards »
- ⚠️ Le même sketch doit être flashé sur les deux coeurs : cible M7 puis cible M4 (menu des ports/cibles de l'IDE)
- Console série 115200 bauds
Code complet
// 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, démarre 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);
}
Vérification attendue
Flash sur M7 → rien ne s'affiche (le M4 n'est pas encore là) ; flash le même sketch sur M4 → la console affiche add(1, 2) = 3 puis sub(3, 1) = 2 en boucle. C'est la preuve que le M7 a exécuté du code physiquement sur le M4. La variante officielle RPC_m4 ajoute SerialRPC (le M4 imprime via l'USB série du M7) et un Thread Mbed faisant des appels distants non bloquants.
Erreurs fréquentes
- Flasher un seul cœur : les exemples RPC ne marchent que si le même sketch est sur les deux coeurs — c'est LE piège n°1, documenté dans les exemples officiels.
- Oublier le
delay(100)aprèsRPC.begincôté M7 : les exemples officiels l'insèrent exprès pour laisser au M4 le temps de binder ses fonctions ; sans lui, les premiersRPC.calléchouent. - Appeler une fonction jamais bindée : l'appel ne « crash » pas bruyamment, il renvoie une erreur silencieuse — bind sur le cœur qui doit l'exécuter.
- Croire que le M4 voit la console USB : le M4 n'a pas de série USB propre — utilise
SerialRPCpour imprimer depuis le M4 à travers le M7. - Mélanger les cibles IDE : quand tu passes du blink mono-cœur au RPC, repense bien à sélectionner la cible M4 pour la seconde flash.
- >
Autres tutoriels pour cette carte
- 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
Exemples de code pour cette carte
clignotante.inoArduinobouton-poussoir.inoArduinopwm-respiration.inoArduinoentree-analogique.inoArduinomulti-uart.inoArduinocapteur-i2c-bmp280.inoArduino