SerCx2 で管理されるシリアル ポートからデータを読み取る

通常、シリアル コントローラー (UART) には受信 FIFO が含まれています。 この FIFO は、シリアル ポートに接続されている周辺デバイスから受信したデータのハードウェア制御によるバッファリングを提供します。 受信 FIFO からデータを読み取るために、このデバイスのペリフェラル ドライバーは読み取り (IRP_MJ_READ) リクエストをシリアル ポートに送信します。

シリアル ポートがペリフェラル ドライバーがデータを読み取るよりも速くデータを受信し続けると、受信 FIFO がオーバーフローする可能性があります。 オーバーフローによるデータ損失を防ぐために、周辺機器ドライバーは通常、ハードウェア フロー制御を使用するようにシリアル ポートを構成する必要があります。 フロー制御を使用すると、受信 FIFO がほぼいっぱいになると、シリアル コントローラー ハードウェアが周辺デバイスにデータ送信を停止するよう自動的に信号を送ります。 原則として、SerCx2 によって管理されるシリアル ポートはハードウェア フロー制御を使用する必要があります。 詳細については、フロー制御の詳細をご覧ください。

ただし、フロー制御を使用して周辺デバイスのデータ送信を長時間停止しないでください。停止すると、デバイスが正常に動作しなくなる可能性があります。 たとえば、周辺デバイスには内部データ バッファがあり、デバイスがこのバッファからシリアル ポートにデータを送信できない状態が長時間続くと、オーバーフローする可能性があります。

このページの内容

非同期読み取りリクエストの使用

誤った動作やデータ損失の可能性を回避するために、ペリフェラル ドライバーはシリアル コントローラーの受信 FIFO からデータを適時に読み取る責任があります。 通常、周辺機器ドライバーは、データを受信する前に、周辺機器から将来のデータの到着を予期して、非同期読み取り要求をシリアル ポートに送信します。 この読み取り要求は、受信 FIFO からデータを読み取ることができるようになるまで、SerCx2 I/O キュー内で保留されたままになります。

ほとんどのハードウェア プラットフォームでは、周辺機器ドライバーが一度に複数のそのような読み取り要求を保留する必要はありません。 まれに、データを受信した後、読み込み要求が完了するまでに処理に時間がかかり、その結果データのバックアップによって周辺デバイスがデータを失うか、そうでなければ動作がおかしくなる場合、ドライバは未処理の読み込み要求を1つ以上持つ必要があるかもしれません。

周辺機器ドライバーが一度にそのような読み取り要求を 1 つだけ保留していると仮定すると、この要求で必要なデータ バッファーのサイズは、周辺機器の既知の動作に大きく依存します。 たとえば、ドライバーがデバイスからのデータのバイト数を事前に知っている場合、ドライバーはリクエストのバッファ サイズをこのバイト数に設定します。 読み取りリクエストは、バッファが受信 FIFO からのデータで満たされるとすぐに完了します。 これに応じて、ドライバーは新しい読み取りリクエストを非同期に送信して、次のデータ ブロックを待ちます。

ただし、周辺機器ドライバーは、周辺機器からどの程度のデータが予想されるかを事前に知らない場合があります。 この場合、ドライバーは読み取りリクエストのデータ バッファーを適切なサイズに設定し、インターバル タイムアウトを利用して周辺デバイスからのデータの終わりを識別します。 読み取りバッファに適切なサイズを選択するには、周辺機器の動作方法に関する詳細な知識が必要になる場合があります。 読み取りバッファーが小さすぎる場合、ドライバーはデータの読み取りを完了するために 1 つ以上の追加の読み取り要求を送信する必要があります。

インターバルタイムアウトの詳細

読み取りおよび書き込みリクエストのタイムアウト パラメーターを設定するには、周辺機器ドライバーは IOCTL_SERIAL_SET_TIMEOUTS リクエストをシリアル ポートに送信できます。 読み取りのタイムアウトは、このリクエストの ReadIntervalTimeoutReadTotalTimeoutMultiplier、および ReadTotalTimeoutConstant パラメーター値によって制御されます。 ReadIntervalTimeout は、受信トランザクション内の連続する 2 バイト間に許可される最大時間間隔を指定します。 ReadTotalTimeoutMultiplierReadTotalTimeoutConstant が両方とも ゼロで、読み取りリクエストがシリアル ポートに送信されたときにシリアル コントローラーの受信 FIFO が空の場合、このリクエストはタイムアウトせず (保留状態のままになります)ポートが少なくとも 1 バイトの新しいデータを受信するまで、SerCx2 I/O キューに保持されます。 詳細については、SERIAL_TIMEOUTSをご覧ください。

システム オン チップ (SoC) 集積回路上のシリアル ポートは、数メガビット/秒以上のピーク レートで周辺デバイスからデータを受信できる場合があります。 このデバイスの周辺機器ドライバーの開発者は、インターバル タイムアウト値 (ReadIntervalTimeout パラメーターで指定) をミリ秒以下に設定したいと思うかもしれませんが、この値が望ましい効果をもたらす可能性は低いです。 これは、間隔タイムアウトの検出に使用されるタイマーの精度がシステム クロックの粒度によって制限されるためです。

たとえば、システム クロック周期が 15 ミリ秒で、ドライバーが ReadIntervalTimeout 値を 1 ミリ秒に設定した場合、0 ミリ秒から 15 ミリ秒強の範囲のバイト間間隔によってトリガーされる可能性があります。タイムアウト。この設定により、周辺機器からのデータ送信中にタイムアウトが発生する場合があります。 この送信が終了した後にのみタイムアウトが発生するように、ドライバは ReadIntervalTimeout を 15 ミリ秒よりいくらか大きい値に設定することができます。 たとえば、ReadIntervalTimeout が 20 ミリ秒に設定されている場合、バイト間の間隔が 30 ミリ秒の場合はタイムアウトが確実にトリガーされ、15 ミリ秒以下の間隔ではタイムアウトはトリガーされません。

タイマーの精度がシステム クロックにどのように依存するかについての詳細は、タイマーの精度をご覧ください。

フロー制御の詳細

ベスト プラクティスとして、SerCx2 管理のシリアル ポートを使用する周辺機器ドライバーは、受信 FIFO のオーバーフローを防ぐためにハードウェア フロー制御を使用するようにこれらのポートを構成する必要があります。 保留中の読み取り要求がない場合、SerCx2 は、受信 FIFO の容量を超える受信データのソフトウェア バッファリングを提供しません。 この FIFO がオーバーフローすると、データが失われます。

ハードウェア フロー制御を有効にするために、周辺機器ドライバーは IOCTL_SERIAL_SET_HANDFLOW リクエストを送信して、シリアル ポートのハンドシェイクおよびフロー制御設定を行う場合があります。 または、ドライバーは IOCTL_SERIAL_APPLY_DEFAULT_CONFIGURATION リクエストを送信して、ハードウェア フロー制御を含む一連のデフォルトのハードウェア設定を使用するようにシリアル ポートを構成する場合があります。 IOCTL_SERIAL_SET_HANDFLOW リクエストは、SERIAL_HANDFLOW 構造体を使用してフロー制御設定を記述します。 IOCTL_SERIAL_APPLY_DEFAULT_CONFIGURATION リクエストには、ベンダー指定のデータ形式で同様の情報が含まれる場合があります。

周辺機器ドライバーが IOCTL_SERIAL_SET_HANDFLOW リクエストを使用してハードウェア フロー制御を有効にする場合、ドライバーはこのリクエストの SERIAL_HANDFLOW 構造体に次のフラグを設定する必要があります。

  • 構造体の ControlHandShake メンバーの SERIAL_CTS_HANDSHAKE フラグ。 このフラグにより、シリアル ポートが受信操作にフロー制御を使用できるようになります。
  • FlowReplace メンバーの SERIAL_RTS_CONTROL フラグと SERIAL_RTS_HANDSHAKE フラグ。 これらのフラグにより、シリアル ポートが送信操作にフロー制御を使用できるようになります。