LoginSignup
1
1

More than 1 year has passed since last update.

ESP32マルチ書き込みボードの改造(ネイティブUSBによる書き込み)

Posted at

0. はじめに

先日、『ESP32マルチ書き込みボード』を紹介させていただきました。その後、ESP32-S3のネイティブUSBによる書き込みにも対応したので、今回はそれを紹介いたします。

1. 改造した書き込みボード

新しい書き込みボードは↓こんな感じです。左側のUSBアダプタも作成しました。3.3V降圧モジュールを仕込んであります。

IMG_0876.png

下の写真は改造前のボードで、比較しながら改造点を説明します。
IMG_0802.png

(1) ESP32-S3のネイティブUSBを使用するため、USBシリアル変換モジュールは使用しません。代わりUSBのD-/D+信号線をESP32-S3のIO19/IO20に接続するため、2Pピンソケットを追加しました。

(2) 手動書き込みに対応するため、IO0をGNDに落とすタクトスイッチを追加しました。ネイティブUSBで書き込む場合『自動書き込み』ができず、後から急遽追加しました。そのためタクトスイッチも不揃いで取って付けた感ありありです。

書き込みボード自体の改造は以上の2点だけです。

次回、書き込みボード自体を新規作成する時は、ネイティブUSB用の4Pヘッダ(3.3v/GND/D-/D+)を独立して準備しようと思います。そうすればシリアル接続と共存ができますので。

2. ネイティブUSBを使用する場合の気づき

自分に経験がないため、実際の書き込みは、一筋縄ではいきませんでした。
色々試行錯誤して、今は普通に書き込めるようになりましたので、そこで得た内容を気づき事項としてまとめておきます。

(1) 自動書き込みができない

通常のシリアルインタフェースによる自動書き込みは、RTS/DTRピンによりEN/IO0を制御することでブートモードを制御していますが、ネイティブUSBの場合はそれができません。よって、手動書き込みのため、再起動時にIO0をGNDに落としてDownload Bootにする必要がありました。

同様に、書き込み後の自動リセットも効かないため、手動でリセット(再起動)する必要があります。

自動書き込みができない』という認識は誤り(?)であったことが、後で判明しました。詳しくは後述します。

(2) シリアルポートが変化する

CircuitPythonが書き込んであったESP32-S3をネイティブUSB接続したときのシリアルポートは/dev/cu.usbmodemC7FD1A7E6ACC1でした。

USBデバイスツリーには、ESP32-S3-DevKitC-1-N8R8と認識され、
circuitpython.png
CIRCUITPYというフラッシュドライブも現れます。また、
screen /dev/cu.usbmodemC7FD1A7E6ACC1 115200でREPLも機能します。

これを、Download Bootで起動すると、シリアルポートは/dev/cu.usbmodem144201に変化し、USBデバイスツリーには、USB JTAG/serial debug unitと認識されます。
USB_JTAG.png

ここで、Arduino IDEからESP32のスケッチ例KeyboardMessageを書き込んで再起動すると、今度は、シリアルポートは/dev/cu.usbmodem144202に変化し、USBデバイスツリーには、ESP32S3_DEVと認識されます。
ESP32S3_DEV.png

以上のように、シリアルインタフェースでは固定であったシリアルポートが、ネイティブUSBだと状況により変化するため、esptoolArduino IDEから書き込みをする場合に、シリアルポートを確認する必要があります。

(3) Arduino IDEでのボードの指定方法

よく分からず戸惑ったのが、Arduino IDEでのボードの指定方法です。ボードそのものは、ESP32S3 Dev Moduleでよいのですが、USB ModeUpload Modeで何を指定すべきか分からず、何パターンも試して分かった事があります。

・Upload Mode

これは、現在のESP32-S3のネイティブUSBの認識状態により、指定値の振る舞いが違ってきます。下表は『USB認識状態』を現在のシリアルポートで代用します。

USB認識状態
(シリアルポート)
UART0 / Hardware CDC USB-OTG CDC (TinyUSB)
/dev/cu.usbmodemC7FD1A7E6ACC1 書き込み不可(*1) 書き込み不可(*2)
/dev/cu.usbmodem144201 書き込み可 書き込み可
/dev/cu.usbmodem144202 書き込み不可(*1) 書き込み可

(*1)書き込み不可理由:Connecting...........スケッチの書き込み中にエラーが発生しました.
(*2)書き込み不可理由:シリアルポート「・・・」が選択されていますが、そのポートは存在しないか、ボードが接続されていません。

はじめて今回の書き込みボードでネイティブUSB接続によりアップロードを試みた時は、CircuitPythonが書き込んであるESP32-S3を使用し、シリアルポートは/dev/cu.usbmodemC7FD1A7E6ACC1でした。上の表に示す通り、この状態では、Upload Modeに何を指定してもアップロードすることができなかったことと、その後、(IO0をGNDに落として)Download Bootしたところ、シリアルポートが/dev/cu.usbmodem144201に変化し、アップロードできたことで、前項の『ネイティブUSBの場合は自動書き込みはできない』という誤認識につながりました。

興味ある動作として、USB-OTG CDC (TinyUSB)を指定した場合は、書き込みの最初に現在のシリアルポートを一度閉じて、複数のシリアルポートを試してアップロードするシリアルポートを決定する動作が確認できました。

Arduino IDEのログから抜粋
シリアルポート「/dev/cu.usbmodem144202」を1200bpsで開いて閉じる事によって、リセットを行っています。
PORTS {/dev/cu.BLTH, /dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem144202, /dev/cu.usbmodemHIDLD1, /dev/tty.BLTH, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem144202, /dev/tty.usbmodemHIDLD1, } / {/dev/cu.BLTH, /dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem144201, /dev/cu.usbmodemHIDLD1, /dev/tty.BLTH, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem144201, /dev/tty.usbmodemHIDLD1, } => {/dev/cu.usbmodem144201, /dev/tty.usbmodem144201, }
Found upload port: /dev/cu.usbmodem144201

この動作により、シリアルポートが/dev/cu.usbmodem144202のときも/dev/cu.usbmodem144201に変化し、書き込み可となり、この動作は『自動書き込み(Download Bootへの移行)』の動作だと理解しました。(←この理解も正しく無い気がしています。

・USB Mode

アップロード後のESP32-S3のUSBのモードを指定するものと思われます。

USB Mode 目的 備考
Hardware CDC and JTAG Serial利用
USB-OTG (TinyUSB) USB-HID実装

単なるLチカのスケッチならどちらの指定でもちゃんと動作しますが、シリアルモニタに表示したい場合はHardware CDC and JTAGを指定しないと表示しませんでした。逆に、スケッチ例KeyboardMessageでは、USB-OTG (TinyUSB)を指定しないと機能しませんでした。
KeyboardMessageのソースコードを見ると、コードの先頭にUSBモードの判定が入っています。

KeyboardMessage.ino
#if ARDUINO_USB_MODE
#warning This sketch should be used when USB is in OTG mode
void setup(){}
void loop(){}
#else
: : :

Hardware CDC and JTAGを指定してコンパイルすると、warningメッセージThis sketch should be used when USB is in OTG mode」が出ていたのですが、処理が進んでアップロードができてしまうので、気づきませんでした。#warning#errorに変えてコンパイルエラーにすべきだと思います。

3. 書き込み性能

気持ちネイティブUSB接続の方が早く書き込みができるように感じたので、ESP32ダウンローダによるシリアル接続と、今回のネイティブUSB接続での、書き込み性能を比較してみました。

esptoolを使い、ファイルadafruit-circuitpython-espressif_esp32s3_devkitc_1_n8r8-ja-7.3.3.bin(約1.5MB)を書き込む速度をtimeコマンドで比較。通信以外の時間も含む。

書き込み ボーレート 速度 [秒]
ネイティブUSB接続 指定なし(115,200bps) 23.672
ネイティブUSB接続 12,000,000bps 23.675
シリアル接続 指定なし(115,200bps) 94.538
シリアル接続 921,600bps 28.440
シリアル接続 1,500,000bps 25.127

数秒ですがシリアル接続より早いです。

ESP32­S3 Technical Reference Manualの「33.2 Features」』に「USBシリアル/JTAGデバイスは USB2.0デバイスですが、USB2.0規格で導入された高速スピード (480Mbps) モードではなく、フルスピード (12Mbps) のみをサポートする」と注記がありました。

ネイティブUSB接続の場合はボーレートの指定は意味が無い(?)ようです。

4. あらためて

この記事をまとめるにあたり、あらためて『ESP32-S3 Series Datasheet』を読むと、「3.5.12 USB Serial/JTAG Controller」に、「CDC-ACM supports host controllable chip reset and entry into download mode.」という記載がありました。また、『ESP32­S3 Technical Reference Manual』の「Table 33­-1. Standard CDC­-ACM Control Requests」と「Table 33-­2. CDC­-ACM Settings with RTS and DTR」から、『SET_CONTROL_LINE_STATE』apiによって、RTS/DTRを制御していることが読み取れます。そして、RTS=1/DTR=0でESP32-S3をResetできるようです。

USB-CDCでシリアル通信をエミュレーションしていることが理解できて少しスッキリしました。

しかし、CircuitPythonが書き込んである状態のシリアルポート/dev/cu.usbmodemC7FD1A7E6ACC1では書き込み出来ないことが腑に落ちません。また、どのモードでも書き込み後にリセットが効かず手動リセットが必要で、これも納得できません。これについては、似たような指摘を『esp32-s3 does not reset after upload #6762』で発見しましたが、結論がよく分かりませんでした。

MicroPythonを書き込んで試してみましたが、状況は同じでした。ただし、シリアルポートは/dev/cu.usbmodem1234561、USBデバイスツリーにはEspressif Deviceと認識され、CircuitPythonの時のようなフラッシュドライブは現れません。
micropython.png

esptoolコマンドの--before引数をdefault_resetからusb_resetに変えてみても、状況は変わらず。

この状態で、ESPアップローダでシリアル接続からアップロードすると、これは普通に問題なく可能で、シリアルポートは/dev/cu.wchusbserial53250003491
シリアル接続であれば、どの状態でも自動書き込みが可能です。


ここで、eFuseの設定値を確認しました。
ダウンロードに関係していそうなeFuseの値は以下の通りです。

eFuse summary情報からの抜粋
DIS_FORCE_DOWNLOAD (BLOCK0)                        Disables forcing chip into Download mode           = False R/W (0b0)
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0)         Disables USB-Serial-JTAG download feature in UART  = False R/W (0b0)
                                                   download boot mode    
DIS_USB_OTG_DOWNLOAD_MODE (BLOCK0)                 Disables USB-OTG download feature in UART download = True R/W (0b1)
                                                    boot mode                                        
DIS_DOWNLOAD_MODE (BLOCK0)                         Disables all Download boot modes                   = False R/W (0b0)
ENABLE_SECURITY_DOWNLOAD (BLOCK0)                  Enables secure UART download mode (read/write flas = False R/W (0b0)
                                                   h only)                                           

DIS_USB_OTG_DOWNLOAD_MODETrueになっているのが気になります。

4.1 eFuseを設定する

espefuseコマンドでDIS_USB_OTG_DOWNLOAD_MODEFalseに設定します。

$ espefuse.py --chip esp32s3 --port /dev/cu.wchusbserial53250003491 burn_efuse DIS_USB_OTG_DOWNLOAD_MODE 0

A fatal error occurred: New value is not accepted for efuse 'DIS_USB_OTG_DOWNLOAD_MODE' (will always burn 0->1), given value=0
$

しかし、エラーになりました。
0を1にする変更しか出来ない? 常にDisableでEnable出来ない???
シリアル接続でしたので、ネイティブUSB接続にて再度実行してみる。

$ espefuse.py --chip esp32s3 --port /dev/cu.usbmodem144201 burn_efuse DIS_USB_OTG_DOWNLOAD_MODE 0

A fatal error occurred: New value is not accepted for efuse 'DIS_USB_OTG_DOWNLOAD_MODE' (will always burn 0->1), given value=0
$

ネイティブUSB接続でも結果は同じ。

ESP32-S3の今のUSBモードがHardware CDCのはずなので、これをUSB-OTGに設定して、再度実行するも、結果は同じ。

$ espefuse.py --chip esp32s3 --port /dev/cu.usbmodem144201 burn_efuse DIS_USB_OTG_DOWNLOAD_MODE 0

A fatal error occurred: New value is not accepted for efuse 'DIS_USB_OTG_DOWNLOAD_MODE' (will always burn 0->1), given value=0
$

他、USBモードと接続形態(シリアル/ネイティブUSB)の組み合わせを試しましたが、すべて同じエラーでした。手詰まり、お手上げです。

ネイティブUSB接続の場合は自動書き込みはできず、DOWNLOAD BOOTで起動してから書き込むのが、唯一の手順なのでしょうか?

ESP32ネイティブUSB接続用のVCPドライバが必要な気がします・・・・・。

ネイティブUSB接続時の自動書き込みをご存知の方、ぜひ教えてください。

5. おわり

「自動書き込みはできない、書き込み後のリセットも効かない。」まったくスッキリしていませんが、ネイティブUSBによる書き込みができることは確認できたので、今回の記事は以上とします。

おまけ

ネイティブUSB接続ができると「Digispark ATTiny85」や「Beetle ATMega32u4」を、超高機能なESP32-S3に置き換えて、WiFi付き/Bluetooth付きにすることができます。実現したいことの内容とマイコンの単価を鑑みて、使い分けていこうと思います。

マイコン単体(秋月電子)価格
マイコン サイズ(W x H) 税込価格
ATTiny85-20SUR 約5mm x 7mm ¥150
ATMega32u4 約12mm x 12mm ¥640
ESP32-S3-WROOM-1-N16R8 約14mm x 26mm
(アンテナ部を含む)
¥530

ESP32-S3のコスパの良さが際立ちます。チップサイズに制約が無いならATMega32u4の出番はもう無いかも・・・。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1