Maixduinoでマルチブートする①

# はじめに

[Sipeed Maixduino](https://wiki.sipeed.com/en/maix/board/maixduino.html)などのK210用にloborisがブートローダー[Kboot](https://github.com/loboris/Kboot)を公開しているので使ってみます。

# Kbootについて

### Kbootのブートプロセス

Kbootのブートプロセスは下図のようになっています。

 1. stage #0
ブートROMのコードにより、stage #0のコードがフラッシュメモリからRAMの先頭に読み込まれる

 1. stage #1
Kbootのstage #0のコードにより、stage #1のコードがフラッシュメモリからRAMの上位に読み込まれる

 1. stage #2
Kbootのstage #1のコードにより、ブート構成（インデックス）を検索し、アクティブなアプリのコードがフラッシュメモリからRAMの先頭に読み込まれて、アプリを実行する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555397/2768db04-e1ce-6ca4-f1b2-50cf09a5314e.png)

### ブート構成（インデックス）

| 開始 | 終了 | 長さ | 内容 |
| ---: | ---: | ---: | :--- |
| `0x000` | `01F` | `32` | アプリケーションエントリー #0 |
| `0x020` | `03F` | `32` | アプリケーションエントリー #1 |
| `0x040` | `05F` | `32` | アプリケーションエントリー #2 |
| `0x060` | `07F` | `32` | アプリケーションエントリー #3 |
| `0x080` | `09F` | `32` | アプリケーションエントリー #4 |
| `0x0A0` | `0BF` | `32` | アプリケーションエントリー #5 |
| `0x0C0` | `0DF` | `32` | アプリケーションエントリー #6 |
| `0x0E0` | `0FF` | `32` | アプリケーションエントリー #7 |
| `0x100` | `103` | `4` | **構成フラグ** |
| `0x104` | `11F` | `4` | 予約 |
| `0x120` | `11F` | `4` | 未使用, ユーザーデータ |

各アプリケーションのエントリーの内容は次のようになっています。

| 開始 | 長さ | 内容 |
| ---: | ---: | :--- |
| `0` | `4` | 構成エントリー **ID** (ビット 4-31) + エントリー **フラグ** (ビット 0-4) |
| `4` | `4` | SPI フラッシュ内のアプリケーションアドレス |
| `8` | `4` | SPI フラッシュ内のアプリケーションサイズ. これはアプリケーションの **`.bin`** ファイルのサイズ |
| `12` | `4` | アプリケーションの CRC32 値 (32ビット) |
| `16` | `16` | アプリケーション名（Null で終了した文字列） |


### SPIフラッシュメモリのメモリマッピング

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555397/36ad29af-2d46-1e21-6ada-d69e16d535dc.png)

# インストール

インストールは[Kboot](https://github.com/loboris/Kboot)をダウンロード（クローン）し、buildディレクトリでktoolを使用します。

kboot.kfpkgには、ブートローダーとデフォルトのブート構成情報が入っています。

```bash:
git clone https://github.com/loboris/Kboot
cd build
# まずはこれ（bootloader_lo.bin bootloader_hi.bin, config.bin）
./ktool.py -p /dev/ttyUSB0 -b 2000000 kboot.kfpkg

# デフォルトアプリ
./ktool.py -p /dev/ttyUSB0 -a 65536 -b 2000000 default.bin

# MicroPython (FreeRTOS SDK)
./ktool.py -p /dev/ttyUSB0 -a 524288 -b 2000000 MicroPython.bin

# dvp_ov (Standalone SDK)
./ktool.py -p /dev/ttyUSB0 -a 2621440 -b 2000000 dvp_ov.bin

# maixpy (Standalone SDK)
./ktool.py -p /dev/ttyUSB0 -a 2621440 -b 2000000 maixpy.bin

```

Windowsの場合は、このようになります。ポートやボードは自動認識しますが、"-p COMxx" のように通信ポート、"-B goE" のようにボードを指定することもできます。

```bash:
git clone https://github.com/loboris/Kboot
cd build
# まずはこれ（bootloader_lo.bin bootloader_hi.bin, config.bin）
ktool.py -b 2000000 kboot.kfpkg

# デフォルトアプリ
./ktool.py -a 65536 -b 2000000 default.bin

# MicroPython (FreeRTOS SDK)
./ktool.py -a 524288 -b 2000000 MicroPython.bin

# dvp_ov (Standalone SDK)
./ktool.py -a 2621440 -b 2000000 dvp_ov.bin

# maixpy (Standalone SDK)
./ktool.py -a 2621440 -b 2000000 maixpy.bin

```

# 調整

Kbootは起動時にブート構成（インデックス）を読み込み、最初のアクティブなアプリを読み込んで起動します。デフォルトでは、起動時にK210のIO18(18pin)をGNDにするとアプリの一覧を表示して、シリアル接続のコンソールからアプリを選択することができます。

MaixduinoはIO18が端子に出ていないので、代わりにD9あたりを使いたくなります。その場合、MaixduinoのD7ピンはIO15なので、bootloader_hiのソース50行目の値を修正してリコンパイルします。

```c++:main.c
// Constants
/*
 * Pin used to enter interactive mode and request the user
 * to select which application to load
 * Any valid and not used K210 gpio can be used except gpio#16 (0 ~ 15 & 17 ~ 47)
 */
#define BOOT_PIN            18 <-- ここを15に修正する
#define GPIO_KEY            2

```

# PlatformIO

PlatformIOを使用している場合、そのままではフラッシュメモリの先頭にアプリをアップロードして、上記で設定した内容がすべて上書きされます。デフォルトアプリの場所（0x00010000）にアプリをアップロードするにはPlatformIOのプロジェクトのplatformio.iniを次のように設定します。

ktool.pyは C:\Users\<ユーザー>\.platformio\packages\ktool\ktool.py に配置した例です。

Windowsの場合ポートは-p COMxxで指定します（xxに数字が入ります。デバイスマネージャー等で確認してください）。ポートはKtoolが自動判定してくれますが、MaixduinoはK210とESP32用にポートが２つあるので指定が必要になることがあります。ボードは-B goEのように指定します。選択肢にMaixduinoもありますが、私の環境ではgoEを指定した方が成功します。

```platformio.ini
upload_flags =
    -a
    65536 
    -p
    COMxx
    -b
    2000000
    -B
    goE
upload_command = $PROJECT_PACKAGES_DIR/ktool/ktool.py $UPLOAD_FLAGS -t $SOURCE

```


# まとめ

Maixduinoのフラッシュメモリは6Mバイトあるので、Sipeed社のMaixPy、LoborisのMicroPython、その他のアプリを切り替えて実行することができます。

ESP32に関してはEspressif Systems社がフラッシュメモリの標準のパーティションマップを提供していますが、K210の場合はそれがないのでloborisのKbootのメモリマップが一つの参考になるかもしれません。