標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第424回]

●HIDのデータ転送方式

USBには4つのデータ転送方式があります。
1)コントロール転送  主にデバイス情報をホストに送るのに使われる
2)インタラプト転送  比較的少量のデータを定期的(1ms〜255msごと)に送るのに使われる
3)バルク転送 比較的大量のデータを不定期、高速かつ正確に送るのに使われる
4)アイソクロナス転送 大量のデータを高速に転送するのに使われる

このうちHIDではどの転送方式が使われるのか、ということを確認していませんでした。

1)のコントロール転送は、HIDに限らず、USBでは必須(最初の接続時に必要)なのですから、これがデータ転送に使われるかどうかはともかくとして、とにかくHIDでも必要な転送方式であることに違いはありません。
4)のアイソクロナス転送は大量データが対象ですから、これはHIDでは使えないだろうということは、まあおおよそ想像できます。
2)のインタラプト転送が主に使われるらしいということも、あちこちのドキュメントを読んでいるうちに、わかってきました。
さて、しかし3)のバルク転送がHIDで使えるのかどうか、そこのところは、定かではありませんでした。

それについては、前回紹介しました、USB.ORGのPDF Document HID1_11.pdf(Device Class Definition for Human Interface Devices)に記載があることがわかりました。
その部分を下記に転載いたします。


おお、はっきり書いてありますね。
HIDではControl pipeとInterrupt pipeを使うと書いてあります。
ということは、Bulk転送は使えない、ということです。これで納得です。

あ。
パイプというのは、USB接続での「仮想的」なデータ伝送路のことです。
パイプについてはのちほど説明をいたします。

●フレーム、トランザクション、パケット?

前回はインタラプト転送とバルク転送では1データパケットあたりの最大バイト数が64バイトである、という説明をしました。
それから、USBではHOST(パソコン)とUSB端末がデータのやりとりをするのに、フレームという単位が使われます。ということも書きました。

USBはHOST(パソコン)がコントロールをします。
USB機器(端末装置)は完全にSLAVEとしてHOST(パソコン)に従属しています。
USB機器からHOST(パソコン)に勝手にデータを送ったり、それを要求することはできません。

HOST(パソコン)は1msごとにフレーム(文字通り、まさに「枠」です)という、信号をやりとりするための「ワク」の開始マーク(SOF)を送り、その1msの中で、接続されているUSB機器に順にポーリングをしながら、USB機器にデータを送ったり、またUSB機器にデータを送るように要求します。

前回は話を簡単にするために、そのフレームにのせられるデータはパケットという単位にまとめられて、送受信される、という説明をしました。
インタラプト転送では、1パケットあたり最大64バイトのデータが入れられる、とも説明しました。
そのことは、それで間違いはないのですが、じつはフレームの中で、データが送受信されるときは、「データパケット」単独ではなくて、トランザクションという単位で送受信されるのです。
このあたりがUSBのややこしいところです。

実際にUSBのソフトを書く場合には、こんなことは知らなくても、ファームウェアやアプリケーションソフトウェアが全部処理してくれます。
ですから、「そういうむつかしいことは知らなくてもいいです」で済ましてしまってもよい、はずだったのですけれど…。
私だって、こんなややこしいことは、知らなくて済ませたい、ということで、無視してしまうつもりだったのですよ。
しかしながら、世の中、そうは思い通りにはいかないもので、どうしても、そこのところをパスしてしまうわけにはいかなくなってしまいました。

一番最初にPIC18F4550で、わかったような、わからないようなプログラムを書いて(実際ほとんどわかっていなかった)、パソコンに接続してみたところ、うんともすんとも言ってくれなかったために、そういう最も下層のレベルから検証していかざるをえなくなってしまったのです。
まあ、おかげで、しっかり勉強してしまいました(汗)。

フレームとパケットとトランザクションの関係を図に示すとこんな感じになります。



図の上側の帯がUSBケーブルの中を伝送される信号だと思ってください。
時間軸はオシロスコープなどと同じで左から右に進む方向です。
フレームというひとまとまりの信号単位はパソコンから1msごとにUSBケーブルに送られます。
フレームの先頭には、それを示すマークとしてSOFパケットが置かれます(Start Of Frameです)。

そのあと、主にINデータトランザクションやOUTデータトランザクションがUSBのなかを行ったり来たりします。
上のような図を見ると、概念としては、HOST→USB端末の方向のデータの流れしか思い浮かばないのですが、図は単にUSBケーブルの中を流れる信号の時間推移を表しているだけで(ちょうどオシロの信号のように)、信号の向きを示しているわけではありません。

トランザクションの種類にはデータ以外のものもあるのですが、今はそこまでは踏み込みません。
USBの中で扱われる送受信データは、232CのようにASCIIコードとは限りませんし、それぞれにスタートビットやストップビットがついているわけでもありません。
最大64バイトのデータが「裸で」送られます。

それはいくらなんでも無茶な話で、当然なんらかの「入れ物」が必要になります。
その入れ物に相当する論理的なまとまりがトランザクションとよばれるものです。
データトランザクションは図の下側に示したように、3つのパケット(信号の最小単位)で構成されます。

●トークンパケット

最初にトークンパケットというものがパソコン側から送られます。

パケットは、信号の同期をとるために、必ずSYNCという8ビットの信号から開始されます。
その次にそのパケットの種類を示すPID(Packet ID)という信号が送られます。
PIDは4ビットで、そのあとには必ずPIDの各ビットを反転した4ビットのPID_が続きます。
信号の誤りをチェックするためです。
PIDは4ビットなので、この部分で16種のパケットが識別されることになります。

トークンパケットはUSB端末に、これからデータを送出するぞ、ということを知らせたり(OUT)、またはUSB端末に、データを送れ、と要求したり(IN)するために、パソコンから送出されます。
トークンパケットにはそのほかの種類もありますが、今はそれには触れません。

参考までに。
SYNC信号は、80H(’10000000’)です。
OUTトークンパケットを示すPIDは、1H(’0001’)で、その後ろに、各ビットの0と1を反転した、EH(’1110’)が続きます。
INトークンパケットを示すPIDは、9H(’1001’)で、その後ろに、各ビットの0と1を反転した、6H(’0110’)が続きます。

トークンパケットでは、PID、PID_の次に、USB端末を特定するためのアドレス(7ビット)が送られます。

●アドレス

7ビットですから、USB装置は00〜7Fの128通りのアドレスで区別されます。
なのですが、そのうちのアドレス0だけは特殊な用途のためにリザーブされています。
実際に接続されるUSB装置には、アドレス1から順に番号が割り当てられて区別されます。
つまり理屈の上では最大127個のUSB装置が接続可能である、ということになります。
もちろん、電気的な負荷など物理的な制約がありますから、実際にそれだけのUSB装置が接続できるわけではありません。

で、トークンパケットのこのアドレス部分で識別されたUSB端末装置だけが、このトランザクションに応答することになります。

アドレスの次には、エンドポイント番号(4ビット)が続きます。

●パイプ(エンドポイント)

USBは1本のケーブルでパソコンとUSB装置とを接続していますが、その線を使ってデータを「多重」に伝送します。
USBでは何本ものケーブルで複数のUSB装置をパソコンに接続することができます。
パソコンのUSB接続ポートが足りない場合には、ハブを使って接続端末を増やすこともできます。

しかし、先ほどの図で説明したUSB信号の流れは、それぞれのUSBケーブルごとに別々にあるのではなくて、もとのパソコンのところでは、ただ1本の信号として存在しています。
その1本の信号経路の上に、最大127個のUSB機器が乗っかるということになりますから、これは相当の「多重」送受信が要求されることになります。

12MHz(12Mビット/秒)という転送速度の割には、1msというゆっくりとした間隔でフレームが発行されるのは、そのあたりに理由がありそうです。

最大127個のUSB装置が、パソコンのおおもとのところでは1本のUSB信号にまとめられてしまう、というだけでも相当の多重信号になるのですが、さらに、個々のUSB装置が1本の論理的な信号線を確保しているだけではなくて、それぞれのUSB装置が複数の「論理的」な信号線を持って、パソコンとデータの送受信を行うことができるのです。
そういうことになると、さきほどの7ビットのアドレスだけでは、個々の信号線を区別することはできません。

イメージとしては、たとえばRS232Cは送信(TX)と受信(RX)で別々のラインを使います(これで2ラインです)。
USB装置はそのような送信のラインと受信のラインを、複数本もって、パソコンと接続している、ようなものです。

RS232Cでしたら、接続線だらけになってしまいます。
もっともパソコンのRS232Cには、そんなにたくさんのチャンネルはありません。
スタンダードのデスクトップパソコンでも送信受信がペアのCOM1、COM2のせいぜい2ポートのみです。

USBはその送信と受信を1本のケーブルにのせてしまいます。
だけではなくて、送信、受信も1ラインだけではなくて、目的や必要に応じて、それぞれ複数のラインを定義して使うことができます。

当然この伝送ラインは物理的なものではなくて、物理的な1本のUSB信号ラインに対して、「仮想的」「論理的」な伝送信号ラインです。
1本の物理的なUSB信号の上に、多重に乗せられた、仮想的な伝送ラインがパイプです。

で、そのパイプにつけられた名前が「エンドポイント」です。
(注。この表現は「便宜的」です。厳密には、パイプとエンドポイントとは別ものです。そのことは下の説明を読んでいただければ理解していただけると思います。参考までに、次回[第425回]もお読みください)

ここのところはちょいとわかりにくいところなのですが、たとえば電話のようなものだと理解してください。
大きな会社では部署ごとに電話を置いて、いくつかの電話番号を持っています。
その電話番号に相当するものがエンドポイント(じつは内線番号)です。

電話番号は同じものは1つしかありませんが、たとえば内線番号は、会社ごとに同じ0〜XXを使います。
エンドポイントもそれと同じで、アドレスで識別されたUSB装置とパソコンとは複数の仮想的な伝送路であるパイプで接続されていることになります。

ちょうどHOST(パソコン)と127個のUSB端末とが1本の電話ケーブルでつながっていて、各USB端末はそれぞれ内部に複数の内線番号をもつことができる、というようにイメージするとわかりやすいと思います。

この電話は、端末からは、かけることができません。
パソコンからだけ、かけることができます。
パソコンからは必要に応じて、USB端末に対して電話がかけられます。
しかも、その電話は、7ビットの電話番号+4ビットの内線番号を使って、「ダイレクトイン」でかけられます。
この7ビットの電話番号がアドレスで、4ビットの内線番号がエンドポイント番号です。
HOST(パソコン)から7ビットのアドレス+4ビットのエンドポイント番号で「ダイレクトイン」に、USB端末と接続される「仮想的な」データ信号伝送路がパイプです。
ダイレクトインなのですけれど、7ビットのアドレスで、すでに特定のUSB機器とパソコンがつながっていますから、パイプの番号は「内線番号」だけでよいことになります。

説明がえらく長くなってしまいました。
さきほどのトークンパケットの説明に戻ります。
そういうことで、そのパイプの何番を使うぞ、とUSB端末に知らせるのが、このエンドポイント番号です。

エンドポイント番号は4ビットですから、0〜F(0〜15)になりますが、そのうちエンドポイント0は特殊な目的で使用されます。
また同じエンドポイント番号でも、それが、IN(パソコンからみて入力)に使われるものと、OUT(パソコンからみて出力)に使われるものは、別のパイプとして区別されて扱われます。

パケットの最後には、データビットの誤りを検出するためにCRCというデータビット列が置かれます。
しかしこの部分を使っての誤りチェックはファームウェアが行いますから、ユーザーレベルでは意識する必要はありません。

●データパケット

トークンパケットの次には、いよいよデータパケットが続きます。
トークンパケットが「OUTトークン」であった場合には、そのあとに続いてパソコンからデータパケットが出力されます。

もし、トークンパケットが「INトークン」だった場合には、ここでパソコンは指定したUSB端末からの出力を待ちます。
このとき「INトークン」パケットに続いてラインにあらわれるデータパケットは、外見からは前述のパソコンから出力されるデータパケットと全く変わりませんが、それとは信号の向きが逆で、USB端末からパソコンに向けて出力されるデータパケットです。

データパケットもデータ本体に先だってSYNC(80H)信号と、PID、PID_が送られます。
データパケットを示すPIDは2種類あって、DATA0が3H(’0011’)で、そのあとにCH(’1100’)が続きます。
もうひとつのデータパケットはDATA1で、PIDはBH(’1011’)で、そのあとに4H(’0100’)が続きます。
DATA0、DATA1については、のちほど、どこかで説明することになると思います。

そのあと最大64バイトのデータが続きますが、ここに64バイト以内の何バイトをのせるのかは、最初にそのUSB装置がパソコンに接続されたときに、パソコンに送られる情報(デスクリプタ)によって定義されます。

データ本体の最後にも、誤り検出のためのCRCビット列が置かれます。
これでデータパケットが完了します。

●ハンドシェイクパケット

これだけでデータの送受信は完了するように思われますが、データトランザクションは最後に、そのデータが相手方にちゃんと受け取られたかどうかを確認するための、ハンドシェイクパケットが、受信側から出力されて、はじめて完了します。

ハンドシェイクパケットにはACK(受信成功)とNAK(受信失敗)があります。
そのほかにもあるのですが、それについてはここでは触れません。

ハンドシェイクパケットはSYNC(80H)とPID、PID_だけで構成されます。
ACKを示すPIDは2H(’0010’)で、それに続いてDH(’1101’)が送られます。
NAKを示すPIDはAH(’1010’)で、続いて5H(’0101’)が送られます。

2010.1.28upload
2010.1.29加筆

前へ
次へ
ホームページトップへ戻る