Seeed XIAO RP2040 で pico-usb-blaster を動かす ― Raspberry Pi Pico 前提コードを XIAO 向けに移植した記録

Intel FPGA を扱うとき、手元にある USB-Blaster が足りなかったり、実験用にもう 1 本ほしいと思うことがあります。

そのようなときに便利なのが、RP2040 を使って USB-Blaster 互換デバイスを作る方法です。

今回は、GitHub 上で公開されている thisiseth/pico-usb-blaster をベースにして、Seeed XIAO RP2040 で動作する XIAO 版 USB-Blaster を作成しました。最終的に、Quartus から MAX 10 デバイスを認識し、実際に書き込みまでできるところまで確認できました。

この記事では、どこでつまずいたか、何を修正したか、最終的にどうやって動作確認できたかをまとめます。

元にしたリポジトリ

ベースにしたのは以下のプロジェクトです。

thisiseth/pico-usb-blaster

このプロジェクトは Raspberry Pi Pico を前提としており、RP2040 を USB-Blaster 互換デバイスとして動かすものです。ただし、そのままでは Seeed XIAO RP2040 には持っていけない部分 がありました。

何がそのままでは動かなかったのか

最初は「GPIO の割り当てだけ変更すれば動くだろう」と考えていました。しかし、実際にはそこまで単純ではありませんでした。

問題は主に次の 2 点でした。

1. blaster.c が Pico 前提の GPIO 実装になっている

元の実装は、GPIO が連番で並んでいることを前提にしていたり、mask による一括操作を前提にしていました。Raspberry Pi Pico では都合が良くても、XIAO RP2040 で任意の GPIO に信号を割り当てたい場合には、この前提が邪魔になります。

そのため、XIAO 版では blaster.c任意 GPIO に対応した形で書き直す 必要がありました。

2. vendor control request の受け口が環境に合っていなかった

最初は USB としては見えているのに、Quartus から実際の通信が始まらない状態に悩まされました。jtagconfig --debug では USB-Blaster として見えるのに、JTAG 信号は出ない、という状態です。

調べていくと、USB の vendor request に対する処理を tud_control_request_cb() ではなく tud_vendor_control_xfer_cb() で受ける必要がある ことが分かりました。ここが合っていないと、ホスト側からの vendor request が STALL してしまい、その先の通信に進みません。

今回の XIAO RP2040 側のピン割り当て

今回使用したピン割り当ては以下の通りです。

  • TCK = GPIO2
  • TMS = GPIO3
  • nCE = GPIO4
  • nCS = GPIO6
  • TDI = GPIO7
  • TDO = GPIO26
  • DATAOUT / nSTATUS = GPIO27

JTAG 用途として主に重要なのは TCK / TMS / TDI / TDO / GND ですが、元実装の流れに合わせて nCE, nCS, DATAOUT/nSTATUS も割り当てています。

途中での切り分け

今回かなり役に立ったのは、USB 側と JTAG 側を分けて切り分けたことです。

最初の段階では、

  • USB として列挙される
  • jtagconfig --debug でも USB-Blaster として見える
  • しかし JTAG 信号が出ない

という状態でした。

そこで、main.c にデバッグ用 GPIO を仕込んで、

  • main() に到達しているか
  • mount しているか
  • control request が来ているか
  • bulk transfer が来ているか

を段階ごとに確認しました。

その結果、

  • mount までは OK
  • しかし vendor control request が来ていない、または処理できていない

ことが分かりました。さらに Linux 側で usbmon を見ることで、vendor request が STALL している ことも確認できました。

ここで main.c の USB control request の処理を見直し、tud_vendor_control_xfer_cb() に変更したところ、control / bulk ともに通るようになりました。

最後の詰まりどころ

USB 通信が通ったあとも、まだ JTAG チェーンの認識には失敗していました。

原因は blaster.cshift() 処理でした。元の考え方のままだと、条件によって TDODATAOUT/nSTATUS を切り替えて読んでいましたが、JTAG 用途では常に TDO を読むべきでした。

この部分を修正して、JTAG shift 時には常に TDO をサンプリングするようにしたところ、ようやくチェーン認識に成功しました。

最終結果

最終的には、jtagconfig --debug で以下のようにデバイスを認識できました。

1) USB Blaster [2-2.8]
   (JTAG Server Version 20.1.1 Build 720 11/11/2020 SJ Standard Edition)
  0318A0DD   10M04S(A|C) (IR=10)

  Captured DR after reset = (0318A0DD) [32]
  Captured IR after reset = (155) [10]
  Captured Bypass after reset = (0) [1]
  Captured Bypass chain = (0) [1]
  JTAG clock speed 6 MHz

この状態まで来たあと、Quartus Programmer から 実機への書き込みも成功 しました。

変更点の要点

今回の XIAO 版で重要だった変更点をまとめると、次の通りです。

usb_descriptors.c は元のままでよい

最初は descriptor 側を疑いましたが、結論としては GitHub 版そのままで問題ありませんでした

main.c は vendor control transfer の受け方を修正する

main.c では、vendor control request を TUD の汎用 control callback ではなく、tud_vendor_control_xfer_cb() で受けるように変更しました。

blaster.c は XIAO 向けに実質書き直し

  • 任意 GPIO に対応
  • 連番 GPIO 前提を排除
  • 一括 mask 操作依存を排除
  • JTAG shift 時は 常に TDO を読む

このあたりがポイントでした。

使い方

使い方としては、元の pico-usb-blaster のリポジトリに対して、

  • src/blaster.h
  • src/blaster.c
  • src/main.c

を XIAO 版に置き換え、usb_descriptors.c はそのまま使います。

ビルドは通常通りです。

mkdir -p build
cd build
cmake ..
make pico_usb_blaster

生成された UF2 を XIAO RP2040 に書き込めば動作します。

まとめ

今回の移植で感じたのは、「USB として見える」ことと「USB-Blaster として実際に使える」ことは別だということです。最初は descriptor や VID/PID の問題に見えても、実際には control request の受け方や、JTAG shift の細かな実装差が本質でした。

XIAO RP2040 は小型で扱いやすく、手元に余っていることも多いので、ちょっとした USB-Blaster 互換器として使えるとかなり便利です。同じように XIAO RP2040 で pico-usb-blaster を動かしたい方の参考になれば幸いです。

補足

  • ターゲット FPGA との GND 共通 は必須
  • 電圧レベル互換は要確認
  • JTAG 配線はできるだけ短くする
  • 今回は JTAG 用途での動作確認 が中心で、非 JTAG モードの詳細確認は行っていません

参考

ダウンロード

XIAO RP2040 用 USB-Blaster(ビルド済みUF2+ソース一式)

xiao-rp2040-usb-blaster.zip

すぐ使う(おすすめ)

  1. XIAO RP2040 の BOOT ボタンを押しながら USB 接続
  2. 「RPI-RP2」ドライブが表示される
  3. pico_usb_blaster_xiao_v1.uf2 をコピー

これだけで USB-Blaster として認識されます。

ソースからビルド

src フォルダを元の pico-usb-blaster に上書きしてビルドしてください。

スポンサーリンク
スポンサーリンク
スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
スポンサーリンク