Extension C pour MicroPython sur Raspberry Pi Pico
Ceci est un guide sur la façon d'écrire et d'exécuter une extension C de base pour MicroPython sur le Raspberry Pi Pico. Je couvrirai les raisons d'étendre MicroPython, comment écrire le module d'extension, comment le compiler et comment l'installer sur le Pico. Si vous voulez en savoir plus sur ce sujet, veuillez vous référer à https://docs.micropython.org/en/latest/develop/extendingmicropython.html
Introduction
Pourquoi étendre MicroPython ?
Il peut y avoir plusieurs raisons pour lesquelles vous souhaitez étendre MicroPython. Étant donné qu'il s'agit d'une version allégée de Python, MicroPython n'est pas très performant lorsqu'il s'agit de tâches de calcul lourd (comme Python). En revanche, le langage C est parfaitement adapté à ce type de tâches. Une extension C pour Micropython vous permet d'effectuer ces calculs en langage C et d'utiliser les résultats dans MicroPython. Cela peut accélérer certains processus d'un ordre de grandeur.
Une deuxième raison pourrait être que vous souhaitez interfacer un matériel qui utilise une API C à partir de MicroPython.
Types d'extensions C de MicroPython
Il existe deux façons différentes d'étendre MicroPython : les modules C externes et le code machine natif dans les fichiers .mpy.
Pour exécuter un module C externe, vous devez le recompiler dans le firmware MicroPython. Il s'agit d'un processus assez compliqué, c'est pourquoi ce guide se concentrera sur la seconde alternative. Si vous êtes toutefois intéressé par cette approche, vous pouvez en lire plus sur ces pages web : https://docs.micropython.org/en/latest/develop/cmodules.html https://www.raspberrypi.org/forums/viewtopic.php?t=300352
Le fichier .mpy est un fichier qui contient le code machine natif compilé et qui peut être lié dynamiquement. Cela le rend beaucoup plus flexible puisque vous n'avez pas besoin de recompiler l'ensemble du firmware MicroPython.
Écrire le module d'extension
L'écriture du module d'extension est la partie la plus facile de l'extension de MicroPython. Je vais vous montrer comment le faire à l'aide d'un exemple simple. Pour commencer, nous allons créer un nouveau répertoire appelé factfib. Ouvrez une nouvelle fenêtre de terminal, allez dans le nouveau répertoire et créez un nouveau fichier appelé factfib.c. Si vous avez créé le répertoire sur un Raspberry Pi sous Dekstop, la commande ressemble à ceci.
cd ~/Desktop/factfib
touch factfib.c
Ouvrir factfib.c dans votre éditeur de texte favori et saisissez le code suivant :
#include "py/dynruntime.h
STATIC mp_int_t factorial_helper(mp_int_t x) {
if (x < 1) {
return 1;
}
return x*factorial_helper(x-1);
}
STATIC mp_obj_t factorial(mp_obj_t x_obj) {
mp_int_t x = mp_obj_get_int(x_obj);
mp_int_t rslt = factorial_helper(x);
return rslt;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);
STATIC mp_int_t fibonacci_helper(mp_int_t x) {
if (x <= 0) {
return 0;
}
else if (x == 1) {
return 1;
}
else {
return (fibonacci_helper(x-1) + fibonacci_helper(x-2));
}
}
STATIC mp_obj_t fibonacci(mp_obj_t x_obj) {
mp_int_t x = mp_obj_get_int(x_obj);
mp_int_t rslt = fibonacci_helper(x);
return mp_obj_new_int(rslt);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj));
mp_store_global(MP_QSTR_fibonacci, MP_OBJ_FROM_PTR(&fibonacci_obj));
MP_DYNRUNTIME_INIT_EXIT
}
Laissez-moi vous expliquer le code ci-dessus : Dans MicroPython et Python, chaque variable est un objet. Par conséquent, en C, nous les représentons comme mp_obj_t. Mais un programme C ne peut travailler qu'avec des variables de type C, c'est pourquoi nous devons transformer l'objet en un type C. Cela s'appelle le Marshalling. Ceci est appelé Marshalling et MicroPython fournit des fonctions pour extraire n'importe quel type C d'un objet.
Cette page web d'Oliver Robson est très utile pour le maréchalage. https://mpy-c-gen.oliverrobson.tech/. En outre, vous pouvez trouver des exemples de Marshalling dans la documentation de MicroPython. https://docs.micropython.org/en/latest/develop/natmod.html. Je vous conseille de lire cet article si vous avez besoin de plus d'explications.
Construire l'extension
Nous construisons l'extension dans un fichier .mpy en utilisant un Makefile. Mais nous devons d'abord mettre en place certaines choses. Assurez-vous que votre terminal est toujours ouvert en mode factfib répertoire. Puis clonez le dépôt GitHub de MicroPython.
sudo apt-get install build-essential libreadline-dev libffi-dev git pkg-config gcc-arm-none-eabi libnewlib-arm-none-eabi
git clone --recurse-submodules https://github.com/micropython/micropython.git
pip3 install 'pyelftools>=0.25'
Ces installations prendront un certain temps, si vous voulez gagner du temps et que vous savez ce que vous faites, il vous suffit de cloner les répertoires /py et /tools à partir du dépôt micropython et de les placer dans un répertoire de type micropython dans le dossier factfib (ignorez la deuxième commande).
Pendant que l'installation est en cours, nous pouvons utiliser ce temps pour écrire le Makefile. Exécutez simplement
touch Makefile
et ouvrez le fichier nouvellement créé dans un éditeur de texte.
MPY_DIR = micropython
MOD = factfib
SRC = factfib.c
ARCH = armv7m
include $(MPY_DIR)/py/dynruntime.mk
Vous avez peut-être remarqué que nous avons défini le ARCH à la variable armv7m bien que le pico soit armv6m. Nous devons le faire parce que le armv6m n'est (au moment où j'écris cet article) pas supportée par l'architecture dynruntime.mk outil.
Mais heureusement, nous pouvons toujours compiler une extension fonctionnelle pour le Pico. Nous devons juste modifier le fichier dynruntime.mk qui doit être situé sous micropython/py/dynruntime.mk. Ouvrez-le et sous la rubrique Configuration de l'architecture dans armv7m, trouvez la variable CFLAGS (qui devrait être la ligne 64). Changez -mcpu=cortex-m3 à -mcpu=cortex-m0 et enregistrez le fichier.
Puis, une fois que tout est installé, exécutez
make
et le factfib.mpy sera créé.
Installer et tester l'extension
La dernière étape est l'installation et le test. Pour cela, nous utilisons le système de fichiers que Micropython crée sur le Raspberry Pi Pico. Tout d'abord, nous devons flasher le Pico avec le firmware MicroPython. La façon la plus simple de le faire est d'utiliser l'IDE Thonny (préinstallé sur Raspbian/Raspberry Pi OS).
Si vous n'utilisez pas un Raspberry Pi pour programmer votre Pico ou si vous n'avez jamais utilisé MicroPython sur le Pico auparavant, veuillez vous reporter au guide de démarrage avec MicroPython de Raspberry Pi. https://www.raspberrypi.org/documentation/rp2040/getting-started/#getting-started-with-micropython
Si vous utilisez Windows, vous devriez consulter cet article de blog sur le Raspberry Pi Pico et MicroPython sous Windows. https://picockpit.com/raspberry-pi/raspberry-pi-pico-and-micropython-on-windows/
Fermez Thonny après avoir flashé votre Pico avec le firmware MicroPython et installez rshell. Nous utilisons rshell pour accéder au système de fichiers à partir de la ligne de commande.
sudo pip3 install rshell
rshell --version
Cela imprime la version rhsell si tout est configuré correctement. Ensuite, débranchez le pico et rebranchez-le (sans maintenir le bouton BOOTSEL) pour vous assurer que rien n'essaie d'accéder au système de fichiers. Maintenant, nous devons exécuter
rshell -p /dev/ttyACM0 --buffer-size 512
cp factfib.mpy /pyboard/factfib.mpy
Pour tester l'installation, vous pouvez utiliser soit rshell, soit l'IDE Thonny pour enregistrer votre .py sur le Pico mais je vais démontrer comment utiliser l'interpréteur MicroPython sur le minicom.
Alors, appuyez d'abord sur Ctrl+c pour quitter rshell et ensuite installer minicom via
sudo apt install minicom
maintenant nous pouvons accéder au REPL de Picos (boucle Read-eval-print)
minicom -o -D /dev/ttyACM0
Les trois crochets de fermeture >>> indiquent que l'interpréteur MicroPython est en cours d'exécution. Nous pouvons maintenant importer notre extension et travailler avec elle comme d'habitude.
>>> import factfib as ff
>>> ff.factorial(5)
>>> 120
>>> ff.fibonacci(7)
>>> 13
Félicitations ! Vous avez créé votre première extension MicroPython C pour le Pico ! L'étape suivante consiste à apprendre à écrire et à compiler des modules plus complexes. Une bonne façon de commencer est de tester le fonctionnement du Marshalling de listes et de dicts (voir la page web Marshalling ci-dessus).
Si vous avez des questions concernant cet article, n'hésitez pas à écrire un commentaire.
A part l'erreur dans le programme c, ça a marché à merveille. Merci.
STATIQUE mp_obj_t factorial(mp_obj_t x_obj) {
mp_int_t x = mp_obj_get_int(x_obj) ;
mp_int_t rslt = factorial_helper(x) ;
retourner mp_obj_new_int(rslt) ;
}
Merci pour vos commentaires 🙂
Comment configurer joomla pour qu'il puisse récupérer les données de mysql ?
J'ai essayé de faire ce qui précède, mais plusieurs choses ne fonctionnent pas comme décrit :
- J'ai suivi les instructions ci-dessus, obtenu micropython, modifié le makefile comme décrit
- Je fais (mais j'obtiens un fichier factfib.native.mpy au lieu de factfib.mpy)
- Je copie le fichier factfib.native.mpy sur le pico comme factfib.mpy
(J'ai essayé rshell mais j'ai eu un "timed out or error in transfer to remote : b"", mais j'ai pu le copier en utilisant Thonny)
- Je peux importer le module (dans thonny ou rshell - c'est pareil) sans erreur.
- J'essaie d'exécuter "ff.fibonacci(5)" mais j'obtiens alors :
" Traceback (dernier appel le plus récent) :
Fichier "", ligne 1, dans
AttributeError : L'objet 'module' n'a pas d'attribut 'fibonacci'".
Qu'est-ce que je fais de mal ?
Avez-vous réussi à le faire fonctionner ?
Maintenant vous pouvez compiler pour armv6, il suffit de changer cette ligne dans le Makefile et il n'est pas nécessaire de changer le code micropython.
ARCH = armv6m
J'ai eu quelques erreurs en compilant le factfib.c, où sont les correctifs :
// il manque le " à la fin.
#include "py/dynruntime.h"
// convertir la valeur de retour en mp_obj_t
STATIQUE mp_obj_t factorial(mp_obj_t x_obj) {
mp_int_t x = mp_obj_get_int(x_obj) ;
mp_int_t rslt = factorial_helper(x) ;
retourner mp_obj_new_int(rslt) ;
}
Merci pour ces informations, Paulo !
J'ai suivi toutes les instructions et j'ai obtenu un fichier facfib.mpy construit. J'ai utilisé
ARCH = armv6m
Lorsqu'il est chargé dans le Pico, j'obtiens cette erreur :
ValueError : fichier .mpy incompatible
Mon Pico a besoin des valeurs mpy suivantes :
version mpy : 6
sous-version mpy : 2
drapeaux mpy : -march=armv6m
La vérification des deux premiers octets du fichier donne la version 6 et la sous-version 6.
Existe-t-il un moyen de corriger ce problème ?