2023年1月23日月曜日

ESP32C3の内蔵jtagを利用してubuntu上のvscodeでデバッグ


背景

ESP32C3にjtagが内蔵されているので使ってみました。
動かすまでになかなか手間取ったので、備忘録として環境構築方法を記事に残します。

使ったもの

  • M5Stamp C3U
    G18をUSBのD-、G19をUSBのD+として使う開発ボードが必要です。
    M5StampのC3Uはそうなっていますが、C3は違うので注意です。
  • ubuntuをインストールしたPC
  • VSCode + platformio

openocd-esp32のruleを配置

対応

下記コマンドで60-openocd.rulesを配置します。
curl -fsSL https://raw.githubusercontent.com/espressif/openocd-esp32/master/contrib/60-openocd.rules | sudo tee /etc/udev/rules.d/60-openocd.rules

配置したらESP32C3のUSBを抜き差しして、設定を更新してください。

platformio向けのrulesである99-platformio-udev.rulesを未設定の場合は、下記のコマンドでそれも配置してください。
curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/master/scripts/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules

動作確認

platformioがインストールしたopenocdと設定ファイルで動作確認できます。
ESP32C3をUSB接続した状態で実行すると、期待通りに動くか分かります。
~/.platformio/packages/tool-openocd-esp32/bin/openocd -f ~/.platformio/packages/tool-openocd-esp32/share/openocd/scripts/board/esp32c3-builtin.cfg

ruleが設定されていなかったりUSB接続されてないと、下記のようなログが表示されます。
Open On-Chip Debugger  v0.11.0-esp32-20220706 (2022-07-06-15:48)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Info : esp_usb_jtag: VID set to 0x303a and PID to 0x1001
Info : esp_usb_jtag: capabilities descriptor set to 0x2000
Warn : Transport "jtag" was already selected
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Error: libusb_open() failed with LIBUSB_ERROR_ACCESS
Error: esp_usb_jtag: could not find or open device!

Error: Unsupported xlen: -1
Error: Unknown target arch!

期待通りに動くと、下記のようなログが表示されます。
接続はCtr-cで終われます。
Open On-Chip Debugger  v0.11.0-esp32-20220706 (2022-07-06-15:48)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Info : esp_usb_jtag: VID set to 0x303a and PID to 0x1001
Info : esp_usb_jtag: capabilities descriptor set to 0x2000
Warn : Transport "jtag" was already selected
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : esp_usb_jtag: serial (84:F7:03:25:81:B4)
Info : esp_usb_jtag: Device found. Base speed 40000KHz, div range 1 to 255
Info : clock speed 40000 kHz
Info : JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)
Info : datacount=2 progbufsize=16
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0x40101104
Info : starting gdb server for esp32c3 on 3333
Info : Listening on port 3333 for gdb connections

riscv32-esp-elf-gdbのためにpython2をインストール

対応

内蔵jtagと連携するプログラムriscv32-esp-elf-gdbの動作にpython2が必要なのでインストールします。
sudo apt install python2.7-dev

動作確認

python2無しでplatformioのデバッグを実行してもビルドをしたあと何も始まりません。
ESP32C3のプロジェクトのディレクトリ内でgdb(gnu debugger)を指定してplatformioのデバッグを実行すると、gdbが期待通りに動くか確認できます。
pio debug --interface=gdb

python2.7-devをインストールしていないと下記のログが表示されます。
Warning! Your `/etc/udev/rules.d/99-platformio-udev.rules` are outdated. Please update or reinstall them.
More details: https://docs.platformio.org/en/latest/core/installation/udev-rules.html
/home/asuki/.platformio/packages/toolchain-riscv32-esp@8.4.0+2021r2-patch5/bin/riscv32-esp-elf-gdb: error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory

期待通りに動くとgdbのコマンド受付画面が表示されます。
自分が試した範囲ではこのモードを閉じる操作方法は分からなかったので、終了するにはターミナルを閉じます。(Ctr-cでgdbは止まりますが、bashに戻りません。)
pio debug --interface=gdb
Warning! Your `/etc/udev/rules.d/99-platformio-udev.rules` are outdated. Please update or reinstall them.
More details: https://docs.platformio.org/en/latest/core/installation/udev-rules.html
Reading symbols from /home/asuki/pio/esp32-xbox-example/.pio/build/esp32c3u/firmware.elf...
(gdb)

デバッグのための設定と手順

platformio.iniにdebug_toolとしてbuiltin-jtagを使う設定を書きます。
USBシリアルを有効にしたい場合はARDUINO_USB_CDC_ON_BOOTとARDUINO_USB_MODEを定義します。
platformio.ini
[env:esp32c3u]
platform = espressif32
framework = arduino
board = esp32-c3-devkitm-1
build_flags =
-DARDUINO_USB_CDC_ON_BOOT
-DARDUINO_USB_MODE
debug_tool = esp-builtin

上記の設定で一度プログラムをESP32C3に書き込みます。
デバッグモードを開始してもプログラムの書き換えはされないので、デバッグ対象のプログラムを先に書き込んでおく必要があります。


プログラムのどこかにブレークポイントを設定します。
VSCodeのプログラムの行番号の横をクリックするとブレークポイントの設置や削除ができます。
ブレークポイントの設定は、プログラム書き込み前でもデバッグ開始後でも良いです。


プログラムを書き込んだら 実行 -> デバッグの開始 を選び、デバッグを開始します。


ブレークポイントに到達したら止まります。
デバッグ開始から初回の停止までに自分の環境では20秒ほどかかりました。
ボタン操作で継続、ステップオーバー、ステップイン、ステップアウト、再起動、停止を選べます。


jtagとUSBシリアルの通信は別れているので、デバッグ中でもシリアルポートで出力を確認できます。


ブレークポイントで止まってもmillisの加算は止まらず経過時間に応じて増えるので、millisを利用する処理のデバッグは工夫が必要です。
下記の例ではプログラムでは500msの待ち時間としていますが、ブレークポイント停止状態で放置した時間(26442 -> 76848では約50秒)分millisの出力値が増えています。


終わり

jtag用のrulle配置とpython2が必要で手間取りましたが、ubuntu上のplatformioを利用してESP32C3のjtagデバッグを動かせました。
デバッグしながらserial出力を見れたのは嬉しかったのですが、millisがブレークポイントで停止中も増えてしまうのは不都合な場面がありそうでした。

参考

ESP32C3の内蔵jtagに関する公式の説明です。
Configure ESP32-C3 built-in JTAG Interface
JTAG Debugging

openocd-esp32のrule設定が必要と把握した記事です。
Visual Studio Code で ESP32 の JTAG debug 環境を構築 (Ubuntu 版)

udev rulesに関するページです。
99-platformio-udev.rules
60-openocd.rules

0 件のコメント :