①MicroPython + FabGLが実現できたが、ヒープが減少
FabGLを組み込む前は、99KB程度MicroPythonのヒープ空きサイズがありましたが、さすがにVGA表示メモリが必要になるので、22KBまで減ってしまっていました。WiFiや、Bluetoothなどが使用できる上にVGA表示とてんこ盛りしましたが、簡単なプログラムなら使えるのではないでしょうか。
そこで、ヒープを増やすため調査すると、幸いにも、SPIRAM搭載のESP-WROVERを搭載したESP32-DevKitC開発ボードを見つけましたので、これを使うことにしました。
②ビルドで"IRAM0 segment data does not fit."が発生
menuconfigで、SPIRAMを有効にし、ビルドオプションを指定してビルドを行いましたが、リンカーのASSERTに引っ掛かり、"IRAM0 segment data does not fit."となってしまいました。
下記は、リンカーが割り当てた、各セグメントの割り振りです。"iram0_0_seg"は、128KBしかなく、これが溢れたようです。この領域は、CPUが高速にアクセスできる高速処理を必要としている関数群に割り当てることになっていますが、MAPファイルを確認すると、SPIRAM関連のMicroPython・FabGLの関数でオーバーフローしたようです。
Memory Configuration
Name Origin Length Attributes
iram0_0_seg 0x0000000040080000 0x0000000000020000 xr
iram0_2_seg 0x00000000400d0020 0x000000000032ffe0 xr
dram0_0_seg 0x000000003ffbdb5c 0x000000000001e6a4 rw
drom0_0_seg 0x000000003f400020 0x00000000003fffe0 r
rtc_iram_seg 0x00000000400c0000 0x0000000000002000 xrw
rtc_data_seg 0x000000003ff80000 0x0000000000002000 rw
rtc_slow_seg 0x0000000050000200 0x0000000000000e00 rw
extern_ram_seg 0x000000003f800000 0x0000000000400000 xrw
*default* 0x0000000000000000 0xffffffffffffffff
"IRAM0 segment data does not fit."の対処方法を調査すると、不要と思われる関数(機能)を外すという消極的な対策程度しか確認できませんでした。半分あきらめ気味で、FabGL内で"IRAM_ATTR"属性が付けられている関数を確認すると、"displaycontroller.cpp"内は、それほど高速性でなくても行けそうな感じでした。
そこで、ESP-IDFの機能で、リンカーへのセグメント割り当てオプションができる"Linker Script"があることがわかりましたので、"linker_fragment_file.lf"を作成し、"CMakeLists.txt"に必要な定義を追加しました。これで、"IRAM0 segment data does not fit."が回避できました。
"displaycontroller.cpp"内の関数は、全てFlashROMに移動させました。実行時は、CPUのCacheメモリ経由でアクセスされますので、大きな問題はないと思われます。CPUクロック周波数を240MHz、Flashクロックを80MHzに指定して、特に表示のちらつきは、無いようです。
ESP-WROVERの恩恵で、無事MicroPythonの空きヒープサイズがが4MBになりましたので、かなりの大きさのプログラムでも問題無いはずです。
③ESP-WROVERでSDカードが使えない
ここまでなんとか来ましたが、SDカードの動作確認をすると、エラーが出て使えませんでした。ESP-WROVER内部とESP32-DevKitC開発ボードの回路図を確認すると、ORENGE-ESPerでSDカード信号に使用しているPin(17)とPin(16)は、SPIRAMで使用しているため、ESP32-DevKitC開発ボード上は、NCになっていました。
そこで、オプションのシリアルI/Fで使う、Pin(2)とPin(34)に変更しました。ジャンパ線が必要ですが、ESP-WROVERに依存していますので、下記のようにESP32-DevKitC開発ボード上でジャンパ線を追加しました。これで、ORENGE-ESPerは、ESP-WROVERでもESP-WROOM両者で使えます。
但し、GPIO2は、ESP32のプログラミング書き込みに使用されているため、浮遊容量が増え、不安定になる場合があるようですので、ESP32のプログラミング書き込みは、ORENGE-ESPerから外してESP32-DevKitC開発ボード単独で行うことをお勧めします。また、シリアルポート番号が変わることがありますので、注意ください。
Pin(17) <-> Pin(2)
Pin(16) <-> Pin(34)->->
下記は、ジャンパ線を飛ばした後のESP-WROVER版ESP32-DevKitC開発ボードです。
④おまけモジュールの追加
最後に、MicroPythonを使いやすくするために、下記のモジューを"micropython/port/esp32/modules"
に配置し、ビルドするとコンパイル済mpy形式でビルドイメージに組み込まれます。
・uwipye.py 軽量pythonエディター
・upysh.py ファイル操作shellライクコマンド
・mount_sd.py SDカードのマウント('/sd'にマウント)
⑤ソース・バイナリの公開
MicroPythonは、MITライセンス、FabGLは、GPLライセンスで公開されていますので、今回は、GPLライセンスに従い、ソースとバイナリをtarボールで公開します。変更箇所は、Winmergeなどで差分を確認できると思いますが、オリジナルを変更した部分には"jr2xzy"の記述を入れています。
ファイルサイズの関係で、fullclean状態になりますので、MicroPythonのソースツリーの"micripython/port/esp32"に上書きし、menuconfig後、ビルドしてください。また、ESP-WROVERの場合、"linker_fragment_file.lf"を有効にしてください。
## ESP-WROOM for ESPer ##
cd ~/esp32/micropython/ports/esp32
idf.py menuconfig
Serial flasher config --->
Flash SPI mode (QIO) --->
Flash SPI speed (80 MHz) --->
Flash size (4 MB) --->
Driver configurations --->
RTCIO configuration --->
[*] Support array `rtc_gpio_desc` for ESP32
Component config --->
ESP32-specific --->
CPU frequency (240 MHz) --->
[ ] Support for external, SPI-connected RAM
idf.py build
## ESP-WROVER for ESPer ##
cd ~/esp32/micropython/ports/esp32
idf.py menuconfig
Serial flasher config --->
Flash SPI mode (QIO) --->
Flash SPI speed (80 MHz) --->
Flash size (4 MB) --->
Driver configurations --->
RTCIO configuration --->
[*] Support array `rtc_gpio_desc` for ESP32
Component config --->
ESP32-specific --->
CPU frequency (240 MHz) --->
[*] Support for external, SPI-connected RAM
SPI RAM config --->
Set RAM clock speed (80MHz clock speed) --->
[*] Initialize SPI RAM during startup (NEW)
idf.py -D MICROPY_BOARD=GENERIC_SPIRAM build
バイナリは、"micropython/port/esp32"配下の"ESP-WROOM"及び、"ESP-WROVER"に置いています。ORANGE-ESPer用の"esptool.exe"と"upload.batを適当に変更して使えば、ビルドしなくても焼くことができるはずです。
下記は、"import mount_sd"を実行後、MicroPythonの空きヒープサイズが"4095296"になっています。"from uwipye import pye"を実行後、pye()エディターのキー機能が表示されます。
以上、ESP32(ESP-IDF)には結構苦労しましたので、Arduinoの有難さがわかります。ESP32の能力をフルに出すためには、ESP-IDFが必要な感じです。今後、FabGLのMicroPythonインタフェースが追加できれば、用途が広がるかもしれません。いずれにしろ、ORENGE-ESPerを楽しんだり、ESP32のデバッグに役立ていただければと思います。