Επέκταση C για MicroPython σε Raspberry Pi Pico
Αυτός είναι ένας οδηγός για το πώς να γράψετε και να εκτελέσετε μια βασική επέκταση C για το MicroPython στο Raspberry Pi Pico. Θα καλύψω τους λόγους για την επέκταση του MicroPython, πώς να γράψετε το module της επέκτασης, πώς να το μεταγλωττίσετε και πώς να το εγκαταστήσετε στο Pico. Αν θέλετε να διαβάσετε περισσότερα σχετικά με αυτό το θέμα, ανατρέξτε στη διεύθυνση https://docs.micropython.org/en/latest/develop/extendingmicropython.html
Εισαγωγή
Γιατί να επεκτείνετε το MicroPython;
Μπορεί να υπάρχουν πολλοί λόγοι για τους οποίους μπορεί να θέλετε να επεκτείνετε το MicroPython. Δεδομένου ότι είναι μια περικομμένη έκδοση της Python, η MicroPython δεν έχει πολύ καλές επιδόσεις όταν πρόκειται για υπολογιστικά βαριές εργασίες (παρόμοιες με την Python). Η C από την άλλη πλευρά είναι πραγματικά κατάλληλη για τέτοιες εργασίες. Μια επέκταση C για τη Micropython σας επιτρέπει να εκτελείτε αυτούς τους υπολογισμούς μέσω της γλώσσας C και να χρησιμοποιείτε τα αποτελέσματα στη MicroPython. Αυτό μπορεί να επιταχύνει ορισμένες διεργασίες κατά μια τάξη μεγέθους.
Ένας δεύτερος λόγος μπορεί να είναι ότι θέλετε να διασυνδέσετε κάποιο υλικό που χρησιμοποιεί API C μέσα από τη MicroPython.
Τύποι επεκτάσεων MicroPython C
Υπάρχουν δύο διαφορετικοί τρόποι επέκτασης του MicroPython : εξωτερικές ενότητες C και εγγενής κώδικας μηχανής σε αρχεία .mpy.
Για να εκτελέσετε μια εξωτερική ενότητα C πρέπει να την μεταγλωττίσετε εκ νέου στο υλικολογισμικό MicroPython. Αυτή είναι μια αρκετά περίπλοκη διαδικασία, γι' αυτό και αυτός ο οδηγός θα επικεντρωθεί στη δεύτερη εναλλακτική λύση. Αν ωστόσο σας ενδιαφέρει αυτή η προσέγγιση, μπορείτε να διαβάσετε περισσότερα γι' αυτήν σε αυτές τις ιστοσελίδες: https://docs.micropython.org/en/latest/develop/cmodules.html https://www.raspberrypi.org/forums/viewtopic.php?t=300352
Το .mpy είναι ένα αρχείο που αποθηκεύει μεταγλωττισμένο εγγενή κώδικα μηχανής και μπορεί να συνδεθεί δυναμικά. Αυτό το καθιστά πολύ πιο ευέλικτο, αφού δεν χρειάζεται να μεταγλωττίσετε εκ νέου ολόκληρο το firmware της MicroPython.
Γράψτε την ενότητα επέκτασης
Η συγγραφή της ενότητας επέκτασης είναι το ευκολότερο μέρος της επέκτασης του MicroPython. Θα σας δείξω πώς να το κάνετε εξετάζοντας ένα απλό παράδειγμα. Για να ξεκινήσουμε, θα δημιουργήσουμε έναν νέο κατάλογο με όνομα factfib. Ανοίξτε ένα νέο παράθυρο τερματικού, πηγαίνετε με cd στο νέο κατάλογο και δημιουργήστε ένα νέο αρχείο με όνομα factfib.c. Αν δημιουργήσατε τον κατάλογο σε ένα Raspberry Pi στο πλαίσιο του Dekstop, η εντολή μοιάζει ως εξής.
cd ~/Desktop/factfib
touch factfib.c
Ανοίξτε το factfib.c στον αγαπημένο σας επεξεργαστή κειμένου και εισάγετε τον ακόλουθο κώδικα:
#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
}
Επιτρέψτε μου να εξηγήσω τον παραπάνω κώδικα: Στην MicroPython και την Python, κάθε μεταβλητή είναι ένα αντικείμενο. Ως εκ τούτου, στη C τις αναπαριστούμε ως mp_obj_t. Αλλά ένα πρόγραμμα C μπορεί να δουλέψει μόνο με μεταβλητές τύπου C, γι' αυτό πρέπει να μετατρέψουμε το αντικείμενο σε τύπο C. Αυτό ονομάζεται Marshalling και το MicroPython παρέχει συναρτήσεις για την εξαγωγή οποιουδήποτε τύπου C από ένα αντικείμενο.
Αυτή η ιστοσελίδα του Oliver Robson είναι πραγματικά χρήσιμη για το Marshalling https://mpy-c-gen.oliverrobson.tech/. Επιπλέον μπορείτε να βρείτε παραδείγματα Marshalling στην τεκμηρίωση της MicroPython https://docs.micropython.org/en/latest/develop/natmod.html. Σας συμβουλεύω να διαβάσετε αυτό το άρθρο αν χρειάζεστε περισσότερες εξηγήσεις.
Κατασκευάστε την επέκταση
Δημιουργούμε την επέκταση σε ένα αρχείο .mpy χρησιμοποιώντας ένα Makefile. Αλλά πρέπει πρώτα να ρυθμίσουμε μερικά πράγματα. Βεβαιωθείτε ότι το τερματικό σας είναι ακόμα ανοιχτό στο factfib κατάλογο. Στη συνέχεια, κλωνοποιήστε το αποθετήριο MicroPython GitHub.
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'
Αυτές οι εγκαταστάσεις θα πάρουν αρκετή ώρα, αν θέλετε να εξοικονομήσετε χρόνο και ξέρετε τι κάνετε, το μόνο που χρειάζεται είναι να κλωνοποιήσετε τον κατάλογο /py και /tools από το αποθετήριο micropython και να τα τοποθετήσετε μέσα σε ένα micropython φάκελο μέσα στο factfib (παραλείψτε τη δεύτερη εντολή).
Ενώ η εγκατάσταση εκτελείται, μπορούμε να χρησιμοποιήσουμε το χρόνο για να γράψουμε το Makefile. Απλά εκτελέστε
touch Makefile
και ανοίξτε το νεοδημιουργημένο αρχείο σε έναν επεξεργαστή κειμένου.
MPY_DIR = micropython
MOD = factfib
SRC = factfib.c
ARCH = armv7m
include $(MPY_DIR)/py/dynruntime.mk
Ίσως έχετε παρατηρήσει ότι ορίσαμε το ARCH μεταβλητή σε armv7m αν και το pico είναι armv6m. Πρέπει να το κάνουμε αυτό γιατί η armv6m αρχιτεκτονική δεν υποστηρίζεται (τη στιγμή που γράφω αυτό το άρθρο) από το dynruntime.mk εργαλείο.
Αλλά ευτυχώς μπορούμε ακόμα να συντάξουμε μια επέκταση που λειτουργεί για το Pico. Απλά πρέπει να τροποποιήσουμε το dynruntime.mk αρχείο, το οποίο θα πρέπει να βρίσκεται κάτω από micropython/py/dynruntime.mk. Ανοίξτε το και στην ενότητα Architecture configuration στο armv7m βρείτε τη μεταβλητή CFLAGS (θα πρέπει να είναι στη γραμμή 64). Αλλάξτε το -mcpu=cortex-m3 στο -mcpu=cortex-m0 και αποθηκεύστε το αρχείο.
Στη συνέχεια, αφού εγκατασταθούν όλα, εκτελέστε
make
και το factfib.mpy θα δημιουργηθεί το αρχείο.
Εγκατάσταση και δοκιμή της επέκτασης
Το τελευταίο βήμα είναι η εγκατάσταση και η δοκιμή. Για το σκοπό αυτό χρησιμοποιούμε το σύστημα αρχείων που δημιουργεί το Micropython στο Raspberry Pi Pico. Πρώτα πρέπει να κάνουμε flash στο Pico με το firmware της MicroPython. ο ευκολότερος τρόπος για να το κάνουμε αυτό είναι να χρησιμοποιήσουμε το Thonny IDE (προεγκατεστημένο στο Raspbian/Raspberry Pi OS).
Εάν δεν χρησιμοποιείτε ένα Raspberry Pi για να προγραμματίσετε το Pico ή εάν δεν έχετε χρησιμοποιήσει ποτέ πριν το MicroPython στο Pico, τότε ανατρέξτε στον οδηγό για τα πρώτα βήματα με το MicroPython από το Raspberry Pi. https://www.raspberrypi.org/documentation/rp2040/getting-started/#getting-started-with-micropython
Αν χρησιμοποιείτε Windows θα πρέπει να ελέγξετε αυτό το blog Post σχετικά με το Raspberry Pi Pico και MicroPython στα Windows https://picockpit.com/raspberry-pi/raspberry-pi-pico-and-micropython-on-windows/
Κλείστε το Thonny μετά την αναβάθμιση του Pico με το υλικολογισμικό MicroPython και εγκαταστήστε το rshell. Χρησιμοποιούμε το rshell για να έχουμε πρόσβαση στο σύστημα αρχείων από τη γραμμή εντολών.
sudo pip3 install rshell
rshell --version
Αυτό εκτυπώνει την έκδοση rhsell αν όλα έχουν ρυθμιστεί σωστά. Στη συνέχεια, αποσυνδέστε το pico από την πρίζα και συνδέστε το ξανά (χωρίς να κρατάτε πατημένο το κουμπί BOOTSEL) για να βεβαιωθείτε ότι τίποτα δεν προσπαθεί να αποκτήσει πρόσβαση στο σύστημα αρχείων. Τώρα πρέπει να εκτελέσουμε
rshell -p /dev/ttyACM0 --buffer-size 512
cp factfib.mpy /pyboard/factfib.mpy
Για να δοκιμάσετε την εγκατάσταση μπορείτε να χρησιμοποιήσετε είτε το rshell είτε το Thonny IDE για να αποθηκεύσετε το .py αρχεία στο Pico, αλλά θα δείξω πώς να χρησιμοποιήσετε τον διερμηνέα MicroPython μέσω του minicom.
Οπότε πρώτα πατήστε Ctrl+c για να εγκαταλείψετε το rshell και στη συνέχεια να εγκαταστήσετε το minicom μέσω
sudo apt install minicom
τώρα μπορούμε να έχουμε πρόσβαση στο Picos REPL (Read-eval-print loop)
minicom -o -D /dev/ttyACM0
Οι τρεις κλειστές αγκύλες >>> υποδεικνύουν ότι ο διερμηνέας MicroPython εκτελείται. Τώρα μπορούμε να εισάγουμε την επέκτασή μας και να δουλέψουμε μαζί της ως συνήθως.
>>> import factfib as ff
>>> ff.factorial(5)
>>> 120
>>> ff.fibonacci(7)
>>> 13
Συγχαρητήρια! Δημιουργήσατε την πρώτη σας επέκταση MicroPython C για το Pico! Το επόμενο βήμα είναι να μάθετε πώς να γράφετε και να μεταγλωττίζετε πιο σύνθετες ενότητες. Ένας καλός τρόπος για να ξεκινήσετε είναι να δοκιμάσετε πώς λειτουργεί το Marshalling των λιστών και των dicts (δείτε την ιστοσελίδα Marshalling από πάνω).
Αν έχετε οποιεσδήποτε ερωτήσεις σχετικά με αυτή τη θέση, μη διστάσετε να γράψετε ένα σχόλιο.
Εκτός από το σφάλμα στο πρόγραμμα c λειτούργησε άψογα. Ευχαριστώ.
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 mp_obj_new_int(rslt),
}
Σας ευχαριστούμε για τα σχόλιά σας 🙂
Πώς να ρυθμίσετε το joomla που μπορεί να ανακτήσει τα δεδομένα από τη mysql;
Προσπάθησα να κάνω τα παραπάνω, αλλά διάφορα πράγματα δεν λειτουργούν όπως περιγράφεται:
- Ακολούθησα τις παραπάνω οδηγίες, πήρα το micropython, τροποποίησα το makefile όπως περιγράφεται
- Κάνω make (αλλά λαμβάνω ένα αρχείο factfib.native.mpy αντί για factfib.mpy)
- Αντιγράφω το αρχείο factfib.native.mpy στο pico ως factfib.mpy
(Δοκίμασα rshell αλλά πήρα ένα "timed out or error in transfer to remote: b"", αλλά θα μπορούσα να το αντιγράψω χρησιμοποιώντας Thonny)
- Μπορώ να εισαγάγω την ενότητα (στο thonny ή στο rshell - το ίδιο) χωρίς σφάλματα
- Προσπαθώ να τρέξω το "ff.fibonacci(5)", αλλά μετά λαμβάνω:
"Traceback (πιο πρόσφατη κλήση τελευταία):
Αρχείο "", γραμμή 1, σε
AttributeError: Το αντικείμενο 'module' δεν έχει το χαρακτηριστικό 'fibonacci'"
Τι κάνω λάθος;
Τελικά το καταφέρατε να λειτουργήσει;
Τώρα μπορείτε να μεταγλωττίσετε σε armv6, οπότε απλά αλλάξτε αυτή τη γραμμή στο Makefile και δεν χρειάζεται να αλλάξετε τον κώδικα micropython
ARCH = armv6m
Είχα μερικά σφάλματα κατά τη μεταγλώττιση του factfib.c, πού είναι οι διορθώσεις:
// λείπει το " στο τέλος.
#include "py/dynruntime.h"
// μετατροπή της τιμής επιστροφής σε mp_obj_t
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 mp_obj_new_int(rslt),
}
Σε ευχαριστώ για τις πληροφορίες, Paulo!
Ακολούθησα όλες τις οδηγίες και κατέληξα σε ένα αρχείο facfib.mpy. Χρησιμοποίησα
ARCH = armv6m
Όταν φορτώνεται στο Pico λαμβάνω αυτό το σφάλμα:
ValueError: ασύμβατο αρχείο .mpy
Το Pico μου απαιτεί τις ακόλουθες τιμές mpy:
έκδοση mpy: 6
υπο-έκδοση mpy: 2
σημαίες mpy: -march=armv6m
Ο έλεγχος των δύο πρώτων bytes του αρχείου δίνει την έκδοση 6 και την υπο-έκδοση 6.
Υπάρχει τρόπος να διορθωθεί αυτό, παρακαλώ;