さて、パケットの最後は(ITP)Isochronous Timestamp Packetである。ITPはHostより現在Activeな全てのDeviceに対して、Timestampの伝達を行うために利用される。要するに、個々のDeviceとHostで時間の同期をとるためのものである。Activeな全てのDeviceに対して、しかもなるべく時間差が無い様に伝達しないといけないこともあり、伝達にはMulticastが利用される。つまり途中にHubが介在する場合、全てのHubは自分の配下にあるActiveなDownstream Portに対して一斉に、受け取ったITPを送出する事が求められている。またMulticastだから当然Address Routingなどは行われない。またMulticastなので、DeviceはITPに対するResponceをHostに返す必要もない。

ITPの送出は当然ながらHostのみが実施できる。HostはtTimestampWindow(Specificationによれば、この値はMin:0、Max:8μsとなっている)の期間毎に一回づつ、ITPの送出を行わねばならない。このITP送出は、HostのRoot portがポーリング状態からU0になった、もしくはU3からU0に遷移した後にtTimestampStart(こちらはMax:250μsのみが規定されている)の期間以内に開始しなければならない。ITPはまた、他のPacketのBurst Transferの合間に送ることも可能となっている。

ITPの構造はPhoto01に示す通りである。ここで一番大きいのがTypeの5bitに続く27bitのIST(Isochronous Timestamp)である。このフィールドは前半14bitのBus interval counterと後半13bitのdeltaに分かれている。Bus interval counterは1/8msec(125μsec)のカウンタで、125μsec毎にインクリメントしてゆき、0x3FFFになったら再び0にロールオーバーするだけのカウンタである。続く13bitのDeltaが、Bus interval boundaryからの時間差となる。こちらは単位がtIsochTimestampGranularity単位(16.67ns)と規定されており、この倍数が入る形だ。ちなみにこのtIsochTimestampGranularity、Specificationでは8 USB2.0 High-Speed bit timeと規定されており、ここから16.67nsと算出できる。

Photo01: TypeにはITPが入る。Routingが必要ないので、Device Addressなどのフィールドは設けられていない。

続くBus Interval Adjustment Controlは、bus interval adjustmentの対象となるDeviceのアドレスが入る。初期化直後、あるいはdeviceがDisconnectになった場合、ここはゼロクリアされる。

このITPがどういうシーンで使われるかというと、Isochronous TransferでBus Intervalを明確にするためのboundaryとして働く事になるが、このあたりを説明するにはまずIsochronous Transferの説明から入らねばならないので、これはちょっと後回しにさせていただき、もう少し具体的なTransactionの説明から先に始めたいと思う。ということでLMPはまぁ別として、TP/DP/ITPの各パケットを使い、実際にTransactionがどのように行われるか、をちょっと俯瞰してみたい。

Photo02は単純な、Single PacketのOUT Transactionである。USB 3.0はUSB 1.1/2.0までと同様、全てのTransactionは必ずHostからスタートすることになる。なので、単純にDPPを一つDeviceに送り出すだけであれば、Transactionはごく簡単である。ここで、HostからのDPPの送出と、DeviceからのLGOOD_0/LCRD_Aの送出がオーバーラップしている(というか、オーバーラップできる)のがUSB 3.0の特徴である。これにより若干ながらハンドシェイクのオーバーヘッドを削減できることになる。

Photo02: HostはまずSeq#=0でDPHを送出後、DPPを送り出す。DeviceはDPPの受信と並行してDGOOD_0とLCRD_Aを送出、ACK TPをSeq#=1/NumP=1として送り返す。これを受けてHost側がLGOOD_2とLCRD_Bを送り返し、トランザクション完了である。

逆にSingle PacketのIN Transactionはどうなるか? というのがPhoto03だ。こちらもHostからスタートで、まず開始される予定のSequence Numberを持つACK TPをDeviceに送り出す。このACK TPを受けてDeviceは自身の持つデータをDPPに乗せて送り出すという仕組みだ。こちらでもLGOOD_2やLCRD_Bがオーバーラップしていることで、若干のオーバーヘッド削減となっている。ACKが転送の前に出てくるあたりがちょっと普通と異なる(ACKは本来転送後に送るもの)だが、では転送要求パケットを別に定義するとオーバーヘッドが増えることになってしまうし、(これはOUT Transactionにも言えるが)DPPの正当性は続くTPで判断できるから構わないという判断なのだろう。

Photo03: まずHostがACK TPをSeq=0/NumP=0として送り出す。DeviceはこのACK TPに対するLGOOD_0/LCRD_Aを送出後、DPH(Seq#=0)とDPPを相次いで送り出す。一方HostはDPHの受信後にLGOOD_2とLCRD_Bを送出する形だ。問題なければ、次のACK TPを送り出すことで、Seq#=0のTransactionは完了である。

(続く)