M5Stackを最小構成で開発したい(したかった)
M5Stack Grayを秋葉原で買ってきました、昨日
開発環境について事前に調べていなかったのですが、多くの記事ではArduinoIDEかESP-IDFを使用しています
- ArduinoIDE
- Linux, Vimを愛する私がそんな環境で生きていけるとは思えない ので却下
- ESP-IDF
- pythonにたっぷり依存していてコンパイラのしくみを隠蔽してしまっている それがとても気持ち悪い
のでコマンドラインでC(など)からバイナリを生成、M5Stackへ書き込み という構成を作っていきたいと思います
追記: 軽く調べて見つからなかったので自分で険しい道を選んでいます。詳しい/すでにやってて体系が出来上がってる/何か知ってる 人がいたらコメントください!
ちなみにArduinoIDE, ESP-IDFはどちらも依存関係の構築に失敗してうまく動かなかったという事情もあります ただそこに労力を使うのも癪なので諦めることにしました
xtensa-esp32-elf: GCCベースのtoolchain があるらしい
書き込みなどにはesptoolが使えそう
とりあえずこれでwhile(1){}
が動作した(?)
int main() {
while (1) {}
return 0;
}
xtensa-esp32-elf-gcc main.c
esptool.py elf2image a.out
esptool.py --chip esp32 load_ram a.bin # M5の画面が固まる 書き込みに成功している?
# esptool.py --chip esp32 write_flash 0x00000 a.bin # 再起動後も何も起こらない なぜだろう
ダンプしておいた初期ROMイメージをxxdして読んでみると、データは0x1000から始まっているように見えた。エントリポイントがそこにあると予想したので
esptool.py --chip esp32 write_flash 0x01000 a.bin
とすると、毎再起動後画面が黒いままスピーカーから変な音が無限に鳴る(バッファの書き込みをしていないから?)ようになった とりあえず成功。
調べてみたところヒットしました docsはちゃんと読みましょう…(ここにあるとは思わんやん…)
Application Startup Flow - ESP32 - — ESP-IDF Programming Guide latest documentation
これを読めばうまく進められそう…!
読んでわかったことまとめ(@ Second Stage Bootloaderの途中):
- (ESP-IDFでは)複数のappを保存しておいてbootloaderが呼び分けることができるようになっている。RAMからも読めはする。→初期化の段階を楽にしてとりまとめるため?それ以外のメリットがないなら最初のうちは0x1000に直接プログラムを置いてしまいたい
- (PICで昔やったように)一バイナリを0x00に転送してやるだけで実行できるわけではなく、(番地とかフラッシュメモリとかの観点で)データが分散してるらしい、そりゃあ独自ビルドスクリプトを用意するわけですね
今日はここまで。おやすみなさい
今日も今日とて
今日はシリアルへのHelloWorldから画面表示までやっていきたいですね
#include <stdio.h>
int main(void) {
printf("Hello, world!");
while (1) {}
return 0;
}
/usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/libc.a(lib_a-stdio.o):(.literal+0x20): warning: _close_r is not implemented and will always fail
/usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/libc.a(lib_a-makebuf.o):(.literal+0x8): warning: _fstat_r is not implemented and will always fail
/usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/libc.a(lib_a-stdio.o):(.literal+0xc): warning: _lseek_r is not implemented and will always fail
/usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/libc.a(lib_a-stdio.o):(.literal+0x4): warning: _read_r is not implemented and will always fail
/usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/libc.a(lib_a-stdio.o):(.literal+0x10): warning: _write_r is not implemented and will always fail
/usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/libc.a(lib_a-puts.o):(.literal+0x24): warning: pthread_setcancelstate is not implemented and will always fail
/usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /usr/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/libc.a(lib_a-puts.o):(.literal+0x38): warning: __getreent is not implemented and will always fail
syscallがないようなのでesp-idfからライブラリを借りてきます
esp-idf/components/esp_rom/esp32/ld/
にPROVIDEがいくつかあるので、そこにbuilt-in syscallがあるっぽい?もしくはesp-idfが実装しているかもしれないけど、わからない
それっぽいものをいくつか試してみたが、望む結果は得られなかった(見る場所が違う?それとも呼びかたが違う?)
- 何もしないときの挙動(中身は起動ごとに違うかも、一例。)
- 初回:
21a5 0a00 089c bc4a ddfd 31
- それ以降:
d5d5 dd08 3121 fa21 a50a fe90 e542 a801 dea6 d5ed
- 初回:
- printf:
0x40056978
- ets_install_uart_printf:
0x40007d28
- ets_printf:
0x40007d54
- ets_write_char_uart:
0x40007cf8
いろいろ試して埒が開かないのでesp-idfを動かしてビルドログを読むことにしました→動いてしまったので満足してしまいました これにてcloseとします(えー)
わかったことなどを軽くまとめておきます
- AURのものを使うと設定がよくわからないので公式の指示に従って$HOMEに入れたほうが無難
- esp-idfでも書き込みにはesptool.pyを使えと言われるので変な書き込みはしてないらしい
中身の深い理解に繋がったので今回の悪あがきも無駄ではなかったのかなと思っています また気が向いたらチャレンジするかもしれないけど
サークルの先輩からArduinoIDEでも外部エディタで編集できるよと教えてもらったので試してみて分かったこと:
どうやらarduinoも結局C++(C?)でしかないらしい(下手なブラックボックス化やめてくれ…)、
なんならArduinoIDEで作ったプロジェクトもesp-idfなどを使ってビルドされているらしい
ビルドはarduino-cliを使えば済む話のようなので、vimでの補完環境さえ整えられれば完璧ということですね(?)
というわけで再度ちょっと足掻いてみることにします