BLE接続の無線式USB-Blasterを作った

はじめに

動き回るロボット上のFPGAを遠隔で書き換えたい!
と思ったのでBLEモジュールを2つ使ってUSB BlasterのJTAGコマンドを中継させてみた。

ロボットにリッチOSを積んでいるならUSB over IP系のソフトウェアを使ってWiFi経由でUSB-Blasterを接続したほうがいいのでは。

ハードウェア

ハードウェア構成と写真を以下に示す。


ハードウェア構成

ハードウェア写真

PCに接続するUSBインターフェースICとしてFT240X、BLEモジュールはBGM220を使用した。FT240XにはUSB-Blasterと同じVID, PID, String Descriptorを書き込んであるためPCからはUSB-Blasterとして認識される。

PCからFT240Xに書き込まれたJTAGコマンドはClient側BGM220によって読み出されそのままServer側BGM220に送信される。ServerはJTAGコマンドに従ってJTAG信号線を操作する。JTAGコマンドによってデータ読み出しが指示された場合、読み出されたデータはServerからClient、ClientからFT240Xへと書き込まれPCが読み出す。

ファームウェア

レスポンスあり(Write & Indicate)とレスポンスなし(Write w/o Response & Nofity)の2つのファームウェアを作って試した。レスポンスなしとはいってもパケットロスが起きたときはリンク層で再送制御が行われるらしいので安心である。

試験的なシステムなので非接続状態においてServerはアドバタイズし続け、Clientは対象のUUIDのサービスを持つサーバーを見つけたら接続を試みる。セキュリティも何もあったものではないシステムである。

レスポンスありバージョン

初めに作ったのがBLEのWriteとIndicateによるレスポンスあり転送バージョンである。レスポンスありの転送ではClient、Server各々の受信バッファに空きが無くなったときにレスポンスを返さないことでさらなるデータの到着を阻止できる。これによりバッファ管理が少し簡単になる。

しかしレスポンスありの転送は最短7.5ms周期で訪れる通信インターバルに1パケットしか送受信できず、レスポンス待ちを含めると15msごとに1パケットしか送受信できない。1パケットに含められるペイロードは最大244バイトであるので最大スループットは約16KB/sである。なお送受信は別々に行えるので16KB/sで送信しながら16KB/sで受信可能であった。

Clientの動作

  • 送信キューに空きがあればFT240Xからデータを読み出す
  • 送信キューにデータがあればServerにWriteで送信する
  • Writeが成功したら送信キューから送信した分のデータを消去する
  • ServerからIndicateでデータを受信したとき
    受信キューに空きがあれば受信データを受信キューに書き込みConfirmを返す
    受信キューに空きが無く受信データを書き込めなかった場合、受信データを一時バッファに保存しConfirmはまだ返さない
  • 受信キューに空きがあれば一時バッファの内容を書き込む
    書き込めたらServerにConfirmを返し一時バッファを消去する
  • 受信キューにデータがあればFT240Xにデータを書き込む
    書き込めた分のデータを受信キューから消去する

Serverの動作

  • ClientからのWriteでデータを受信したとき
    送信キューに十分な空きがあればWriteへResponseを返しJTAGコマンドを実行し、読み出したデータを送信キューに書き込む
    送信キューに十分な空きが無ければ一時バッファへデータを保存しResponseはまだ返さない
  • 送信キューに十分な空きがあれば一時バッファの中のJTAGコマンドを実行し、読み出したデータを送信キューに書き込む
    書き込めたらClientにResponseを返し一時バッファを消去する
  • 送信キューにデータがあればClientにIndicateで送信する
  • Indicateが成功したら送信キューから送信した分のデータを消去する

レスポンスなしバージョン

レスポンスありバージョンは遅すぎたのでレスポンスなしで作り直した。レスポンスなしの場合、通信インターバルあたりに複数のパケットを送受信することが可能なためスループットの向上が見込まれる。

その一方でパケットの受信を拒めなくなるためバッファが溢れるおそれがある。そこで今回はClientが自身の受信キューとServer側の送信キューの空きを管理しながらServerへデータを送信することにした。ClientがJTAGコマンドをパースして受信データサイズを予想するようにしたためこのようなことが可能になった。

Clientの動作

  • 送信キューに空きがあればFT240Xからデータを読み出す
  • Clientの受信キューとServerの送信キューに十分な空きがあればServerにWrite w/o Responseで送信する
    送信キューから送信した分のデータを消去する
  • ServerからNofityでデータを受信したら受信キューに書き込む
  • 受信キューにデータがあればFT240Xにデータを書き込む
    書き込めた分のデータを受信キューから消去する

Serverの動作

  • ClientからのWrite w/o Responseでデータを受信したらJTAGコマンドを実行し、読み出したデータを送信キューに書き込む
  • 送信キューにデータがあればClientにNotifyで送信する
    送信した分のデータを送信キューから消去する

スループット

Cyclone 10 LP(10CL025)をターゲットにコンフィギュレーションを試みた。レスポンスなしにおいてはBLEの変調速度を2Mbpsに引き上げればさらなるスループット向上が望めるだろう。

レスポンスあり : 10.5KB/s (1分8秒)
レスポンスなし : 55KB/s (13秒)

ダウンロード

レスポンスなしバージョンのプロジェクトをここに置いておく。名前にUARTの送受信テストをしていた名残が残っているが。

開発環境はSimplicity Studio 5、BluetoothスタックはBluetooth 3.1.0を使用した。

Client側プロジェクト
Server側プロジェクト

0 件のコメント :

コメントを投稿