Closed ciniml closed 2 years ago
Seeeduino XIAOにこだわる理由がXIAO RP2040が出た以上特に無いので、さっさとRP2040にも対応できるようにする。
XIAO (SAMD21) とXIAO RP2040の両方を並行して整理していけば、異なるMCU間でのちょうどよい抽象化層の検討もつくだろう。たぶん…
rp-halにはXIAO RP2040のBSPはまだないが、とりあえずRPi Pico向けで動くと思うので、まずは rp-pico
クレートを使ってRP2040実装をしてみる。
USBシリアルのサンプルあるので、これベースにすればDAPの実装はすぐできるとおもわれる。PIOつかってゴニョゴニョとかはそのうちやろう。 https://github.com/rp-rs/rp-hal/blob/main/boards/rp-pico/examples/pico_usb_serial_interrupt.rs
とりあえずXIAO (SAMD21) と XIAO RP2040版を boards
ディレクトリ以下に入れるようにして、GPIOでBitBangする処理の共通部分を切り出すなどした。
https://github.com/ciniml/rust-dap/tree/2-refactor-examples/boards
SAMD21版はSWD接続できるのを確認できたが、RP2040版はまだ接続できない。 現状手元にロジアナがなくて波形観測できないので、帰ったら試すことにしよう。
未初期化のポートの出力が有効になっていたらしく、そのピンがターゲットのリセットにつながっていたので、ターゲットがリセット状態になっていただけだった。(SWD的には正しく動いていた)
というわけで、RP2040版も動いた。
RP2040版をなんとか動かせました。 LinuxからUSBデバイスとして認識されなかったり、 UARTインターフェースを無しにしてやらないとWindowsでデバイスマネージャーに表示されるもののCMSIS-DAPのデバイスのハンドルを取得できない謎の挙動がありました。 UARTありの時にBOS/WCID周りを修正してCMSIS-DAPのインターフェースにWinUSBドライバを割り当てるというのは上手く出来たんですが。
ウチの環境だとLinuxで特に問題なく認識してるんですけどなんでだろう… dmesgで何かエラーとか出てる感じですかね?
あとそういやまだLinuxでしか試してなかったですね…
特に現状リポジトリに置いてるコードから変更なしで、Windowsで認識しましたね。何か違うんですかね… Windows11にしたせいか、デバイスのドライバ削除ができないので、こちらの環境はあまりクリーンではないかもしれませんが。
RP2040向けのUART実装を始めたが、どうもUART割り込み周りの実装は rp-hal 0.3.0ではまだ入っておらず、mainブランチを使う必要がありそう。
https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/uart/reader.rs
また、お邪魔します。 Linux については再度検証したところ動くことを確認出来ました。 今度は Xiao_m0 の方も使って Windows 10 環境で挙動を調べましたが、RP2040 の場合と同様に認識されるものの使えません。認識の様子は、上で挙げて下さったデバイスマネージャの画像と同じです。シリアルポートのエコーバックは動きます。 これと似た現象は見たことがないのでじっくり調べるつもりです。
ヒント1: "USB Composite Device" の部分に WinUSB ドライバを強制的に(オレオレAuthenticodeによって)割り当てると ソフトウェアから使えるようになることが分かりました。ソフトウェアは openocd 、pyocd 、rusb で実装した自作テストプログラムです。
ヒント2: DAP-Link を改造して CMSIS-DAP の bulk インターフェース と シリアルポート だけにすると同様に認識するのに使えないものになりました。Linux では使えます。デバイスの根幹に WinUSB ドライバを割り当てると使えます。
素直に考えると WebUSB ( WinUSB ではなく WebUSB ) のインターフェースを定義しておくことがうまく動くために必要、 となりますが、はたして?
他の Windows 環境 、Windows 11 の環境などでも試してみたいと思います。
なるほど。そういえばComposite DeviceにしてからWindowsで動くの確認したか怪しいですね。確認しておきます。
…なんかそういやlibusbでのデバイス列挙時の見え方が変わってて、OpenOCDで見つけてくれなかったので、なんかOpenOCD側いじったような気がしてきた。
いずれにせよ、そもそも rust-dap
実装したの、Windowsでzadig無しでドライバが入るDAPLink実装が欲しかったからなので、対応しようと思います。
UARTの実装が難航中。共有リソースの効率的な管理が面倒になってきたので、RTICを使うことにする。
割り込みタイミングとか見ている限り、RX FIFOが半分以上たまった状態で漸く UART0_IRQ
が起きていた。
原因はuartのインスタンスのロックをUSB_IRQ内でusb_serialの送信バッファ分を送り終わるまで取ったままだったため。
UARTもreader/writerにsplitできるので、splitしたうえでそれぞれ個別にロックを取るように修正して、ループバックが動くようになった。
一旦欲しい機能はRP2040版に実装できたのでmergeする。 https://github.com/ciniml/rust-dap/pull/6
忘れないうちに波形のログだけ貼っておく
debug_led
UART0_IRQ内のUART受信処理で、1文字受信ごとにトグルdebug_irq_led
UART0_IRQの入り口でhigh, 出口でlowdebug_irq_usb_led
USBCTRL_IRQの入り口でhigh, 出口でlow波形を見る限り、 UARTのデータが半分以上貯まった時 (図だと24個目の受信中) に割り込みが起きているのが分かる。 (パケット図の23に現在位置マークがついている)
また、送受信処理中は基本的に USBCTRL_IRQ の中で処理が実行されている。これは送信処理自体を割り込み処理中に実行しているからである。
USB処理周りに悪影響が出てきた場合は、UART送信処理をUSB IRQから追い出してメインループ内でやるようにしたほうがよい。
examples
に移動するなど)現状の問題点としては、
SwdIo
traitの実装がプラットフォームごとに必要になっているが、実際のところはGPIO操作するところ以外のSWD
のプロトコル共通の部分もかなりプラットフォーム依存側に含まれてしまっている。https://github.com/ciniml/rust-dap/blob/main/rust-dap-xiao/src/main.rs#L135
これは、
SwdIo
インターフェースの実装として将来的にハードウェア機能を使えるように、ある程度抽象度高めに作っているからだが、現状はGPIOの直接操作部分との間がかなり存在している。この部分を適切に切り出して、移植側では最低限のGPIOの上げ下げや周波数設定程度の操作で動かせるようにするように、もう一段階中間レイヤを挟む。