2021年7月15日のNature Bath vol.13で発表した 「RustでCMSIS-DAPじっそうしてみた。」トークの資料です。
タイトルの通り、RustでCMSIS-DAPを実装してみた経緯と感想について説明しています。
RustでCMSIS-DAPを実装してみたNATURE BATH VOL.13 2021/07/15Kenta Ida (@ciniml)
View Slide
自己紹介•井田 健太 (@ciniml)•仕事:FPGAの論理設計•使用言語:C++, SystemVerilog, Rust, C#•組込みRust本の1割くらい書きました(サンプルアプリ作ったり、デバッガ試したり)→2021/7/15Rust CMSIS-DAPで を実装してみた
Rust CMSIS-DAPで を実装してみたというわけで、デバッガの話をします2021/7/15
Wio Terminalとは?2021/7/15Rust CMSIS-DAPで を実装してみた• 組込みRust本でターゲットとしたマイコン・モジュール• 液晶、ボタン、スピーカーが筐体に収まっている• メインCPUはArmコア• ATSAMD51P19A (Microchip)• Cortex-M4F@120MHz• 無線通信機能 (WiFi, BLE) もついてる• バッテリは含まず• LiPoの処分に困るので助かる
組込みソフトウェアのデバッグ2021/7/15Rust CMSIS-DAPで を実装してみた•MCUにはデバッグのための機能が組み込まれている• e.g. Armの場合:CoreSight DAP•JTAGやSWDといったプロトコルでデバッガと接続
CMSIS-DAP2021/7/15Rust CMSIS-DAPで を実装してみた•Cortex系プロセッサ内部のデバッグ機能にUSB経由でアクセスするための仕様とファームウェア実装• ホストとUSB経由で通信• ターゲットとJTAGもしくはSWDで通信•Armが策定しており、仕様とソースコードが公開されている• 現在はGitHub上で管理されている• https://arm-software.github.io/CMSIS_5/DAP/html/index.htmlホストPCUSBついてるArm MCU デバッグしたいArm CPUCMSIS-DAPUSBJTAGSWD
Wio Terminalのデバッグ事情2021/7/15Rust CMSIS-DAPで を実装してみた•デバッグ用コネクタ• 0.5[mm]x10ピン FFCコネクタ• FFC+FFC変換基板でデバッガに接続• どちらもAmazonやaitendoで買える• 機材リストはサポートページに記載https://github.com/tomoyuki-nakabayashi/Embedded-Rust-from-Basics/tree/main/debug
デバッグ用アダプタを作る2021/7/15Rust CMSIS-DAPで を実装してみた•USBついてるMCUがあれば作れる•今回はSeeeduino XIAOを使用• ATSAMD21G18• USB2.0 FS•ファームは既存のもの• Seeedが移植している(のを改造したやつ) CMSIS-DAPファームウェア入りSeeeduino XIAOホストPCのUSBポートへ
既存CMSIS-DAPファームウェアの欠点2021/7/15Rust CMSIS-DAPで を実装してみた•Windowsへのインストールがメンドイ!• ベンダ固有クラスなのでドライバが必要• Zadigを使ってドライバを導入する必要がある•挿しただけで動くようにしたい!• Zadigの手順書くのメンドイねん→WCIDの設定をしよう!
WCID (Windows Compatibility ID)2021/7/15Rust CMSIS-DAPで を実装してみた• 汎用USBドライバ(WinUSB)を自動インストールするための仕組み• Microsoft OS Descriptor 2.0という仕様にしたがったディスクリプタでデバイスがWinUSB対応であることを表明できる• ファームウェア改造しよう!• SeeedのCMSIS-DAPファームウェアは現行の構造上返せないことが判明 (残念…)→Rustで実装すればいいんじゃない?SeeedのCMSIS-DAPファーム=WCID非対応
RustでCMSIS-DAPを実装する2021/7/15Rust CMSIS-DAPで を実装してみた•そもそも可能なのか?• Seeeduino XIAOのコードをRustで書けるか? →書ける• xiao_m0クレートを使えばいい• USBを扱うクレートはあるのか? →ある• usb-deviceクレート• xiao_m0クレートがusb-deviceクレート内のトレイトを実装している→実装しよう!
開発中の風景2021/7/15Rust CMSIS-DAPで を実装してみたデバッガのデバッグ用XIAORust実装版ファームのXIAOSeeeduino XIAO用ベースボード実験用デバッグ対象のWioTerminal
開発の流れ2021/7/15Rust CMSIS-DAPで を実装してみた•USBデバイスとしての機能を実装していく• usb_deviceクレートのUsbClassトレイトを実装するだけ• コンフィグレーション・ディスクリプタを返す• ストリング・ディスクリプタを返す• etc...•USBデバイス開発としてはかなり楽impl UsbClass forCmsisDapInterface <‘_, B> {fn get_configuration_descriptors(...) {...}fn get_bos_descriptors(...) {...}fn get_string(...) {...}fn control_in(...) {...}...}
動作確認2021/7/15Rust 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=testInfo : CMSIS-DAP: SWD SupportedInfo : CMSIS-DAP: FW Version = 2.00Info : CMSIS-DAP: Serial# = PiyoInfo : CMSIS-DAP: Interface Initialised (SWD)Info : SWCLK/TCK = 0 SWDIO/TMS = 0 TDI = 0 TDO = 0 nTRST = 0 nRESET = 0Info : CMSIS-DAP: Interface readyInfo : clock speed 2000 kHzInfo : SWD DPIDR 0x2ba01477 // SWDでターゲットと通信して読んだ値Info : atsame5.cpu: hardware has 6 breakpoints, 4 watchpointsInfo : starting gdb server for atsame5.cpu on 3333Info : 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 halttarget halted due to debug-request, current mode: ThreadxPSR: 0x01000000 pc: 0x0000056c msp: 0x2000d6a0(gdb) contContinuing.^C...(gdb) info reg // レジスタ読み出しr0 0x6 6r1 0x19f1 6641...pc 0x75fe 0x75fe core::convert::From forembedded_graphics::pixelcolor::rgb_color::Rgb565>::from+64>xPSR 0x41000000 1090519040...
動作確認 (Windows)2021/7/15Rust CMSIS-DAPで を実装してみた•WCID対応→OK• WINUSBと互換性アリ•実際にWinUSBドライバがロードされているRust実装版CMSIS-DAP=WCID対応
実装してみて感じたRustの便利なところ2021/7/15Rust CMSIS-DAPで を実装してみた•cargo便利• 外部ライブラリの導入が用意• C/C++だとライブラリ入れるの面倒なので…•ハードウェアの抽象化が良くできている• usb-deviceクレートを使えば驚くほど簡単にUSBデバイスが作れる• usb-deviceクレートを使って汎用のCMSIS-DAP実装• XIAO以外のハードでも動作するはず• そのうちRaspberry Pi Picoあたりで試したい
実装してみて感じたRustの便利なところ2021/7/15Rust 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;
実装してみて感じたRustの便利なところ2021/7/15Rust CMSIS-DAPで を実装してみた•結局のところ、• 現代的な仕様の言語• 組込みで使える要求コストの低さ• GCなし、ゼロコスト抽象化、etc...というところが便利(ライフタイムのチェックとかの安全性は言わずもがな)
まとめ2021/7/15Rust CMSIS-DAPで を実装してみた•とりあえずCMSIS-DAPうごいた•Rustがいろいろ便利なのでサクサク開発できた• cargo便利• usb_deviceクレート便利
余談:Arm以外のマイコンはどうなの?2021/7/15Rust CMSIS-DAPで を実装してみた• RISC-V• Tier2サポート• ESP32• XtensaバックエンドのLLVMメインストリームへのマージ停滞中• ISAリファレンスが無い問題は解消• Espressifがドキュメントを用意• 2021/6以降動きが無• LLVMにマージされたらRustもあるいは?• 現状は自前でrustcビルドが必要
おしまい2021/7/15Rust CMSIS-DAPで を実装してみた