ESP32用ツールでシリアル指定が省略できる?

 idf.pyやesptool.pyやespefuse.pyなどを使うときに-pでのシリアルポート指定が省略できることがある。

 これは自動判定しているのか、それとも、一度指定した値をどこかにキャッシュしているのか。謎。

 時間のない人向けに結論から先に。

 ・idf.pyはesptool.pyを呼んでいるので実装は同じ。port指定をしない場合は、自動認識する。複数接続されている場合は、esptoolで逆順にソートされて一番上が使われる。これはOSによってデバイス名が異なるので同じ動作にはならない。

 ・espefuse.pyは独自実装で、v4系では無指定の場合は/dev/ttyUSB0が呼ばれる。v5以降からはポート指定は必須になっている。つまり、常時指定しないと動作しない。

 ・CONFIG_ESPTOOLPY_PORTは古い設定で、CMakeベースのビルドシステムやidf.pyでは無視される。

 んで、調べる。

 少なくともidf.pyでは、公式ドキュメントには「PORTを指定しない場合は、利用可能なUSBポートを使って自動接続を試みる」とあった。

 シリアルポートの指定条件はドキュメントによると以下になる。

 コマンドラインで -p / --port を明示した場合

 指定した値が使われる。idf.pyでは、コマンドライン指定が環境変数より優先される。

 環境変数ESPPORTを設定している場合

 idf.pyは$ESPPORTを-pの既定値として使う。$ESPPORTが-pのデフォルト値になる。

-p も ESPPORT もない場合

 idf.pyは利用可能なUSBポートから自動接続を試みる。1台だけ見つかった場合は、そのまま通信を開始する。

 複数ポートがある、あるいは別のUSBシリアル機器も刺さっている場合

 自動判定ができないので、失敗することがある。

 最後のは、実際にやってみないとわからないね。

 ESP32-S3を2つつなぐと、こんな感じ。デバイス名に数字がついて、区別ができるようになる。

% ls /dev/tty.*

/dev/tty.Bluetooth-Incoming-Port /dev/tty.usbmodem11401

/dev/tty.usbmodem11301

% idf.py monitor

Executing action: monitor

Serial port /dev/cu.usbmodem11401

Connecting...

Detecting chip type... ESP32-S3

 (snip)

% esptool.py chip_id

esptool.py v4.11.dev1

Found 2 serial ports

Serial port /dev/cu.usbmodem11401

Connecting...

Detecting chip type... ESP32-S3

Chip is ESP32-S3 (QFN56) (revision v0.2)

Features: WiFi, BLE, Embedded Flash 4MB (XMC), Embedded PSRAM 2MB (AP_3v3)

Crystal is 40MHz

USB mode: USB-Serial/JTAG

MAC: b4:3a:45:ae:42:c0

Uploading stub...

Running stub...

Stub running...

Warning: ESP32-S3 has no Chip ID. Reading MAC instead.

MAC: b4:3a:45:ae:42:c0

Hard resetting via RTS pin...

 idf.pyは自前でシリアルポートを選んでいるのではなく、esptoolのポート列挙と接続ループを呼んでいる感じかな。

esp-idf/tools/idf_py_actions/tools.py at master · espressif/esp-idf · GitHub

https://github.com/espressif/esp-idf/blob/master/tools/idf_py_actions/tools.py

 idf.pyのget_default_serial_port()は、ports = esptool.get_port_list()を取得して、そのままesptool.get_default_connected_device(serial_list=ports, ...)に渡している。つまり、選定順序はesptool側の出力で決まるということだ。

 esptool側では、serial_listをreversed(serial_list)で走査していた。

 現行のesptoolの検索スニペットに、reversed(serial_list): log.print(f"Serial port {each_port}:")とあるので、esptoolは受け取ったポート一覧の逆順で接続を試している。idf.pyにもこの逆順が渡っている。

 シリアルポートの選定は、デバイス名の大きいほうから行われるようだ。

 これはmacOSの事例になるので、他のOSでは、まずシリアルデバイスの名称が変わるし、さらにOSから取得するシリアルポートの受け取り順も違ってくるから、OSを変えると期待した動作にならない可能性がある。

 さらに、もうちょっとやっかい。espefuse.pyは挙動が違う。

% espefuse.py summary

espefuse.py v4.11.dev1

A fatal error occurred: Could not open /dev/ttyUSB0, the port is busy or doesn't exist.

 ([Errno 2] could not open port /dev/ttyUSB0: [Errno 2] No such file or directory: '/dev/ttyUSB0')

Hint: Check if the port is correct and ESP connected

Please make sure that you have specified the right port with the --port argument

 デフォルト値として「/dev/ttyUSB0」が埋め込まれていて、引数指定がない場合は、それが使われる感じ。うーん...

% espefuse.py -p /dev/cu.usbmodem11401 summary

espefuse.py v4.11.dev1

Connecting...

Detecting chip type... ESP32-S3

=== Run "summary" command ===

 (snip)

 現在使っているのは「espefuse.py v4.11.dev1」だけど、v5のマイグレーションガイドには、--portオプションは必須になっているとある。

v5 Migration Guide - ESP32 - — esptool latest documentation

 https://docs.espressif.com/projects/esptool/en/latest/esp32/migration-guide.html?#port-option-is-required

 「--port オプションは、すべてのコマンドで必須になりました(--virt オプションを使用する場合を除く)。以前はオプションで、デフォルト値は /dev/ttyUSB0 でした。」

 扱いが面倒だね。

 さらに、古いmenuconfigには、CONFIG_ESPTOOLPY_PORTという設定があって、「Default serial port」という説明がある。これは、現在ではCMakeベースのビルドシステムやidf.pyでは無視される。

 というわけで、どこかにキャッシュしているというようなことはなかった。

 つまり、一台だけ繋がっている場合は、idf.py, esptool.pyでは省略可能。複数台時はOSの違いで同じにならない。espefuse.pyはポート指定必須。という感じ。


オリジナル投稿:
ESP32用ツールでシリアル指定が省略できる?|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/11561656