M5Burner v3のUser Customで配布できるバイナリファイルを用意する

# はじめに

M5Stack用のツールM5Burner v3には、「User Custom」というタブが用意され、ユーザーが独自に提供するファームウェアを配布できるようになっています。公式なドキュメントは今のところ公開されていないようなので推測に基づくものではありますが、以下のようにすることにより、独自のファームウェアを配布できます。

この記事が前提としている前提条件は次の通りです。

- Arduino IDEでM5Stack用ファームウェアをビルドできる
- Terminalなどコマンドラインでの基本的な操作ができる

動作確認を行った環境は次の通りです。

- macOS Monterey v12.4
- Arduino IDE v1.8.19
- M5Stack v2.0.3

# M5Burner v3のShare Code機能について

まず、M5Burner v3のShare Code機能の使い方について簡単に説明します。

## 配布元での作業

1. M5Burnerを起動する
2. 左下の［User Custom］タブをクリックする
3. 「You must be logged in to manage your firmware.」（ファームウェアを管理するには、ログインする必要があります。）と表示されるので、[M5Stack Community](https://community.m5stack.com/)のアカウントを（持っていなければ作成して）ログインする
4. ［Publish］ボタンをクリックし、続いて表示される「Publish Firmware」ダイアログで必要な情報を入力し、［Upload］ボタンを押して閉じる

<img width="50%" alt="「Publish Firmware」ダイアログに入力する項目の説明" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92577/c6629d13-c1b9-2991-c8b5-bdb2ab086556.png">

図1：「Publish Firmware」ダイアログに入力する項目の説明

以上のような手順により、配布先にArduino IDEなど開発環境のセットアップを要求する必要なくファームウェアを配布できます。配布先の手順は次のようになります。

## 配布先での作業

1. M5Burnerをダウンロードする
2. M5Burner上部の「Search」にファームウェアの名前の一部または全部を入力する
3. 表示された候補の中から該当するファームウェアを選択し、［Download］ボタンをクリックしてダウンロードする
4. ダウンロードが完了したら、［Burn］ボタンをクリックしてM5Stackに書き込む

# 配布用バイナリの作成について

## M5Burner v3で作成する方法

M5Burner v3の最新版より、画面上部のメニューから［Firmware Exporter］を実行することにより、シリアルで接続したM5Stackからファームウェアを吸い出せるようになりました。

![「Firmware Exporter」を含むメニューの画面例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92577/21aaf908-1058-615f-337b-fcc1e7c4ed47.png)

図2：「Firmware Exporter」を含むメニューの画面例

## Arduino IDEで作成する方法

次に、配布用バイナリの作成について説明します。作成にはEspressif Systemsが配布するツール「[esptool.py](https://docs.espressif.com/projects/esptool/en/latest/esp32/esptool/index.html)」を使います。このツールは、Arduino IDEにM5Stackボードを追加した際にインストールされています。

1. Arduino IDEの「環境設定」→「より詳細な情報を表示する」→「書き込み」をチェックする
2. M5Stackに書き込む
3. Arduino IDEに表示されたログをテキストエディタにコピー＆ペーストする
4. esptool.pyを用いてアップロードしている部分を見つけ、書き込み（`write_flash`）ではなくバイナリをマージ（`merge_bin`）するよう変更する
5. 変更したコマンドをTerminalで実行する

アップロードしている部分は次のようになっていると思います（`--flash_size 16MB`の部分は使用しているモデルによって異なり、これはM5Stack Fireの例です）。

```shell-session
/{esptoolのパス}/esptool --chip esp32 --port /dev/cu.usbserial-******** --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 16MB 0x1000 {0x1000に書き込むバイナリファイルのパス} ...（以下続く）
```

これを次のように変更することにより、Arduino IDEが書き込みの準備段階で生成したバイナリファイルをマージして、M5Burner v3で配布できる単一のバイナリファイルを作成できます。

```shell-session
/{esptoolのパス}/esptool --chip esp32 merge_bin -o {マージ後のファイル名.bin} --flash_mode dio --flash_size 16MB 0x1000 {0x1000に書き込むバイナリファイルのパス} ...（以下続く）
```

なお、これらの作業はArduino IDEを起動したまま行う必要があります。Arduino IDEの終了時にテンポラリフォルダは消去されてしまうからです。

繰り返しこの作業を行う場合は、次のようにしてビルドパスを固定しておくと、シェルスクリプトなどによる自動化がやりやすくなるでしょう。

1. Arduino IDEの「環境設定」を開く
2. `preferences.txt`の場所を確認する
3. Arduino IDEを一旦終了する
4. `preferences.txt`の最後に`build.path`の設定を追加する（例：`build.path=/Users/username/Documents/arduino_build`）

# 非公開状態での共有

最初に説明したのはファームウェアを公開する方法でした。そうではなく、公開する前にテストを依頼し、確認した上で公開したいという場合があるかもしれません。その場合には、次のような手順を取ることにより、非公開のまま共有用コードを知る人たちの間でのみ配布することができます。

## 配布元での作業

1. M5Burnerを起動する
2. 左下の［User Custom］タブをクリックする
3. アップロードしたファームウェアの行にある［Unpublish］ボタンをクリックし、非公開状態へと変更する
4. 同じ行の［Share］ボタンをクリックし、続いて表示される「Share Code」ダイアログでShare Codeをコピーする
5. Share Codeを何らかの方法で配布先に伝える

## 配布先での作業

1. M5Burnerを起動する
2. 左下の［User Custom］タブをクリックする
3. 「You must be logged in to manage your firmware.」（ファームウェアを管理するには、ログインする必要があります。）と表示されるので、[M5Stack Community](https://community.m5stack.com/)のアカウントを（持っていなければ作成して）ログインする
4. ［Share Burn］ボタンをクリックし、続いて表示される「Share Burn」ダイアログに、受け取ったShare Codeを入力する
5. 必要に応じて「COM」をM5Stackに接続されているCOMポートに変更し、Share Codeの右側にあるアップロードボタンをクリックする

<img width="50%" alt="「Sahre Code」ダイアログの画面例" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92577/947ad6ac-5ea9-be02-2b5a-ea0be659878e.png">

図3：「Sahre Code」ダイアログの画面例

# レファレンス

- Espressif Systems. [Merge Binaries for Flashing: merge_bin](https://docs.espressif.com/projects/esptool/en/latest/esp32/esptool/basic-commands.html#merge-binaries-for-flashing-merge-bin)