在Raspberry Pi Pico上为MicroPython提供C语言扩展

这是一份关于如何在Raspberry Pi Pico上编写和运行MicroPython的基本C语言扩展的指南。我将介绍扩展MicroPython的原因,如何编写扩展模块,如何编译以及如何在Pico上安装它。如果你想阅读更多关于这个主题的内容,请参考 https://docs.micropython.org/en/latest/develop/extendingmicropython.html

简介

为什么要扩展MicroPython?

你可能想扩展MicroPython,这可能有多种原因。由于MicroPython是Python的精简版,当涉及到计算量大的任务时(类似于Python),MicroPython的表现不是很好。另一方面,C语言确实很适合此类任务。Micropython的C语言扩展使你能够通过C语言进行这些计算,并在MicroPython中使用这些结果。这可以使一些程序的速度提高一个数量级。

第二个原因可能是,你想在MicroPython中连接一些使用C语言API的硬件。 

MicroPython C语言扩展的类型

有几种不同的方式来扩展MicroPython:外部C模块和.py文件中的本地机器代码。

要运行一个外部C模块,你需要把它重新编译到MicroPython固件中。这是一个相当复杂的过程,这就是为什么本指南将重点介绍第二种方法。如果你对这种方法感兴趣,你可以在这些网页上阅读更多信息。                https://docs.micropython.org/en/latest/develop/cmodules.html                      https://www.raspberrypi.org/forums/viewtopic.php?t=300352

.py是一个存储已编译的本地机器代码的文件,可以动态链接。这使得它更加灵活,因为你不需要重新编译整个MicroPython固件。

编写扩展模块

编写扩展模块是扩展MicroPython的最简单的部分。我将通过一个简单的例子来告诉你如何做。首先,我们将创建一个新的目录,名为 事实fib.打开一个新的终端窗口,cd进入新目录,并创建一个新的文件,名为 事实fib.c.如果你在Dekstop下的Raspberry Pi上创建了该目录,该命令看起来像这样。

cd ~/Desktop/factfib

触摸 factfib.c

开放式 事实fib.c 在你喜欢的文本编辑器中,输入以下代码

#include "py/dynruntime.h

STATIC mp_int_t factorial_helper(mp_int_t x) {
   如果(x < 1) {
      返回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) {
   如果(x <= 0) {
      返回0。
   }
   否则如果(x == 1) {
      返回1。
   }
   否则 {
      返回(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类型的函数。

奥利弗-罗布森的这个网页对法警工作很有帮助。 https://mpy-c-gen.oliverrobson.tech/.此外,你可以在MicroPython文档中找到调集的例子 https://docs.micropython.org/en/latest/develop/natmod.html.如果你需要进一步解释,我建议你阅读这篇文章。

构建扩展

我们通过使用Makefile将扩展程序构建成一个.mpy文件。但我们需要先设置一些东西。确保你的终端仍然打开在 事实fib 目录。然后克隆MicroPython的GitHub仓库。

sudo apt-get install build-essential libreadline-dev libffi-dev git pkg-config gcc-arm-one-eabi libnewlib-arm-one-eabi

git clone -recurse-submodules https://github.com/micropython/micropython.git

pip3 安装 'pyelftools>=0.25'

这些安装会花费一些时间,如果你想节省时间并且知道自己在做什么,你只需要从micropython仓库克隆/py和/tools目录,然后把它们放在一个 微软 文件夹内的 事实fib 文件夹(跳过第二个命令)。

在安装过程中,我们可以利用这段时间来编写Makefile。只需执行

触摸Makefile

并在一个文本编辑器中打开新创建的文件。 

MPY_DIR = micropython

MOD = factfib

SRC = factfib.c

ARCH = armv7m

include $(MPY_DIR)/py/dynruntime.mk

你可能已经注意到,我们将 ARCH 变量为 armv7m 虽然皮克是 armv6m.我们必须这样做,因为 armv6m 架构(在我写这篇文章的时候)不支持 dynruntime.mk 工具。

但幸运的是,我们仍然可以为Pico编译一个有效的扩展。我们只需要修改 dynruntime.mk 文件,它应该位于 micropython/py/dynruntime.mk打开它并在armv7m的架构配置下找到CFLAGS变量(应该是第64行)。改变 -mcpu=cortex-m3 至 -mcpu=cortex-m0 并保存该文件。

将-mcpu=cortex-m3改为-mcpu=cortex-m0

然后在一切安装完毕后,执行

使

和 事实fib.mpy 文件将被创建。

安装并测试该扩展

最后一步是安装和测试。为此我们利用Micropython在Raspberry Pi Pico上创建的文件系统。首先,我们需要用MicroPython固件对Pico进行闪存。最简单的方法是使用Thonny IDE(预装在Raspbian上)。

如果你没有使用Raspberry Pi为你的Pico编程,或者你以前从未在Pico上使用过MicroPython,那么请参考Raspberry Pi的MicroPython入门指南。 https://www.raspberrypi.org/documentation/rp2040/getting-started/#getting-started-with-micropython

如果你使用的是Windows,你应该看看这篇关于Raspberry Pi Pico和MicroPython在Windows上的博文。 https://picockpit.com/raspberry-pi/raspberry-pi-pico-and-micropython-on-windows/

在你用MicroPython固件刷新你的Pico后,关闭Thonny,并安装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 文件,但我将演示如何在minicom上使用MicroPython解释器。

因此,首先按 Ctrl+c 来离开rshell,然后通过以下方式安装minicom

sudo apt install minicom

现在我们可以访问Picos REPL(读取-评估-打印循环)。

minicom -o -D /dev/ttyACM0

三个结尾的角括号 >>> 表示MicroPython解释器正在运行。现在我们可以导入我们的扩展并像往常一样使用它。

>>>导入 factfib 作为 ff

>>> ff.阶乘(5)

>>> 120

>> ff.fibonacci(7)

>>> 13

恭喜你!你已经为Pico创建了第一个MicroPython C语言扩展。你已经为Pico创建了你的第一个MicroPython C语言扩展!下一步是学习如何编写和编译更复杂的模块。一个好的开始是测试列表和数据集如何工作(见上面的 Marshalling 网页)。如果你对这篇文章有任何疑问,欢迎写下评论。

再见,直到下一次

内森

2评论

  1. PeterB 在11 月 26, 2021在8:29 上午

    除了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);
    返回mp_obj_new_int(rslt)。
    }

发表评论