MicroPythonのZephyr移植版をNXP FRDM-K64Fで動作させてみた

# はじめに
MicroPythonをベアメタル(？)上でサポートしているNXPマイコンはRTに限られている．(各種移植されているプラットフォームについては[このページ](https://docs.micropython.org/en/latest/)参照)

だけど[Zephyr(RTOS)](https://www.zephyrproject.org)上のアプリケーションとしてなら，より多くのプラトフォームに移植されていて，使える品種がずっと増える．

Zephyrはその開発環境を準備して，MicroPythonをアプリケーションとしてビルドしなくてはならず，その手順の確認と作業が面倒でやってなかった．

今回はMicroPython v1.19.1を[FRDM K64F基板](https://www.nxp.jp/design/development-boards/freedom-development-boards/mcu-boards/freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F)用にビルドしてみたのでそのメモ

:::note
ここではFRDM-K64FでMicroPythonを走らせるためのファームウェア作成方法について説明しています．このようなステップは飛ばして，すぐにFRDM-K64FでMicroPythonを試したいヒト向けに，そのファームウェアといくつかのサンプルコードを用意しました．
ダウンロードは下のURLから．
https://github.com/teddokano/MicroPython_v1.19.1_zephyr-frdm_k64f
:::

![board.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288603/c88e6691-1ae9-367f-692a-2e77ed1aa003.jpeg)

# Zephyrのインストールと動作確認
## Zephyrのインストール

Zephyrの環境構築はこのページの通り進めれば問題なく完了できる．これを順にやっていく
https://docs.zephyrproject.org/latest/develop/getting_started/index.html

試してみたのは上記ページに書かれている**macOS**用の手順．

- [Install dependencies](https://docs.zephyrproject.org/latest/develop/getting_started/index.html#install-dependencies)の節．Homwbrewはすでにインストール済みだったので，そのステップは飛ばした
- [Get Zephyr and install Python dependencies](https://docs.zephyrproject.org/latest/develop/getting_started/index.html#get-zephyr-and-install-python-dependencies)の節．「Install within virtual environment」と「Install globally」のふたつのオプションでのインストール方法が書かれているが，「Install globally」で進めた
- M1シリコン搭載マシンを使ったので，SDKのダウンロードは注意書きにある通り「x86_64」を「aarch64」に置きかえて行った（たぶんx86_64のままでもOKなのだけど，せっかくなのでアップルシリコン用のものを使った）
https://docs.zephyrproject.org/latest/develop/getting_started/index.html#install-zephyr-sdk
- Zephyr SDKの展開先ディレクトリは`/opt`にした

SDKインストール後の
```
./setup.sh
```
の実行は，私はtcshを使っているのでそのままでは動かない．
なので一旦Bashを動かして実行した（`bash`のあと上記コマンドを実行して，そのあと`exit`して元のシェルに戻る）

## Zephyrの動作確認

### ビルド

ビルドは`~/zephyrproject/zephyr`ディレクトリで行うようになってるっぽい．
https://docs.zephyrproject.org/latest/develop/getting_started/index.html#build-the-blinky-sample

サンプルにあるコマンドの`<your-board-name>`にターゲット基板の名前を入れないといけない．
どこにこの名前の指定方法があるのかと探して，[こちらのページ](https://github.com/micropython/micropython/blob/master/ports/zephyr/README.md#building)の例を見つけた．これは「frdm_k64f」でOKだった．
以下のコマンドでビルドできた
```
west build -p always -b frdm_k64f samples/basic/blinky
```
のちに知ることになるのであるが，使えるボードの名称一覧は以下のコマンドで確認できる 
```
west boards
```

### フラッシュ書き込み

FRDM-K64F基板をPCに繋いでおく．基板にはマイクロUSBコネクタが2個用意されている．基板裏面のコネクタのある場所に「OpenSDA」「K64F USB」の表示がある．この「OpenSDA」側のコネクタを使う（このページ上部の写真のように接続）．

フラッシュの書き込みは[west flashで行うと書かれている](https://docs.zephyrproject.org/latest/develop/getting_started/index.html#flash-the-sample)が，実行してみるとPythonがエラーを吐いて実行できなかった．
...多分またどこかのインストール作業のステップを飛ばしてしまたかもしれない．これはあとで確認する

なので代わりにビルドできたバイナリを，Macのデスクトップ上にあるDAPLINKストレージアイコンにD&Dコピーした．
ビルドしたバイナリは`~/zephyrproject/zephyr/build/zephyr/zephyr.bin`としてできてた．

ここまででLチカ(LEDチカチカ)プログラムの動作確認はおしまい．

ちなみにソースの中身を見てみると，こんな感じになっていた． 
```~/zephyrproject/zephyr/samples/basic/blinky/src/main.c 
void main(void)
{
    ...
    ..
	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return;
	}

	while (1) {
		ret = gpio_pin_toggle_dt(&led);
		if (ret < 0) {
			return;
		}
		k_msleep(SLEEP_TIME_MS);
	}
}
```

# MicroPythonのZephyr移植版のビルドと動作確認
## ビルド
MicroPythonは下のURLからクローンしてくる．
https://github.com/micropython/micropython


ビルドの仕方は[ここに](https://github.com/micropython/micropython/blob/master/ports/zephyr/README.md)すべて書かれてある


私の場合，クローンしたmicropythonフォルダは
`~/mp/micropython`として置いたので，ビルドのコマンドは
```
west build -b frdm_k64f ~/mp/micropython/ports/zephyr
```

となった．westコマンドは`~/zephyrproject/zephyr`の下で使うみたいなので，そのディレクトリに移動しておいて上のコマンドを打つ

ここで私はZephyrのバージョンを戻すことをせず先に進んだのでビルドがエラーに．あとでこれに気づいて，バージョンを以下のコマンドで戻して置いたら問題なく完了した
```
git checkout v3.1.0
west update
```

このコマンドの結果できるバイナリは，Lチカのサンプルの時と同様，
`~/zephyrproject/zephyr/build/zephyr/zephyr.bin` 
となった

## 動作確認
### 接続

これをK64FのDAPLINKストレージアイコンにD&Dコピーして，そのままターミナルやThonnyアプリを開けばREPLプロンプトが表示される． 

FRDM-K64F基板とPCの接続はデバッガ・チップ側の方のUSBコネクタで行う．MIMXRT1050-EVKBでZephyrを介さずに直接動作するMicroPythonの場合は，ターゲットMCU直結のUSBコネクタにつなぎ直さなければならなかったが，その必要はない．PC上に「DAPLINK」ストレージが見えている状態でMicroPythonに接続できる．
 
下の画像はThonnyで接続してみた際の例．右下のShellペインに表示された先頭の行に`zephyr-frdm_k64f`と表示があり動作していることがわかる．また右側にはDAPLINKストレージが見えたままになっているのがわかる
![スクリーンショット 2023-04-25 2.46.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288603/606fc31d-d1d0-7e08-2f9e-c3bac46b3cf7.png)

### MicroPythonの動作

動作は[ここ](https://github.com/micropython/micropython/blob/master/ports/zephyr/README.md#quick-example)のサンプルコードをそのまま使った． ありがたいことに，ピン設定方法を調べずにそのまま青色LEDが点滅した
```python
import time
from machine import Pin

LED = Pin(("GPIO_1", 21), Pin.OUT)
while True:
    LED.value(1)
    time.sleep(0.5)
    LED.value(0)
    time.sleep(0.5)
```

せっかくのRGB LEDなので他の色も点滅させたい．回路図([ここからダウンロード可能](https://www.nxp.jp/design/development-boards/freedom-development-boards/mcu-boards/freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F))を見てみると，![スクリーンショット 2023-04-25 2.54.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288603/7a3f4319-09f1-ebdb-af0f-f301033b088d.png)

ポートの「PTB」を`"GPIO_1"`と表現してるみたい．なのでこれにならって赤が接続された「PTB22」を`("GPIO_1", 22)`，青の「PTE26」を`("GPIO_4", 26)`として， ベタ書きだけど下のようなコードを書いてみたら順番に点灯した ☺️
```python
import time
from machine import Pin

LED_B = Pin(("GPIO_1", 21), Pin.OUT)
LED_R = Pin(("GPIO_1", 22), Pin.OUT)
LED_G = Pin(("GPIO_4", 26), Pin.OUT)
while True:
    LED_B.value(1)
    LED_R.value(1)
    LED_G.value(0) # LEDは0でON，1でOFFになる
    time.sleep(0.5)
    
    LED_B.value(1)
    LED_R.value(0)
    LED_G.value(1)
    time.sleep(0.5)
    
    LED_B.value(0)
    LED_R.value(1)
    LED_G.value(1)
    time.sleep(0.5)
```
ピン名の指定方法は他にもあるかもしれない．これはそのうち調べてみる 


# さらに

Zephyr移植版MicroPythonはLPC55シリーズでも使えるみたいなので，とりあえずビルドだけ試してみた．

先ほど`frdm-k64f`用にビルドしたので，ターゲット指定だけを変えてコマンドを打つとエラーになる．以下のように`--pristine`を追加してやると，`make clean`してから作業してくれる感じになる

```
west build --pristine -b lpcxpresso55s69_cpu0 ~/mp/micropython/ports/zephyr
```

残念ながら上記コマンドではエラーが出てうまくいかない．メモリの制約に引っかかる．でも最低限のconfig設定（コマンドに`-- -DCONF_FILE=prj_minimal.conf`を追加）でやってみたら通った 
```
west build --pristine -b lpcxpresso55s69_cpu0 ~/mp/micropython/ports/zephyr  -- -DCONF_FILE=prj_minimal.conf
```

次の表はデフォルトconfig状態でビルドが通るかどうかの結果．各ターゲット毎にデフォルトconfig状態が設定があるのかもしれないので，これによって何がどうって言えないのかもしれない．

|結果|ターゲット|
---|---
Fail|lpcxpresso11u68
Fail|lpcxpresso54114_m0
Pass|lpcxpresso54114_m4
Pass|lpcxpresso55s06
Fail|lpcxpresso55s16
Pass|lpcxpresso55s28
Fail|lpcxpresso55s69_cpu0
Fail|lpcxpresso55s69_cpu1
Fail|lpcxpresso55s69_ns 

MIMXRT1050用のビルドは問題なく通った．