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



