ESP32S3-N16R8用のCircuitPythonをビルドする on Mac

# はじめに

[CircuitPythonのダウンロードサイト](https://circuitpython.org/downloads?q=esp32s3)には、ESP32S3のN8R8やN32R8が公開されているが、手持ちのN16R8向けは提供が無い。
N16R8にN32R8向けをインストールすると、リブートを繰り返し使えない。N8R8向けはインストールできるが、16MBメモリを有効に活用できない。

```shell:N16R8にN8R8向けをインストールした結果
Adafruit CircuitPython 8.0.2 on 2023-02-14; ESP32-S3-DevKitC-1-N8R8 with ESP32S3
>>> import os
>>> fs_stat = os.statvfs('/')
>>> print("Disk size in MiB", fs_stat[0] * fs_stat[2] / 1024 / 1024)
Disk size in MiB 5.66016
>>> print("Free space in MiB", fs_stat[0] * fs_stat[3] / 1024 / 1024)
Free space in MiB 5.65625
>>> 
>>> 
>>> import gc
>>> print(gc.mem_free() / 1024 / 1024)
7.8148
>>> 
```


そこで、[ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/index.html)環境にて、N16R8向けのCircuitPythonをビルドすることにした。

# 環境

当方の環境は以下の通り

```shell
$ uname -a
Darwin MacBook-Pro.local 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:17:10 PDT 2022; root:xnu-8020.140.49~2/RELEASE_X86_64 x86_64

$ idf.py --version
ESP-IDF v4.4.3

$ python --version
Python 3.10.8

$ make --version
GNU Make 3.81

$ gmake --version
GNU Make 4.4
```

ESP-IDF環境は既に整っている前提


# 手順

主に『[ESP32-S3-N16R8 build and flash CircuitPython firmware](https://timonpeng.com/esp32-s3-n16r8-build-and-flash-circuitpython-firmware/)』を参考にさせてもらった。
また、公式サイト『[Build CircuitPython](https://learn.adafruit.com/building-circuitpython/build-circuitpython)』『[Espressif Builds](https://learn.adafruit.com/building-circuitpython/espressif-build)』『[macOS Setup](https://learn.adafruit.com/building-circuitpython/macos)』も参考にした。

以下にコマンドの流れだけを示す。

```shell:事前準備（インストール済みであればスキップ）
brew update
brew install uncrustify cmake ninja
brew link gettext --force
pip install minify-html
pip install jsmin
```


```shell:circuitpython.gitをクローン
git clone https://github.com/adafruit/circuitpython.git
cd circuitpython
git checkout main
make fetch-submodules  OR   fetch-all-submodules

cd ports/espressif
esp-idf/install.sh
```


```shell:N8R8をコピーしてN16R8向けを作る
cd boards
cp -r espressif_esp32s3_devkitc_1_n8r2 espressif_esp32s3_devkitc_1_n16r8
sed -i "" 's/ESP32-S3-DevKitC-1-N8R2/ESP32-S3-DevKitC-1-N16R8/g' espressif_esp32s3_devkitc_1_n16r8/mpconfigboard.h
sed -i "" 's/ESP32-S3-DevKitC-1-N8R2/ESP32-S3-DevKitC-1-N16R8/g' espressif_esp32s3_devkitc_1_n16r8/mpconfigboard.mk
sed -i "" 's/dio/qio/g' espressif_esp32s3_devkitc_1_n16r8/mpconfigboard.mk
sed -i "" 's/8MB/16MB/g' espressif_esp32s3_devkitc_1_n16r8/mpconfigboard.mk
echo 'CIRCUITPY_ESP32_CAMERA = 0' >> espressif_esp32s3_devkitc_1_n16r8/mpconfigboard.mk
sed -i "" 's/CONFIG_SPIRAM_MODE_QUAD/CONFIG_SPIRAM_MODE_OCT/g' espressif_esp32s3_devkitc_1_n16r8/sdkconfig
sed -i "" 's/2097152/8388608/g' espressif_esp32s3_devkitc_1_n16r8/sdkconfig
```


```shell:N16R8向けをビルド
cd ..
source esp-idf/export.sh
gmake -j8 BOARD=espressif_esp32s3_devkitc_1_n16r8
```

バージョンが古いせいか、makeコマンドだと、`Use make V=1, make V=2 or set BUILD_VERBOSE similarly in your environment to increase build verbosity.`エラーが出てビルドできなかったので、gmakeコマンドを使った。

## ビルド結果

```shell:成果物フォルダ(circuitpython/ports/espressif/build-espressif_esp32s3_devkitc_1_n16r8)
$ ls build-espressif_esp32s3_devkitc_1_n16r8
autogen_display_resources-en_US.P	firmware.elf.map
autogen_display_resources-en_US.c	firmware.uf2
autogen_display_resources-en_US.o	genhdr
autogen_web_workflow_static.c		lib
background.P				main.P
background.o				main.o
bindings				mphalport.P
boards					mphalport.o
build-espressif_esp32s3_devkitc_1_n16r8	peripherals
circuitpython-firmware.bin		py
common-hal				shared
esp-idf					shared-bindings
extmod					shared-module
firmware.bin				supervisor
firmware.elf
```

今回は、上の`firmware.bin`を`esptool`でesp32s3に焼いた。

```shell:
$ esptool.py --chip esp32s3 --port /dev/cu.usbserialxxx --baud 921600 erase_flash
$ esptool.py --chip esp32s3 --port /dev/cu.usbserialxxx --baud 921600 write_flash -z 0x0 firmware.bin

```

<br>

:::note warn
`circuitpython-firmware.bin`との違いが分からない。<br>サイズや拡張属性が異なる。
```shell
$ ls -ls@ *.bin
2800 -rw-r--r--  1 user  staff  1429872  2 23 12:12 circuitpython-firmware.bin
2928 -rw-r--r--@ 1 user  staff  1495408  2 23 12:12 firmware.bin
	com.apple.metadata:kMDLabel_apnqz4ufxxzkf7xrsotqb32bzq	    249 
```
:::


# N16R8用CircuitPythonの実行結果

```shell
$ screen /dev/cu.usbmodemxxx 115200

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

Press any key to enter the REPL. Use CTRL-D to reload.

Adafruit CircuitPython 8.1.0-alpha.2-14-gc2c7b9345-dirty on 2023-02-23; ESP32-S3-DevKitC-1-N16R8 with ESP32S3
>>> 
```

無事に起動しました。最新バージョンのため`8.1.0-alpha.2-14-gc2c7b9345-dirty`となっている。`git checkout xxx`でバージョンを指定できるようだが、上手くいかなかったので最新指定。

さて、メモリは増えたのか確認する。

```python
>>> import os
>>> fs_stat = os.statvfs('/')
>>> print("Disk size in MiB", fs_stat[0] * fs_stat[2] / 1024 / 1024)
Disk size in MiB 13.6563
>>> print("Free space in MiB", fs_stat[0] * fs_stat[3] / 1024 / 1024)
Free space in MiB 13.6484
>>> 
>>> 
>>> import gc
>>> print(gc.mem_free() / 1024 / 1024)
7.8134
>>> 
```

メモリの空き容量はほぼ同じで、ファイルシステムの方に8MB増えていた。パーティションテーブルいじって無いからこうなる？（pythonファイルをいっぱい置ける）

## しかし、疑問が残る

そもそもPSRAMはどこで見えるのか？

| ESP32-S3 | Flash | PSRAM | メモリ<br>空き容量 | ディスク<br>容量 | ディスク<br>空き容量       |
| :-------: | ----: | ----: | -------------: | -----------: | ---------------:  |
| N8R8     | 8MB   | 8MB   | 7.81 MiB       | 5.66 MiB     | 5.65 MiB         |
| N16R8    | 16MB  | 8MB   | 7.81 MiB       | 13.66 MiB    | 13.64 MiB        |


# 追加 (2023.3.18)

参考にした元の記事に従い、ボード情報`espressif_esp32s3_devkitc_1_n8r2`をコピーして`espressif_esp32s3_devkitc_1_n16r8`としたが、Flashサイズの変更は1箇所に対し、多くの変更箇所はPSRAMの容量や種別でした。
後から考えてみると、コピー元を`espressif_esp32s3_devkitc_1_n8r8`とするべきだったと思います。そうすれば、変更箇所はたった1箇所で済みますから。





# おわりに

Micropythonだと、USB-HIDがいまいちだったので、CircuitPythonでやってみようとしたのが、今回の記事のきっかけです。
これでHIDの高機能デバイスをCircuitPythonで作る準備ができました。自分への備忘録も兼ねて手順を残しておきました。

自作のesp32s3実装ボード；
![IMG_1425.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/a5d74e4a-6760-b688-c1f6-b75ed26247a8.png)

以上