Lesen von Daten von einem SerCx2-Managed seriellen Port
Ein serieller Controller (oder UART) enthält in der Regel eine Empfangs-FIFO. Dieser FIFO bietet eine hardwaregesteuerte Pufferung von Daten, die von dem Peripheriegerät empfangen werden, das mit dem seriellen Port verbunden ist. Zum Lesen von Daten aus dem empfangenen FIFO sendet der Peripherietreiber für dieses Gerät Leseanforderungen (IRP_MJ_READ) an den seriellen Port.
Wenn der serielle Port weiterhin Daten schneller empfängt, als der Peripherietreiber die Daten lesen kann, kann der Empfangs-FIFO überlaufen. Um Datenverluste aufgrund von Überlauf zu vermeiden, sollte der Peripherietreiber den seriellen Port in der Regel für die Verwendung der Hardwareflusssteuerung konfigurieren. Bei der Flusssteuerung signalisiert die serielle Controllerhardware dem Peripheriegerät automatisch, dass das Senden von Daten beendet wird, wenn das Empfangs-FIFO nahezu voll ist. In der Regel sollten serielle Ports, die von SerCx2 verwaltet werden, die Hardwareflusssteuerung verwenden. Weitere Informationen finden Sie unter Details zur Ablaufsteuerung.
Die Flusssteuerung sollte jedoch nicht verwendet werden, um zu lange zu verhindern, dass das Peripheriegerät Daten sendet. Andernfalls funktioniert das Gerät möglicherweise nicht mehr ordnungsgemäß. Beispielsweise kann das Peripheriegerät über einen internen Datenpuffer verfügen, der überlaufen kann, wenn das Gerät zu lange daran gehindert ist, Daten aus diesem Puffer an den seriellen Port zu senden.
Auf dieser Seite
- Verwenden von asynchronen Leseanforderungen
- Details zum Intervalltimeout
- Details zur Ablaufsteuerung
Verwenden von asynchronen Leseanforderungen
Um fehlerhaften Betrieb und möglichen Datenverlust zu vermeiden, ist der Peripherietreiber dafür verantwortlich, die Daten aus dem Empfangs-FIFO des seriellen Controllers rechtzeitig zu lesen. In der Regel sendet der Peripherietreiber vor dem Empfang von Daten eine asynchrone Leseanforderung an den seriellen Port in Erwartung der zukünftigen Ankunft von Daten vom Peripheriegerät. Diese Leseanforderung bleibt in der SerCx2-E/A-Warteschlange ausstehend, bis Daten aus dem Empfangens-FIFO gelesen werden können.
Auf den meisten Hardwareplattformen muss ein Peripherietreiber nicht mehr als eine solche Leseanforderung gleichzeitig ausstehen. In seltenen Fällen benötigt ein Treiber möglicherweise mehr als eine ausstehende Leseanforderung, wenn die Verarbeitung einer Leseanforderung nach dem Empfang der Daten so lange dauert, bevor sie abgeschlossen werden kann, dass die resultierende Datensicherung dazu führt, dass das Peripheriegerät Daten verliert oder sich anderweitig falsch verhält.
Wenn der Peripherietreiber jeweils nur eine solche Leseanforderung aussteht, hängt die erforderliche Größe des Datenpuffers in dieser Anforderung weitgehend vom bekannten Verhalten des Peripheriegeräts ab. Wenn der Treiber beispielsweise im Voraus weiß, wie viele Bytes daten vom Gerät erwartet werden, legt der Treiber die Puffergröße in der Anforderung auf diese Anzahl von Bytes fest. Die Leseanforderung wird abgeschlossen, sobald der Puffer mit Daten aus dem Empfangs-FIFO gefüllt ist. Als Antwort kann der Treiber asynchron eine neue Leseanforderung senden, um auf den nächsten Datenblock zu warten.
Der Peripherietreiber weiß jedoch möglicherweise nicht im Voraus, wie viele Daten vom Peripheriegerät zu erwarten sind. In diesem Fall legt der Treiber den Datenpuffer in der Leseanforderung auf eine geeignete Größe fest und verwendet dann ein Intervalltimeout, um das Ende der Daten vom Peripheriegerät zu identifizieren. Die Auswahl einer geeigneten Größe für den Lesepuffer erfordert möglicherweise detaillierte Kenntnisse über die Funktionsweise des Peripheriegeräts. Wenn der Lesepuffer zu klein ist, muss der Treiber eine oder mehrere zusätzliche Leseanforderungen senden, um das Lesen der Daten abzuschließen.
Details zum Intervalltimeout
Um die Timeoutparameter für Lese- und Schreibanforderungen festzulegen, kann ein Peripherietreiber eine IOCTL_SERIAL_SET_TIMEOUTS-Anforderung an den seriellen Port senden. Timeouts für Lesevorgänge werden durch die Parameterwerte ReadIntervalTimeout, ReadTotalTimeoutMultiplier und ReadTotalTimeoutConstant in dieser Anforderung gesteuert. ReadIntervalTimeout gibt das maximal zulässige Zeitintervall zwischen zwei aufeinanderfolgenden Bytes in einer Empfangstransaktion an. Wenn ReadTotalTimeoutMultiplier und ReadTotalTimeoutConstant beide null sind und die Empfangs-FIFO des seriellen Controllers leer ist, wenn eine Leseanforderung an den seriellen Port gesendet wird, tritt für diese Anforderung kein Timeout auf (und bleibt daher in der SerCx2-E/A-Warteschlange ausstehend), bis der Port mindestens ein Byte neuer Daten empfängt. Weitere Informationen finden Sie unter SERIAL_TIMEOUTS.
Ein serieller Port an einer integrierten SoC-Schaltung (System on a Chip) kann Daten von einem Peripheriegerät mit Spitzenraten von mehreren Megabit pro Sekunde oder mehr empfangen. Der Entwickler des Peripherietreibers für dieses Gerät ist möglicherweise versucht, den Intervalltimeoutwert (wie durch den ReadIntervalTimeout-Parameter angegeben) auf eine Millisekunde oder weniger festzulegen, aber dieser Wert wird wahrscheinlich nicht die gewünschte Wirkung haben. Das liegt daran, dass die Genauigkeit des Timers, der zum Erkennen von Intervalltimeouts verwendet wird, durch die Granularität der Systemuhr begrenzt wird.
Wenn der Systemuhrzeitraum beispielsweise 15 Millisekunden beträgt und der Treiber den Wert ReadIntervalTimeout auf 1 Millisekunde festlegt, kann ein Byte-zu-Byte-Intervall im Bereich von 0 bis etwas mehr als 15 Millisekunden ein Timeout auslösen. Gelegentlich kann diese Einstellung zu einem Timeout während einer Datenübertragung vom Peripheriegerät führen. Um sicherzustellen, dass ein Timeout erst nach Abschluss dieser Übertragung auftreten kann, kann der Treiber ReadIntervalTimeout auf einen Wert von etwas mehr als 15 Millisekunden festlegen. Wenn ReadIntervalTimeout beispielsweise auf 20 Millisekunden festgelegt ist, löst ein Byte-zu-Byte-Intervall von 30 Millisekunden zuverlässig ein Timeout aus, und ein Intervall von 15 Millisekunden oder weniger löst kein Timeout aus.
Weitere Informationen dazu, wie die Timergenauigkeit von der Systemuhr abhängt, finden Sie unter Timergenauigkeit.
Details zur Ablaufsteuerung
Als bewährte Methode sollten Peripherietreiber, die von SerCx2 verwaltete serielle Ports verwenden, diese Ports so konfigurieren, dass die Hardwareflusssteuerung verwendet wird, um zu verhindern, dass die Empfangs-FIFO überläuft. In Ermangelung einer ausstehenden Leseanforderung bietet SerCx2 keine Softwarepufferung von Empfangsdaten, die die Kapazität des Empfangs-FIFO überschreitet. Wenn dieser FIFO überlaufen darf, gehen Daten verloren.
Um die Steuerung des Hardwareflusses zu aktivieren, sendet ein Peripherietreiber möglicherweise eine IOCTL_SERIAL_SET_HANDFLOW Anforderung zum Festlegen der Handshake- und Flusssteuerungseinstellungen für den seriellen Port. Oder der Treiber sendet möglicherweise eine IOCTL_SERIAL_APPLY_DEFAULT_CONFIGURATION Anforderung, um den seriellen Port so zu konfigurieren, dass er eine Reihe von Standardhardwareeinstellungen verwendet, die die Hardwareflusssteuerung enthalten. Die IOCTL_SERIAL_SET_HANDFLOW-Anforderung verwendet die SERIAL_HANDFLOW-Struktur , um die Einstellungen für die Flusssteuerung zu beschreiben. Eine IOCTL_SERIAL_APPLY_DEFAULT_CONFIGURATION-Anforderung kann ähnliche Informationen in einem vom Anbieter angegebenen Datenformat enthalten.
Wenn der Peripherietreiber eine IOCTL_SERIAL_SET_HANDFLOW-Anforderung verwendet, um die Steuerung des Hardwareflusses zu aktivieren, sollte der Treiber in dieser Anforderung die folgenden Flags in der SERIAL_HANDFLOW-Struktur festlegen:
- Das SERIAL_CTS_HANDSHAKE Flag im ControlHandShake-Element der -Struktur. Dieses Flag ermöglicht es dem seriellen Port, die Flusssteuerung für Empfangsvorgänge zu verwenden.
- Die flags SERIAL_RTS_CONTROL und SERIAL_RTS_HANDSHAKE im FlowReplace-Element . Diese Flags ermöglichen es dem seriellen Port, die Flusssteuerung für Übertragungsvorgänge zu verwenden.