C uitbreiding voor MicroPython op Raspberry Pi Pico

Dit is een gids over hoe een basis C uitbreiding voor MicroPython te schrijven en te draaien op de Raspberry Pi Pico. Ik zal de redenen voor het uitbreiden van MicroPython behandelen, hoe de uitbreidingsmodule te schrijven, hoe het te compileren en hoe het te installeren op de Pico. Als u meer wilt lezen over dit onderwerp, raadpleeg dan https://docs.micropython.org/en/latest/develop/extendingmicropython.html

Inleiding

Waarom MicroPython uitbreiden?

Er kunnen meerdere redenen zijn waarom u MicroPython zou willen uitbreiden. Omdat het een afgeslankte versie van Python is, presteert MicroPython niet erg goed als het aankomt op rekenkundig zware taken (vergelijkbaar met Python). C daarentegen is zeer geschikt voor dergelijke taken. Een C extensie voor Micropython maakt het mogelijk om die berekeningen in de C taal uit te voeren en de resultaten in MicroPython te gebruiken. Dit kan sommige processen met een orde van grootte versnellen.

Een tweede reden kan zijn, dat u hardware die een C API gebruikt vanuit MicroPython wilt koppelen. 

Soorten MicroPython C-uitbreidingen

Er zijn verschillende manieren om MicroPython uit te breiden: externe C modules en native machine code in .mpy bestanden.

Om een externe C-module te kunnen gebruiken, moet u deze hercompileren in de MicroPython firmware. Dit is een nogal gecompliceerd proces, daarom zal deze gids zich richten op het tweede alternatief. Als u echter geïnteresseerd bent in deze aanpak, kunt u er meer over lezen op deze webpagina's:                https://docs.micropython.org/en/latest/develop/cmodules.html                      https://www.raspberrypi.org/forums/viewtopic.php?t=300352

De .mpy is een bestand dat gecompileerde native machine code opslaat en dynamisch kan worden gelinkt. Dit maakt het veel flexibeler omdat je niet de hele MicroPython firmware hoeft te hercompileren.

Schrijf de uitbreidingsmodule

Het schrijven van de uitbreidingsmodule is het gemakkelijkste deel van het uitbreiden van MicroPython. Ik zal je laten zien hoe je dat doet aan de hand van een eenvoudig voorbeeld. Om te beginnen maken we een nieuwe directory aan genaamd factfib. Open een nieuw terminal venster, cd naar de nieuwe directory en maak een nieuw bestand genaamd factfib.c. Als je de directory op een Raspberry Pi onder Dekstop hebt aangemaakt, ziet het commando er als volgt uit.

cd ~/Desktop/factfib

aanraken factfib.c

Open factfib.c in uw favoriete tekstverwerker en voer de volgende code in

#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
}

Laat me de code hierboven uitleggen: In MicroPython en Python, is elke variabele een object. Daarom stellen we ze in C voor als mp_obj_t. Maar een C programma kan alleen werken met C type variabelen, daarom moeten we het object omzetten in een C type. Dit heet Marshalling en MicroPython biedt functies om elk C type uit een object te halen.

Deze webpagina van Oliver Robson is echt nuttig voor Marshalling https://mpy-c-gen.oliverrobson.tech/. Verder kunt u Marshalling voorbeelden vinden in de MicroPython documentatie https://docs.micropython.org/en/latest/develop/natmod.html. Ik raad u aan dit artikel te lezen als u meer uitleg nodig hebt.

Bouw de uitbreiding

We bouwen de extensie in een .mpy bestand met behulp van een Makefile. Maar we moeten eerst een paar dingen instellen. Zorg ervoor dat je terminal nog steeds geopend is in de factfib map. Kloon dan de MicroPython GitHub repository.

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 installeer "pyelftools>=0.25

Deze installaties zullen een tijdje duren, als je tijd wilt besparen en je weet wat je doet, hoef je alleen maar de /py en /tools directory van de micropython repository te clonen en ze in een micropython map in de factfib map (sla het tweede commando over).

Terwijl de installatie loopt, kunnen we de tijd gebruiken om de Makefile te schrijven. Voer gewoon

touch Makefile

en open het nieuw aangemaakte bestand in een tekstverwerker. 

MPY_DIR = micropython

MOD = factfib

SRC = factfib.c

ARCH = armv7m

include $(MPY_DIR)/py/dynruntime.mk

Je hebt misschien gemerkt dat we de ARCH variabele naar armv7m hoewel de pico armv6m. We moeten dit doen omdat de armv6m architectuur wordt (op het moment dat ik dit artikel schrijf) niet ondersteund door de dynruntime.mk gereedschap.

Maar gelukkig kunnen we nog steeds een werkende uitbreiding compileren voor de Pico. We hoeven alleen maar de dynruntime.mk bestand, dat zich moet bevinden onder micropython/py/dynruntime.mkOpen het en zoek onder Architectuur configuratie in armv7m naar de CFLAGS variabele (zou regel 64 moeten zijn). Verander -mcpu=cortex-m3 naar -mcpu=cortex-m0 en sla het bestand op.

chnge -mcpu=cortex-m3 naar -mcpu=cortex-m0

Dan nadat alles geïnstalleerd is, voer

maken

en de factfib.mpy bestand zal worden aangemaakt.

Installeer en test de uitbreiding

De laatste stap is installeren en testen. Hiervoor maken we gebruik van het bestandssysteem dat Micropython aanmaakt op de Raspberry Pi Pico. Eerst moeten we de Pico flashen met de MicroPython firmware. De gemakkelijkste manier om dit te doen is om de Thonny IDE te gebruiken (voorgeïnstalleerd op Raspbian).

Als u geen Raspberry Pi gebruikt om uw Pico te programmeren of als u MicroPython nog nooit op de Pico hebt gebruikt, raadpleeg dan de handleiding "Aan de slag met MicroPython" van Raspberry Pi https://www.raspberrypi.org/documentation/rp2040/getting-started/#getting-started-with-micropython

Als u Windows gebruikt, kijk dan eens naar deze blogpost over de Raspberry Pi Pico en MicroPython op Windows https://picockpit.com/raspberry-pi/raspberry-pi-pico-and-micropython-on-windows/

Sluit Thonny nadat je je Pico hebt geflashed met de MicroPython firmware en installeer rshell. We gebruiken rshell om toegang te krijgen tot het bestandssysteem vanaf de commandoregel.

sudo pip3 install rshell

rshell -versie

Dit drukt de rhsell versie af als alles juist is ingesteld. Trek dan de stekker van de pico uit het stopcontact en steek hem er weer in (zonder de BOOTSEL knop ingedrukt te houden) om er zeker van te zijn dat niets toegang probeert te krijgen tot het bestandssysteem. Nu moeten we het volgende uitvoeren

rshell -p /dev/ttyACM0 -buffer-grootte 512

cp factfib.mpy /pyboard/factfib.mpy

Om de installatie te testen kunt u rshell of de Thonny IDE gebruiken om uw .py bestanden op de Pico, maar ik zal demonstreren hoe je de MicroPython interpreter over de minicom gebruikt.

Dus druk eerst op Ctrl+c om rshell te verlaten en dan minicom te installeren via

sudo apt install minicom

nu hebben we toegang tot de Picos REPL (Read-eval-print loop)

minicom -o -D /dev/ttyACM0

De drie afsluitende haakjes >>> geven aan dat de MicroPython interpreter draait. Nu kunnen we onze uitbreiding importeren en er zoals gewoonlijk mee werken.

>>> importeer factfib als ff

>>> ff.factorial(5)

>>> 120

>>> ff.fibonacci(7)

>>> 13

Gefeliciteerd! U heeft uw eerste MicroPython C uitbreiding voor de Pico gemaakt! De volgende stap is het leren schrijven en compileren van complexere modules. Een goede manier om te beginnen is door te testen hoe de Marshalling van lijsten en dicts werkt (zie de Marshalling webpagina van hierboven). Als u vragen heeft over deze post, voel u dan vrij om een commentaar te schrijven.

Tot ziens en tot de volgende keer

Nathan

2 Opmerkingen

  1. PeterB op november 26, 2021 op 8:29 am

    Afgezien van de fout in het c-programma werkte het prima. Bedankt.

    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);
    geef mp_obj_new_int(rslt) terug;
    }

    • raspi berry op november 27, 2021 op 5:56 pm

      Hartelijk dank voor uw feedback 🙂 Dank u.

Laat een reactie achter