M5Stack用MicroPythonのビルドとカスタマイズ


はじめに

M5StackでMicroPythonを使った開発を行うためのMicroPythonのファームウェアのビルド済みイメージ・ファイルは、M5Stackから提供されています。
これらのファームウェアは M5Burner に含まれており、M5Burnerを使ってM5Stackに書き込んで使うことができます。

M5Stackの公式MicroPythonファームウェアは、M5Cloudや UI.Flow を使って開発することを目的として調整されています。そのため、ベースとなったMicroPythonの実装にある機能がすべて有効になっているわけではありません。
こういった機能を有効化するなどのカスタマイズを行うためには、MicroPythonを自分でビルドする必要があります。

M5Stackで使われているカスタム版MicroPythonのソースコードは、GitHubの リポジトリ から入手可能です。

カスタマイズとビルド

Windowsでのビルド環境の構築

ESP-IDFを使う環境

ESP32用MicroPythonはESP-IDFでビルドできるように作られているので、基本的に WindowsでのESP-IDFの開発環境を構築する手順と同様です。
ESP-IDFの公式ドキュメントに セットアップ手順 が記載されているので、この手順でセットアップを行います。

ドキュメントにあるリンクをたどって、Espressifの公式ページからWindows用 all-in-one パッケージをダウンロードします。執筆時点では  https://dl.espressif.com/dl/esp32_win32_msys2_environment_and_toolchain-20181001.zip です。

ダウンロードしたら適当な場所に展開しておきます。パスにスペースや日本語を含まない場所が無難です。

シンボリック・リンクを扱うための設定

MicroPythonのリポジトリでシンボリック・リンクを使っているため、シンボリック・リンクを使えるように設定する必要があります。

Windows 10 April 2018 Update (1803) 以降は、デフォルトでシンボリック・リンクを作成する権限の設定が行われているようですが、それ以前のバージョンでは権限の設定が必要になるようです。筆者は1803でしか試していないので、この作業は行っていません。
検索すると手順を説明している記事がでてきますので、そちらを参考に設定してください。

ビルド環境である MSYS2 はデフォルトではWindowsのシンボリック・リンク機能を使わない設定になっていますので、設定を変更します。
ESP-IDFのall-in-oneパッケージを展開したディレクトリにある mingw32.ini をエディタで開き、MSYS=winsymlinks:nativestrictを設定している行のコメント・アウトを解除します。

MSYS=winsymlinks:nativestrict
#MSYS=error_start:mingw64/bin/qtcreator.exe|-debug|<process-id>
#CHERE_INVOKING=1
#MSYS2_PATH_TYPE=inherit
MSYSTEM=MINGW32

また、Windows用のGit自体もシンボリック・リンクを使わない設定になっているため、設定を変更する必要があります。

git config --global core.symlinks true

ソースコードの取得と設定

GitHub上に M5Stack_MicroPython としてM5Stack用MicroPythonがアップロードされています。

公式のMicroPythonのBoris Lovosevic氏によるESP32向けカスタム版として MicroPython_ESP32_psRAM_LoBo があります。
M5Stack_MicroPython は MicroPython_ESP32_psRAM_LoBo フォークしてM5Stack向けの機能を追加したものになっています。

ESP-IDFのall-in-oneパッケージを展開したディレクトリにある mingw32.exe を実行して開いたターミナルで適当なディレクトリに移動して M5Stack_MicroPython リポジトリを clone します。

git clone https://github.com/m5stack/M5Stack_MicroPython.git

ビルド用のスクリプトが MicroPython_BUILD/BUILD.sh にあるので、MicroPython_BUILD ディレクトリに移動して以下のとおり呼び出して、MicroPythonの設定を行います。

cd MicroPython_BUILD
./BUILD.sh menuconfig

しばらくすると、ESP-IDFのプロジェクト設定の画面が表示されます。

MicroPython エントリの下に、MicroPythonの各種設定項目が含まれています。

さすがに全設定項目は説明しきれませんので、筆者がよく設定する項目についてのみ説明します。選択式の設定項目の場合の設定値は、Y が選択、N が非選択を意味することとします。

グループ 名前 設定値 内容
MicroPython/System settings Enable Ftp Server Y FTPサーバ機能を有効にする
MicroPython/Modules Use Curl module Y curlモジュールを有効にする
Compiler options Optimization Level Release (-Os) リリース用に最適化を行う
Component config/ESP32-specific Support for external, SPI-connected RAM Y PSRAMを有効にする
Component config/ESP32-specific/SPI RAM config Ignore PSRAM when not found Y PSRAMが見つからなかってもpanicせずにPSRAMを無効化して起動する
Component config/ESP32-specific Panic handler behavior Invoke GDBStub panic時にGDB Stubを起動する
  • MicroPython/System settings/Enable Ftp Server

    MicroPython_ESP32_psRAM_LoBo に実装されている FTPサーバ機能 を有効化します。 network.ftp 以下のメンバーからFTPサーバ機能を操作できるようになります。

  • MicroPython/Modules/Use Curl module

    MicroPython_ESP32_psRAM_LoBo に実装されている libcurlによるHTTP/FTP/SMTPを使ったネットワーク・アクセス機能を有効化します。
    import curlとしてcurlモジュール を読み込んで使います。

  • Compiler options/Optimization Level

    コンパイル時の最適化レベルを設定します。デバッグ中は -OgにしておくとバグなどでMicroPython自体がクラッシュしたときに原因を探りやすくなります。リリース時は -Os にしておくと、MicroPythonのファームウェアのサイズが小さくなり、動作速度を改善する各種最適化が有効になります。
    MicroPythonユーザーとしては -Os にしておくのがよいでしょう。

  • Component config/ESP32-specific/Support for external, SPI-connected RAM

  • Component config/ESP32-specific/SPI RAM config/Ignore PSRAM when not found

    M5Stack FIREなどに搭載されている外付けSRAM (PSRAM) を有効にするための設定です。通常PSRAMを有効化している場合にPSRAMが見つからなければ、その時点でpanicします。Ignore PSRAM when not found を入れておくことにより、PSRAMが見つからない場合もpanicせずにPSRAMが無効なものとして起動します。

  • Component config/ESP32-specific/Panic handler behavior

    ファームウェアがpanicしたときの挙動を設定します。デフォルトはデバッグ出力にpanic時のレジスタの値やスタック・トレースを出力して動作を停止します。panic時にデバッガを接続できる状態にしたい場合は、Invoke GDBStubを選択しておきます。この場合panic時にGDBを接続するためのデバッグ・スタブが実行され、シリアルポート経由でGDBを接続してpanic時の状態を調査することができます。

ビルドと書き込み

MicroPythonの設定が終わったら、ビルドを行います。

./BUILD.sh all -j9 -v

-j9の部分はmakeコマンドと同様ビルドの並列実行数を指定するオプションです。ビルド環境のPCの性能に応じて適宜数字を増減してください。

-vオプションを指定すると、ビルド中のメッセージがコンソールに出力されます。-vを付けないと、一切メッセージが表示されずビルドの進捗状況がわからないので、つけておくことをお勧めします。

ビルドが終わったら、flashコマンドとflashfsコマンドを実行してファームウェアとSPIFFSのイメージを書き込みます。

ESPPORT=COM6 ./BUILD.sh flash
ESPPORT=COM6 ./BUILD.sh flashfs

ESPPORT環境変数で書き込み先のM5Stackが接続されているシリアル・ポートの名前を指定します。例ではCOM6に接続されている場合としてESPPORT=COM6 を指定しています。

書き込み完了後はブートローダ起動状態のままとなりますので、リセットボタンを押すかシリアルポートを開くなどしてリセットを行います。

以下の例では、ESP-IDFに付属している IDF monitorを起動してリセットとデバッグ・メッセージの表示を行います。

ESPPORT=COM6 ./BUILD.sh monitor

スクリプトの転送

カスタムビルド版のMicroPythonでは、M5GOやM5Stack FIREの出荷時イメージのように、起動直後に実行されるスクリプトが含まれていません。
このため、スクリプトの転送には M5Cloud や UI.Flow を使うことができません。
また、Wi-Fi APとして起動するようにもなっていないので、どうにかしてWi-Fiの接続設定を行う必要があります。

イメージを書き込んだ直後は、自動実行されるスクリプトが含まれていないため、MicroPythonがREPLの状態になります。この状態でユーザはプログラムを手動で入力してnetworkモジュールを操作してWi-Fi接続を行うことは可能です。

ただし、さすがに毎回手動で設定するのは面倒ですので、アクセスポイントへの接続とFTPサーバの起動までを行うスクリプトを用意しておき、REPLのペーストモードで入力して実行します。
スクリプトはGistに置いてあります。

REPLのプロンプト >>> が出ている状態で Ctrl+E を押すとペーストモードになります。この状態でクリップボードからコピー(TeraTermの場合はマウス右クリック) を行って、コピーが終わったら Ctrl+D を押してペーストモードを抜けます。これにより、複数行のスクリプトを効率よく入力して実行することができます。

Wi-Fi APに接続後、割り当てられたIPアドレスを表示し、FTPサーバを起動しています。

あとはWinSCPなどのFTPクライアントを使って実行したいスクリプトを転送します。

転送したスクリプトのうち、appconfig.pyにWi-Fiの接続設定などを書いてあるため、リセット後は自動的にアクセスポイントに接続し、動作を開始します。

ファームウェア書き込み時にスクリプトを書き込む方法

BUILD.sh flashfs で書き込まれるSPIFFSのイメージの内容は MicroPython_BUILD/components/internalfs_image/image ディレクトリの内容です。初回書き込み時からあらかじめ入れておきたいスクリプトやデータはここに置いておくと便利です。

コンパイル済みスクリプトの追加

MicroPython_BUILD/components/micropython/esp32/modules に含まれているPythonスクリプトは、MicroPythonのビルド時にバイトコードに変換された状態で組み込まれます。このため、滅多に変更しないスクリプトやサイズの大きいスクリプトはここに置いておくことにより、ESP32上でのバイトコードへの変換を行わずに済みます。

同様に、mpy-crossツールを手動で呼び出すことにより、任意のMicroPythonスクリプトをホスト上でバイトコードに変換しておくことができます。
以下の例では、main.pyをバイトコードにコンパイルして main.mpy を生成します。

MicroPython_BUILD/components/micropython/mpy-cross/mpy-cross.exe main.py

コンパイルした*.mpy ファイルは*.pyと同様にimportできますので、FTP経由などでM5Stackにコピーして実行できます。

おわりに

以上でM5Stack用MicroPythonをカスタマイズしたものをM5Stackで動作させる手順は終わりです。

MicroPythonはいろいろカスタマイズの余地がありますので、設定を変更したり、パフォーマンスが足りない部分をC言語で記述したりして有効活用していければと思います。