なんちゃってシリアル

ATtiny2313でUSBtoシリアル変換器を作ろうと思う。


  • プロトコルはいろいろ考えたが、コントロール転送(ベンダーリクエスト)のみを使うやり方で落ち着いた。
    • これだとエンドポイントを用意しなくて良いので、コードサイズ、SRAMサイズを最小に出来る。
  • 8バイトのコマンドパケットを送って、必要なら8バイトのリターンパケットを受け取る。
  • コマンドパケットの内容(ベンダーリクエスト)
       0      1      2      3      4      5      6      7
    +------+------+---------------------------+-------------+
    | req  | cmd  | 送信データ(最大4バイト)|   wlength   |
    +------+------+---------------------------+-------------+
    • reqはbmRequestTypeである。
    • wlengthは8固定(の予定)これはデバイスからホストへの受信パケットが後続する意味。
    • cmdは送信バイト数(0〜4)
    • cmdが5以上になった場合は、特殊コマンドとして解釈(ボーレート設定等)


  • 受信パケット
       0      1      2      3      4      5      6      7
    +------+------------------------------------------------+
    | size |     受信データ(最大7バイト)                 |
    +------+------------------------------------------------+
    • sizeは0〜7
    • sizeのMSBが1になるときは送信が拒否された。(TxBuf FULL)
    • その場合PC側は同じデータを再送する。
  • ターミナルソフト
    • AVR_Monitを改造して作る。
    • オプションで仮想エコーバックポートに対応したい。
  • ファーム
    • RS232C受信はUSART割り込み駆動。
    • 送信はメインループ内のPoll()のループ内に仕掛ける(1ループで1文字)
    • ベンダーリクエストのパケットが来たら、送信バッファにとりあえず4文字をためておいて
    • USART受信したバッファをホストに送る。
    • 送信バッファが空になっていない場合は再送フラグを立てて、送信データを捨てる。

  • この一連のパケットのやり取りは普通のUHCIなら4フレーム(4mS)掛かる。
  • SiSのOHCI(EHCI)では1フレーム(1mS)でいける。
  • 普通のEHCI(intel含む)でも、間にHiSpeedハブを挟むことによって だいたい1フレームで応答が帰ってくるようだ。

ということは

  • 送信スループットは最大4kB/秒(32Kbps相当)
  • 受信スループットは最大7kB/秒(56Kbps相当)
  • ハブを挟むとか、SiSのチップセットを使うとかの工夫をしない状態だと、この1/4。
  • 送信は手入力のときなどは1回に1バイトになり、アップロードのときは4バイトまでいける。(と思う・・・)
  • これで手を打とうではないか。
  • かろうじてMIDI速度だ。

なぜLowSpeedのBulkを使わない?

  • VistaやLinuxに対応できない。
  • 残念だが、HiSpeedハブに濾過される。
  • 最高速のSiSのEHCIでもバルクパケットの往復だと2フレーム掛かってしまう。
  • だったら、1フレームで送受が完結するコントロール転送のほうがましだ。

なぜCDCクラスにしないのか?

  • これもたぶんHiSpeedハブに濾過される。
  • ATtiny2313では逆立ちしても無理(コードサイズが256バイト以上オーバーする)

なんちゃって方式ではあるが、うまくいけば仮想COMポートのエコーバックを利用してteratermからも使えるようになる(といいなぁ・・・)


LowSpeed AVRUSBの挙動に関するまとめ


転送モードの種類

どのみちUSBにはこれだけしか転送モードは存在しない。

転送モード特徴所要フレーム数速度
コントロール転送各種セットアップに使われるほか、ベンダー独自のコマンドも追加できる。一回のトランザクションで1〜4フレーム程度(注1、2)8kB/秒〜2kB/秒(注1、2)
インタラプト転送一定期間おきに起こるような転送に使うLowSpeedの規格では、10フレームに1回よりも短く出来ないと定められている。実際それ以下には出来ない1kB/秒以下
バルク転送空いているUSB帯域を使ってフルに大量のデータを転送するのに向いている。(注3)1フレームに1〜4パケット程度(注4)8kB/秒〜32kB/秒(注4)
アイソクロナス転送主にUSBオーディオなどでストリームデータを一定の帯域で送るのに使われるLowSpeedでは非対応LowSpeedでは非対応
  • USBにおける1フレームとは1mSのことで、USBドライバーは1フレームを単位としてスケジューリングや同期処理を行っているようだ。このため、アプリケーションから同期(完了復帰型)read/writeを行なうと必ず1mSの整数倍の時間だけ待たされる。
  • USB2.0で定義された480Mbpsモード(HighSpeed)においては、1フレームの1/8にあたる125μ秒を単位とするマイクロフレームが定義されたので、1mSというレイテンシーをその1/8に短縮することが出来る。


  • 注1)intelを含む多くのホストコントローラで実測すると4フレーム掛かるので2kB/秒。
    • これはコントロール転送8バイトを送り、リザルト8バイトを受信した場合。
  • 注2)SiSのコントローラを使用した場合、コントロール転送は1フレームで完結し、8kB/秒になる。
    • SiSコントローラを使用しない場合でも、HighSpeedハブを挟めば、ほぼ8kB/秒の速度が出せるようだ。
    • これは、ホストから見てLowSpeedのデバイスがHighSpeedとみなされることで、トランザクションの時間単位が1mSから1/8mSに短縮される効果のようだ。
  • 注3)規格上、LowSpeedでのバルク転送はサポートされていない
  • はずだが、WindowsXPでは何故か使用できる。
  • Vistaでははじかれる(たぶん)
  • HighSpeed(480Mbps)ハブを挟んだ場合も濾過されて無視される(現在ハブのサンプル数が1個なので、まだ断言は出来ない)
  • 注4)1フレーム(1mS)に4パケットを送るためにはusb_bulk_write()で一度に32バイトのデータを渡す等の工夫が必要。そうでないときはusb_bulk_write()が常に1mS待つので結局1フレームに1パケット(8バイト)となる。

結論から言って、LowSpeedではどの転送モードが使えるのか?

  • LowSpeedで正式にサポートされている転送モードはコントロール転送とインタラプト転送の2種類だけだ。
  • インタラプト転送はポーリング間隔が10mS単位になるので、とても遅くて使えない。

結局LowSpeedにおいてはコントロール転送しか使いものにならないということだ

UHCIは遅い

  • intel製のUSBホストコントローラのこと。
  • 遅いの意味は、1回のコントロール転送(リザルト8バイト受信を入れて)に4フレーム(4mS)も掛かるという意味。
  • 1フレームで済ませてくれと言いたい。

SiSのOHCIは速い

  • SiS製のUSBホストコントローラのこと。
  • 速いというのは語弊があるが、ほぼ理論上のレイテンシーで駆動できている。

EHCIで速くしたければHiSpeedハブを挟め

  • USB1.1までのホストコントローラは歴史的事情でインテル(UHCI)とそれ以外(OHCI)という風に実装が別々になってしまった。
  • その反省を踏まえてUSB2.0のホストコントローラの設計(ハードウェアのインターフェース)はEHCIに統一された。
  • つまり、現在USB2.0をサポートしているホストコントローラは全てEHCI規格なはず。(パソコンに内蔵されるチップセットの話として)
    • 但し、ホストから見てFullSpeed,LowSpeedでの接続時はUHCIもしくはOHCIとしての動作になる。

参考

上記の資料によれば、VIAはUHCIに属するので、やっぱり遅いわけだ。

OHCI>NEC、SiS、Opti 等の Chip に使用されています。

  • ということなので、不幸にもマザーボードがインテルとVIAの人はNECのUSBカードを買ってくればいいわけだ。
  • SiSチップが乗っているUSBカードって、見たこと無いなぁ・・・。
  • Optiって、まだ生きてるの?

LowSpeedバルク転送というのは裏技になってしまったが、どんなときに有効か?

  • USB経由のRS232Cシリアルデバイスを作る場合。例: (AVR-CDC
    • CDC(通信デバイスクラス)のRxD、TxDストリームはBulkタイプのエンドポイントで実装されているので、必然的にバルク転送を使うことになる。
  • コントロール転送は常にエンドポイント0が使われるので、それとは独立したエンドポイントを用意したいとき。
  • コントロール転送よりも速度(帯域)が欲しいとき。

制限事項

  • ただし、上記の通りWindowsXPに限定される。
  • デバイスとの間にHighSpeedハブを挟むことが出来ない。

目次