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のような)計算量の多いタスクにはあまり適していません。一方で、C言語はそのようなタスクにとても適しています。Micropython用のC言語拡張は、C言語を使って計算を行い、その結果をMicroPythonで利用することができます。これにより、いくつかの処理は桁違いに速くなります。

もう一つの理由は、C言語のAPIを使っているハードウェアをMicroPythonでインターフェースしたいということです。 

MicroPython C拡張の種類

MicroPythonを拡張するにはいくつかの方法があります。外部Cモジュールと.mpyファイルのネイティブマシンコードです。

外部のCモジュールを実行するには、それをMicroPythonファームウェアに再コンパイルする必要があります。これはかなり複雑な作業なので、このガイドでは2つ目の方法を紹介します。この方法に興味がある方は、以下のページで詳細をご覧ください。                https://docs.micropython.org/en/latest/develop/cmodules.html                      https://www.raspberrypi.org/forums/viewtopic.php?t=300352

.mpyはコンパイル済みのネイティブマシンコードを格納したファイルで、動的にリンクすることができます。これにより、MicroPythonのファームウェア全体を再コンパイルする必要がないため、柔軟性が高くなります。

拡張モジュールの書き込み

拡張モジュールを書くことは、MicroPythonを拡張する上で最も簡単なことです。簡単な例を見ながら、その方法を紹介します。まず始めに、新しいディレクトリを作成します。 ファクトフィブ.新しいターミナルウィンドウを開き、新しいディレクトリにcdで移動し、新しいファイル FACTFIB.C.Dekstop配下のRaspberry Piでディレクトリを作成した場合、コマンドは以下のようになります。

cd ~/Desktop/factfib

touch factfib.c

オープン FACTFIB.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);
   rsltを返す。
}

STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);

STATIC mp_int_t fibonacci_helper(mp_int_t x) { 以下のようになります。
   もし (x <= 0) {
      0を返します。
   }
   else if (x == 1) {
      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型に変換する必要があります。これはマーシャルと呼ばれ、MicroPythonにはオブジェクトから任意のC型を抽出する関数が用意されています。

オリバー・ロブソンのこのウェブページは、マーシャルにとても役立ちます。 https://mpy-c-gen.oliverrobson.tech/.さらに、MicroPythonのドキュメントにマーシャルの例があります。 https://docs.micropython.org/en/latest/develop/natmod.html.さらに詳しい説明が必要な場合は、この記事を読むことをお勧めします。

エクステンションの構築

Makefileを使って、拡張機能を.mpyファイルにビルドします。しかし、その前にいくつかのことを設定する必要があります。ターミナルが ファクトフィブ ディレクトリを作成します。そして、MicroPythonのGitHubリポジトリをクローンします。

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

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

pip3 インストール 'pyelftools>=0.25' です。

これらのインストールには時間がかかりますが、時間を節約したい場合や自分のやっていることがわかっている場合には、micropythonのリポジトリから/pyと/toolsディレクトリをクローンして、それらを マイクロパイソン の中のフォルダです。 ファクトフィブ フォルダを作成します(2つ目のコマンドは省略)。

インストールを実行している間に、Makefileを書くことができます。単に

touch Makefile

をクリックし、新しく作成したファイルをテキストエディターで開きます。 

MPY_DIR = micropython

MOD = factfib

SRC = factfib.c

アーチ = armv7m

インクルード $(MPY_DIR)/py/dynruntime.mk

を設定していることに気付いたかもしれません。 アーチ への変数です。 armv7m とはいえ、ピコは armv6m.これをしなければならないのは armv6m のアーキテクチャは、(この記事を書いている時点では)サポートされていません。 dynruntime.mk ツールを使用しています。

しかし、幸いなことに、Pico 用の拡張機能をコンパイルすることができます。そのためには dynruntime.mk の下にあるはずのファイルです。 micropython/py/dynruntime.mkそれを開き、armv7mのArchitecture configurationの下にあるCFLAGS変数を見つけます(64行目のはず)。変更 -mcpu=cortex-m3 にしています。 -mcpu=cortex-m0 をクリックして保存します。

chnge -mcpu=cortex-m3 to -mcpu=cortex-m0

そして、すべてがインストールされた後に

作る

とのことです。 ファクトフィブ.mpy ファイルが作成されます。

エクステンションのインストールとテスト

最後のステップは、インストールとテストです。ここではMicropythonがRaspberry Pi Pico上に作成するファイルシステムを利用します。これを行う最も簡単な方法は、RaspbianにプリインストールされているThonny IDEを使うことです。

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 on Windowsについてのブログ記事をご覧ください。 https://picockpit.com/raspberry-pi/raspberry-pi-pico-and-micropython-on-windows/

Pico に MicroPython ファームウェアをフラッシュした後に Thonny を終了し、rshell をインストールします。rshellはコマンドラインからファイルシステムにアクセスするために使います。

sudo pip3 install rshell

rshell -バージョン

これにより、すべてが正しく設定されていれば、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(Read-eval-print loop)にアクセスできるようになりました。

minicom -o -D /dev/ttyACM0

3つの閉じた角括弧 >>> は、MicroPythonインタープリタが実行されていることを示しています。これで、拡張モジュールをインポートして、いつものように作業できるようになりました。

>>> import factfib as ff

>>> ff.factorial(5)

>>> 120

>>> ff.fibonacci(7)

>>> 13

おめでとうございます。あなたはPico用の最初のMicroPython C拡張を作成しました!次のステップは、より複雑なモジュールの書き方やコンパイルの仕方を学ぶことです。まずはリストやディクショナリーのマーシャリングがどのように機能するかをテストするのがよいでしょう(上記のMarshallingのウェブページを参照)。この記事について何かご質問がありましたら、お気軽にコメントをお寄せください。

サヨナラ、そして次の機会まで

ネイサン

2 コメント

  1. PeterB on 11月 26, 2021 at 8:29 am となります。

    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) を返します。
    }

    • raspi berry on 11月 27, 2021 at 5:56 pm となります。

      フィードバックをありがとうございました。

コメントを残す