HDL LOGO

FTDIドライバにおけるLatancyTimerについて

2012/07/19-
 
 このページは、FTDI社の、アプリケーションノート「AN-232B-04」の弊社なりの訳です。
訳に間違いがあるかもしれません。必ず原文をお確かめの上ご参考になさってください。

1. データスループットとハンドシェイキング

1.1 背景
 ユニバーサルシリアルバスはユーザ、開発者にとってま新しいかもしれません。
このアプリケーションノートでは、FT232R、FT2232C(UART mode) またはFT232BM USBシリアル変換器をつかって従来のRS232Cから切り替える際に、ソフトウェア・ハードウェアデザイナ双方が留意しないと行けない代表的なアーキテクチャの違いを解説します。
 多くの情報はFT245R, FT2232C(FIFO mode) FT245BMのパラレルFIFOインタフェースにも適応できます。

2. データ転送

2.1 ハンドシェイキングの必要性
 割り込みを使用してデータ転送を行ってきたシステムでは、通常現れなかった伝送遅延が、USB転送には起こりがちです。
オリジナルのCOMはマザーボードに直接接続されており、割り込みを使用していました。
 文字が送受信された際、(FIFOが使用されているかどうかによりますが)CPUはその割り込みを受けてデータの処理に取りかかります。これはユーザの意図したボーレート、データレートが特別なフローコントロール無しで実現出来ることを意味します。
 ハードウェア割り込みにより、リクエストは確実に処理されます。ですので、データはハンドシェイクを使わなくとも、データ欠損なくPCに届きます。
2.2 データ転送、比較
 USBはデータ転送に割り込みを使用しません。
転送のタイミングはシステムで管理されているので、ハンドシェイキングを使用しない場合、データが欠ける場合があります。スケジュールの遅れる例としては、使用しているアプリケーションをマウスでドラッグした場合などに発生します。

 USBデバイスにとって、データ転送はパケットに分けられます。
データがPCから送信されると、転送データはデバイスドライバにパケットに分割され、USBスケジューラに渡されます。このスケジューラがUSBホストコントローラのタスクリストにリクエストを送ります。
これらの作業は通常最低でも1ミリ秒かかります。なぜなら次のUSB Frameまでリクエストは処理されないからです(このUSB Frameの周期が1ミリ秒です)。ですので、アプリケーションからUSBデバイスへのデータの移動には大きなオーバーヘッドが付きます。(どれくらい大きいかはあなたの求めるスループットに依存します)
もし、アプリケーションから行われるデータ送信が1回に1データのみであるならば、全体のスループットを大きく制限することになります。
2.3 連続したデータ -しこりをならす-
 USBからPCへのデータ受信はポーリングで行われます。
ドライバはUSBスケジューラから受信済みのデータ量を通知されます。これは64byteの整数倍で通知されます。USB Bulk転送のサイズの最大は64bytesです。
ホストコントローラは以下の条件が満たされるまで、デバイスからデータを読みこみます
a)64byteより短いパケットデータを受信
b)通知されたデータ長に達する
 デバイスドライバは64byte〜4kbyteのパケットサイズを通知します。通知するパケットサイズはパフォーマンスやデータレートに影響します。
とても速いスピードとするには、最も大きいパケットサイズが必要です。
 リアルタイム(たとえば音声データを115200baudで転送)なアプリケーションでは最小のパケットサイズが良いでしょう。そうしないとデバイスが一度に4kまでデータを保持してしまいます。
 USBが要求するサイズが大きすぎると相対的にデータレートが落ち、ギクシャクした動作になります。

3. バッファとレイテンシタイマ

3.1 少量のデータとエンドバッファの状態
 FTDI USBシリアル/FIFO ICからPCにデータを送る場合、以下の条件で送信されます。
1. バッファが一杯であるとき (64Byteのうち、2バイトがステータス、このりがデータ)
2. USB-Serialの場合:RS232ステータス信号が変化したとき
  CTS#, DSR#, DCD#, RI#のレベルが変化したとき、バッファが空、64Byte未満関係なく
3. 設定されたイベントキャラクタがデータストリームに見つかったとき
4. チップ内蔵のタイマがタイムアウトしたとき
  タイマ(レイテンシタイマ)はFT232R、FT245R, FT2232C, FT232BM, FT245BMに搭載されており、最後のデータが送られてからの時間を計っています
レイテンシタイマのデフォルト値は16ミリ秒です。レイテンシタイマのリセット毎に、時間データがPCに送信されます。タイムアウトの際、2Byteのステータス情報と、その時点でバッファに入っていたデータを戻します。

 以上より、少量のデータ(もしくは大量データの最終データ)のPCへの転送は、16ミリのディレイ時間が支配的になります。
この遅れは、前章でふれた"USBへのリクエストサイズ"と一緒に考えなければなりません。
ハイスピードモードでも64byteのパケットが大きなバッファを満たせ、かつ1キャラクタを送信する場合にも不都合のないくらいとなる値が選ばれています。
 特定のキャラクタがシリアル/パラレルリンクを通じて受信されるのに16ミリ秒かかるであろう、という理由から16ミリ秒がデフォルト値に選ばれています。(◆)
 大量のデータを高速に転送する場合、レイテンシタイマは使用されないでしょう。最終データパケットの転送には使用されると思います。(64byte以下のデータであるなら)
 すべてのパケットのうち、最初の2byteはドライバへのステータスに使用されます。ステータスは、データの有無にかかわらず16ミリ秒ごとに必ずドライバに通知されます。

 最悪のケースは、62byteのデータがタイムアウトにより送信される場合です。
この場合タイムアウトは発生しませんが、64byte(2status+62 ユーザデータ)が16ミリ秒毎にUSBに返されます。USBDドライバは64byteを受け取ると、ホールド状態となりもう一つのINトランザクションを要求します
 これはもうひとつの16ミリ秒後に実行され、USBDが4k受信するまで繰り返します。(◆)
合計時間はアプリケーションからパケットが届くまでに(4096/64)*16ミリ秒=1.024秒になります。4kパケットで届くのをやめたいのなら、少量でのリクエストにすべきです。
 短いパケット(64byte以下)は、もちろんアプリケーションで使用するためUSBDからFTDIドライバに渡されます。(◆)
アプリケーションプログラマにとって、バッファを使って送受信すべきか、特殊文字を使うかは悩みの種となります
3.2 受信バッファのレイテンシタイマを調整する
 FTDIのR,C,BMシリーズのチップではレイテンシタイマの値をデフォルトの16ミリ秒から1〜255ミリ秒の任意の値に、1ミリ秒刻みで変更できます。
 FTDIの仮想COMポートドライバではポートプロパティにて変更できます。
WindowsではControl Panel→System→Device Managerからポートプロパティを開けます
Windows2000とXPでは、デフォルト値をftdiport.infに下記のようにして設定できます、16ミリ秒はデフォルト値です。
[FtdiPort.NT.HW.AddReg]
HKR,,"LatencyTimer",0x00010001,16
 FTDIのD2XXダイレクトドライバを使用する際はFT_SetLatencyTimer関数を使用できます
3.3 バッファサイズとレイテンシタイマがスループットに与える影響
 USBトータルパケットサイズがデータがスムーズな流れに影響するのかどうかは、すぐには明らかにはなりません。
USBにREADリクエストが送信されると、USBホストコントローラは64byteのパケットを以下の条件が満たされるまで読み続けます。
1. リクエストされたサイズを受け取る(デフォルト:4kbytes)
2.64byteより短いパケットをチップから受け取る
3.キャンセルされる
 ホストコントローラが、上記の条件の一つを待っている間、我々のドライバからデータは全く届きません。ゆえに、ユーザのアプリケーションからも受け取られません。
もしデータが少量である場合、最終的に上記いずれかの発生の際に転送されます。
 通常3項は起こりませんので、項1、2の場合を考えます。
もし64バイトのパケットが途切れることなくホストに送信される場合、ホストはドライバに要求されたブロックサイズ量に達するまでデータを読み続けます。(◆)
 もし少量のデータが送信、またはゆっくり送信された場合、レイテンシタイマがのタイムアウトにより1つのパケットがホストに送信され、READリクエストが終了します。
 読まれたデータはFTDIドライバを介してユーザアプリケーションに届きます。
これらがレイテンシタイマ、データレート、そしてユーザにデータが有効になるまでの関連です。
 レイテンシタイマのタイマアウトを無視するようなレートでデータがFTDIに渡される場合、データの受信と受信との間の時間が長くなる場合があります。
 これは起こりますmなぜならホストコントローラが64byteパケットをレイテンシ周期の最後の前に、そして読込を続ける、ブロックサイズに達するまでユーザアプリケーションに通知された。(◆)
 この場合のレートは"62 / Latency Timer bytes/Second"で与えられます
64byteのうち2byteはステータス用に使用されます
 デフォルト値の場合:62 / 0.016 ~= 3875 bytes /second ~= 38.75 KBaud
ですので、もしデータが3875byte/sec(38.75kBaud)、またはそれ以上の早さで受信される場合、データは USBブロック長のディレイが支配的になります
 もしデータが遅いレートで受信される場合、16ミリ秒後に受信できます
したがって、単体の短いパケットが発生し、故にUSBリクエストを終了しデータが戻ります
(USBブロックリクエストバッファサイズが4kであるとすると)38.75kBaudでバッファからユーザアプリケーションには1.06秒かかります
 これを解決するためにはレイテンシタイマ値を上げるか、USBブロックリクエストを減らします
両者でいうと、USBブロックリクエストを減らす方法の方が好まれます
3.4 USB送信サイズを調整する
 FTDI仮想COMポートドライバを使う場合、USB転送(バッファ)サイズはポートプロパティで設定できます
バッファの初期値ftdiport.int内の値に1を加え、64をかけることで算出できます
ですので0は64byteで、3Fは (63+1)*64 = 4096となります。
 INFファイルに二つのエントリがあります。1つめは送信バッファ、二つめは受信バッファです
[FtdiPort.NT.HW.AddReg]
HKR,,ConfigData,1,01,00,3F,3F,10,27,88,13,C4,09,E2,04,71,02,38,41,9c,80,4E,C0,34,00,1A,00,0D,00,06,40,03,80,00,00,00,00
上記の二つの3Fがエントリです。4k byteに設定されています、そして
[FtdiPort.NT.HW.AddReg]
HKR,,ConfigData,1,01,00,00,00,10,27,88,13,C4,09,E2,04,71,02,38,41,9c,80,4E,C0,34,00,1A,00,0D,00,06,40,03,80,00,00,00,00
これは64byteに設定した例です
FTDIのD2XXダイレクトドライバを使用する場合、FT_SetUSBParameters()関数がUSBブロックリクエストのサイズを調整できます。AN232Bが例です。

4. イベントとフローコントロール

4.1 イベントキャラクタ
 イベントキャラクタはFT232R, FT245R, FT2232C, FT232BM or FT245BMで使用できます。
 イベントキャラクタを有効にし、データストリーム内で検出された場合、デバイスバッファ内のデータは即時に送信されます
 イベントキャラクタはドライバによりデータストリームから削除されたりはしませんので、アプリケーション側で削除する必要があります
 イベントキャラクタは大量のランダムデータであろうと小さなコマンドシーケンスであろうと使用できます
 イベントキャラクタがバッファの最初のデータであった場合、機能しません。二番目以降のデータである必要があります
この理由、インターネットを使用するアプリケーション例ではイベントキャラクタ$7Eとします(◆)
 すべてのデータは最初と最後を$7Eで挟まれたパケットとして送受信されます。
 スループットを最大にするには$7Eで始まるパケットを避けます。先頭にくるイベントキャラクタはトリガになりません
4.2 モデムステータスラインを使って受信バッファをクリアする
 FT232R, FT2232C (UART mode) FT232BMデバイスで、チップ内のバッファクリアにフローコントロールが使用できます
モデムステータスラインのうち、一つを変化させるとクリアできます。
 モデムステータスラインは外部から制御されるか、またはPC自身が駆動します
未使用の出力(DTR)を未使用の入力(DSR)に接続されていた場合、もしDTRラインがアプリケーションによりハイからロー、もしくはローからハイに駆動されるとDSRが影響を受けバッファをクリアしてしまいます。
4.3 フローコントロール
 FT245R, FT2232C (in FIFO mode) FT245BMはハンドシェイキングをTXEラインを使用しています
 ハードウェアとしてRTS/CTS, DTR/DSR、ソフトウェアとしてXOn/XOffが使用できます。
 なんらかのハンドシェイキングを持つことを強く推奨します
 以下にFT232BMで使用できるフローコントロールを4つ示します
1. フローなし - 高速通信時にデータロスがおこるかもしれません
2. RTS/CTS - CTS入力がある場合に送信し、送信できない場合にRTSをおろします
3. DTR/DSR - DSR入力がある場合に送信し、受信できない場合にDTRをおろします
4. XON/XOFF - 特殊な文字を送受信することによりフローコントロールをおこないます。ひとつはXon(transmit on)もうひとつはXoff(transmit off)です
XON/XOFFには、どの文字にも割り当てることができます
 フローコントロールすることを強く推奨します。なぜなら、FTDIドライバがいつもスケジュール通りに動くのは不可能だからです
 チップは384バイトまでのデータをためることができます
Windowsがほかのことで忙しいと、ドライバは自分に時間が割かれることを懇願することになります
 わかりやすい例でいえばタスクバーをマウスでつかんで移動させることでしょう。
この行為は大量の再描画処理を発生させ、ハンドシェイキングなしで高速(たとえば115200)受信処理にデータ欠落を起こさせます
 もしデータレートが低く、データ欠損してよいのであればフローコントロールは必要ありません。
みなさまの参考になれば幸いです。
間違いなど見つけられましたらぜひご指摘下さい。
ひとことコメント 
メールでのご質問はこちらへどうぞ
FTDIシリーズトップへ
 USBシリーズ専用サイトへ