Slide 1

Slide 1 text

RustでCMSIS-DAPを実装してみた NATURE BATH VOL.13 2021/07/15 Kenta Ida (@ciniml)

Slide 2

Slide 2 text

自己紹介 •井田 健太 (@ciniml) •仕事:FPGAの論理設計 •使用言語:C++, SystemVerilog, Rust, C# •組込みRust本の1割くらい書きました (サンプルアプリ作ったり、デバッガ試したり)→ 2021/7/15 Rust CMSIS-DAP で を実装してみた

Slide 3

Slide 3 text

Rust CMSIS-DAP で を実装してみた というわけで、デバッガの話をします 2021/7/15

Slide 4

Slide 4 text

Wio Terminalとは? 2021/7/15 Rust CMSIS-DAP で を実装してみた • 組込みRust本でターゲットとしたマイコン・モジュール • 液晶、ボタン、スピーカーが筐体に収まっている • メインCPUはArmコア • ATSAMD51P19A (Microchip) • Cortex-M4F@120MHz • 無線通信機能 (WiFi, BLE) もついてる • バッテリは含まず • LiPoの処分に困るので助かる

Slide 5

Slide 5 text

組込みソフトウェアのデバッグ 2021/7/15 Rust CMSIS-DAP で を実装してみた •MCUにはデバッグのための機能が組み込まれている • e.g. Armの場合:CoreSight DAP •JTAGやSWDといったプロトコルでデバッガと接続

Slide 6

Slide 6 text

CMSIS-DAP 2021/7/15 Rust CMSIS-DAP で を実装してみた •Cortex系プロセッサ内部のデバッグ機能に USB経由でアクセスするための仕様とファームウェア実装 • ホストとUSB経由で通信 • ターゲットとJTAGもしくはSWDで通信 •Armが策定しており、仕様とソースコードが公開されている • 現在はGitHub上で管理されている • https://arm-software.github.io/CMSIS_5/DAP/html/index.html ホスト PC USBついてるArm MCU デバッグしたい Arm CPU CMSIS-DAP USB JTAG SWD

Slide 7

Slide 7 text

Wio Terminalのデバッグ事情 2021/7/15 Rust CMSIS-DAP で を実装してみた •デバッグ用コネクタ • 0.5[mm]x10ピン FFCコネクタ • FFC+FFC変換基板でデバッガに接続 • どちらもAmazonやaitendoで買える • 機材リストはサポートページに記載 https://github.com/tomoyuki-nakabayashi/Embedded-Rust-from- Basics/tree/main/debug

Slide 8

Slide 8 text

デバッグ用アダプタを作る 2021/7/15 Rust CMSIS-DAP で を実装してみた •USBついてるMCUがあれば作れる •今回は Seeeduino XIAOを使用 • ATSAMD21G18 • USB2.0 FS •ファームは既存のもの • Seeedが移植している (のを改造したやつ) CMSIS-DAPファームウェア入り Seeeduino XIAO ホストPCの USBポートへ

Slide 9

Slide 9 text

既存CMSIS-DAPファームウェアの欠点 2021/7/15 Rust CMSIS-DAP で を実装してみた •Windowsへのインストールがメンドイ! • ベンダ固有クラスなのでドライバが必要 • Zadigを使ってドライバを導入する必要がある •挿しただけで動くようにしたい! • Zadigの手順書くのメンドイねん →WCIDの設定をしよう!

Slide 10

Slide 10 text

WCID (Windows Compatibility ID) 2021/7/15 Rust CMSIS-DAP で を実装してみた • 汎用USBドライバ(WinUSB)を 自動インストールするための仕組み • Microsoft OS Descriptor 2.0という仕様にしたがった ディスクリプタでデバイスがWinUSB対応であることを 表明できる • ファームウェア改造しよう! • SeeedのCMSIS-DAPファームウェアは 現行の構造上返せないことが判明 (残念…) →Rustで実装すればいいんじゃない? SeeedのCMSIS-DAPファーム =WCID非対応

Slide 11

Slide 11 text

RustでCMSIS-DAPを実装する 2021/7/15 Rust CMSIS-DAP で を実装してみた •そもそも可能なのか? • Seeeduino XIAOのコードをRustで書けるか? →書ける • xiao_m0クレートを使えばいい • USBを扱うクレートはあるのか? →ある • usb-deviceクレート • xiao_m0クレートがusb-deviceクレート内のトレイトを実装している →実装しよう!

Slide 12

Slide 12 text

開発中の風景 2021/7/15 Rust CMSIS-DAP で を実装してみた デバッガのデバッグ用XIAO Rust実装版ファームのXIAO Seeeduino XIAO用 ベースボード 実験用デバッグ対象の WioTerminal

Slide 13

Slide 13 text

開発の流れ 2021/7/15 Rust CMSIS-DAP で を実装してみた •USBデバイスとしての機能を実装していく • usb_deviceクレートのUsbClassトレイトを実装するだけ • コンフィグレーション・ディスクリプタを返す • ストリング・ディスクリプタを返す • etc... •USBデバイス開発としてはかなり楽 impl UsbClass for CmsisDapInterface <‘_, B> { fn get_configuration_descriptors(...) {...} fn get_bos_descriptors(...) {...} fn get_string(...) {...} fn control_in(...) {...} ... }

Slide 14

Slide 14 text

動作確認 2021/7/15 Rust CMSIS-DAP で を実装してみた •OpenOCDで接続…うごいた! • プログラムの書き込み • 実行・停止 • レジスタの内容取得 $ sudo ~/openocd-pico/bin/openocd -f interface/cmsis-dap.cfg -c "cmsis_dap_vid_pid 0x6666 0x4444" -f target/atsame5x.cfg ... Info : Using CMSIS-DAPv2 interface with VID:PID=0x6666:0x4444, serial=test Info : CMSIS-DAP: SWD Supported Info : CMSIS-DAP: FW Version = 2.00 Info : CMSIS-DAP: Serial# = Piyo Info : CMSIS-DAP: Interface Initialised (SWD) Info : SWCLK/TCK = 0 SWDIO/TMS = 0 TDI = 0 TDO = 0 nTRST = 0 nRESET = 0 Info : CMSIS-DAP: Interface ready Info : clock speed 2000 kHz Info : SWD DPIDR 0x2ba01477 // SWDでターゲットと通信して読んだ値 Info : atsame5.cpu: hardware has 6 breakpoints, 4 watchpoints Info : starting gdb server for atsame5.cpu on 3333 Info : Listening on port 3333 for gdb connections $ gdb-multiarch 8-2-mic_fft // 組込みRust本のスペアナサンプル (gdb) load // WioTerminalに書き込み ... Transfer rate: 19 KB/sec, 8730 bytes/write. // 19[KB/s]なのでまあまあ実用的 (gdb) monitor reset halt target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x0000056c msp: 0x2000d6a0 (gdb) cont Continuing. ^C ... (gdb) info reg // レジスタ読み出し r0 0x6 6 r1 0x19f1 6641 ... pc 0x75fe 0x75fe for embedded_graphics::pixelcolor::rgb_color::Rgb565>::from+64> xPSR 0x41000000 1090519040 ...

Slide 15

Slide 15 text

動作確認 (Windows) 2021/7/15 Rust CMSIS-DAP で を実装してみた •WCID対応→OK • WINUSBと互換性アリ •実際にWinUSBドライバが ロードされている Rust実装版CMSIS-DAP =WCID対応

Slide 16

Slide 16 text

実装してみて感じたRustの便利なところ 2021/7/15 Rust CMSIS-DAP で を実装してみた •cargo便利 • 外部ライブラリの導入が用意 • C/C++だとライブラリ入れるの面倒なので… •ハードウェアの抽象化が良くできている • usb-deviceクレートを使えば驚くほど簡単にUSBデバイスが作れる • usb-deviceクレートを使って汎用のCMSIS-DAP実装 • XIAO以外のハードでも動作するはず • そのうちRaspberry Pi Picoあたりで試したい

Slide 17

Slide 17 text

実装してみて感じたRustの便利なところ 2021/7/15 Rust CMSIS-DAP で を実装してみた •Resultでのエラー伝搬が楽にできる • C++だと例外だが、 組込みC++の場合は無効化されることが多い • スタック巻き戻しのための諸々のオーバーヘッドが嫌われる • ?でエラー発生時のearly returnが簡単に書ける • エラー処理もサクサク書けるので エラーでハングアップとか起こしにくい • タイムアウトとかサボりがちですよね… let result = swd_transfer_inner_with_retry(config, swdio, swd_request, 0)?; write_u32(response, result); *response_count += 1;

Slide 18

Slide 18 text

実装してみて感じたRustの便利なところ 2021/7/15 Rust CMSIS-DAP で を実装してみた •結局のところ、 • 現代的な仕様の言語 • 組込みで使える要求コストの低さ • GCなし、ゼロコスト抽象化、etc... というところが便利 (ライフタイムのチェックとかの安全性は言わずもがな)

Slide 19

Slide 19 text

まとめ 2021/7/15 Rust CMSIS-DAP で を実装してみた •とりあえずCMSIS-DAPうごいた •Rustがいろいろ便利なのでサクサク開発できた • cargo便利 • usb_deviceクレート便利

Slide 20

Slide 20 text

余談:Arm以外のマイコンはどうなの? 2021/7/15 Rust CMSIS-DAP で を実装してみた • RISC-V • Tier2サポート • ESP32 • XtensaバックエンドのLLVMメインストリームへのマージ停滞中 • ISAリファレンスが無い問題は解消 • Espressifがドキュメントを用意 • 2021/6以降動きが無 • LLVMにマージされたらRustもあるいは? • 現状は自前でrustcビルドが必要

Slide 21

Slide 21 text

おしまい 2021/7/15 Rust CMSIS-DAP で を実装してみた