Compartir a través de


Leer datos de un puerto serie de SerCx2-Managed

Un controlador serie (o UART) normalmente incluye un FIFO de recepción. Este FIFO proporciona almacenamiento en búfer controlado por hardware de los datos recibidos del dispositivo periférico que está conectado al puerto serie. Para leer datos del FIFO de recepción, el controlador periférico de este dispositivo envía solicitudes de lectura (IRP_MJ_READ) al puerto serie.

Si el puerto serie sigue recibiendo datos más rápido que el controlador periférico puede leer los datos, el FIFO de recepción puede desbordarse. Para evitar la pérdida de datos debido al desbordamiento, el controlador periférico normalmente debe configurar el puerto serie para usar el control de flujo de hardware. Con el control de flujo, el hardware del controlador serie indica automáticamente al dispositivo periférico que deje de enviar datos cuando el FIFO de recepción esté casi lleno. Como regla, los puertos serie administrados por SerCx2 deben usar el control de flujo de hardware. Para obtener más información, consulte Detalles del control de flujo.

Sin embargo, el control de flujo no se debe usar para impedir que el dispositivo periférico envíe datos durante demasiado tiempo o que el dispositivo no siga funcionando correctamente. Por ejemplo, el dispositivo periférico podría tener un búfer de datos interno que pueda desbordarse si el dispositivo se impide durante demasiado tiempo enviar datos de este búfer al puerto serie.

En esta página

Uso de solicitudes de lectura asincrónicas

Para evitar la operación incorrecta y la posible pérdida de datos, el controlador periférico es responsable de leer los datos de la recepción de FIFO del controlador serie de forma oportuna. Normalmente, antes de recibir datos, el controlador periférico envía una solicitud de lectura asincrónica al puerto serie en previsión de la futura llegada de datos desde el dispositivo periférico. Esta solicitud de lectura permanece pendiente en la cola de E/S de SerCx2 hasta que los datos estén disponibles para leerse desde el FIFO de recepción.

En la mayoría de las plataformas de hardware, un controlador periférico no necesita tener más de una solicitud de lectura pendiente a la vez. En raras ocasiones, es posible que un controlador necesite tener más de una solicitud de lectura pendiente si, una vez recibidos los datos, una solicitud de lectura tarda tanto tiempo en procesarse antes de que se pueda completar que la copia de seguridad de datos resultante hace que el dispositivo periférico pierda datos o, de lo contrario, se comporte incorrectamente.

Suponiendo que el controlador periférico solo tiene una solicitud de lectura pendiente a la vez, el tamaño necesario del búfer de datos de esta solicitud depende en gran medida del comportamiento conocido del dispositivo periférico. Por ejemplo, si el controlador sabe con antelación cuántos bytes de datos esperar del dispositivo, el controlador establece el tamaño del búfer en la solicitud en este número de bytes. La solicitud de lectura se completa en cuanto el búfer se rellena con datos del FIFO de recepción. En respuesta, el controlador puede enviar de forma asincrónica una nueva solicitud de lectura para esperar al siguiente bloque de datos.

Sin embargo, es posible que el controlador periférico no sepa con antelación cuántas datos esperar del dispositivo periférico. En este caso, el controlador establece el búfer de datos en la solicitud de lectura en un tamaño adecuado y, a continuación, se basa en un tiempo de espera de intervalo para identificar el final de los datos del dispositivo periférico. Elegir un tamaño adecuado para el búfer de lectura puede requerir conocimientos detallados sobre cómo funciona el dispositivo periférico. Si el búfer de lectura es demasiado pequeño, el controlador tendrá que enviar una o varias solicitudes de lectura adicionales para terminar de leer los datos.

Detalles del tiempo de espera de intervalo

Para establecer los parámetros de tiempo de espera para las solicitudes de lectura y escritura, un controlador periférico puede enviar una solicitud de IOCTL_SERIAL_SET_TIMEOUTS al puerto serie. Los tiempos de espera de las lecturas se controlan mediante los valores de parámetro ReadIntervalTimeout, ReadTotalTimeoutMultiplier y ReadTotalTimeoutConstant en esta solicitud. ReadIntervalTimeout especifica el intervalo de tiempo máximo permitido entre dos bytes consecutivos en una transacción de recepción. Si ReadTotalTimeoutMultiplier y ReadTotalTimeoutConstant son cero y el fiFO de recepción del controlador serie está vacío cuando se envía una solicitud de lectura al puerto serie, esta solicitud no agota el tiempo de espera (y así permanece pendiente en la cola de E/S de SerCx2) hasta después de que el puerto reciba al menos un byte de datos nuevos. Para obtener más información, consulte SERIAL_TIMEOUTS.

Un puerto serie en un sistema en un circuito integrado de chip (SoC) podría ser capaz de recibir datos de un dispositivo periférico a velocidades máximas de varios megabits por segundo o superior. Es posible que el desarrollador del controlador periférico de este dispositivo tenga la tentación de establecer el valor de tiempo de espera de intervalo (según lo especificado por el parámetro ReadIntervalTimeout ) en un milisegundo o menos, pero es poco probable que este valor tenga el efecto deseado. Esto se debe a que la precisión del temporizador que se usa para detectar tiempos de espera de intervalo está limitada por la granularidad del reloj del sistema.

Por ejemplo, si el período de reloj del sistema es de 15 milisegundos y el controlador establece el valor ReadIntervalTimeout en 1 milisegundos, un intervalo de bytes a byte en cualquier parte del intervalo de 0 a un poco más de 15 milisegundos podría desencadenar un tiempo de espera. En ocasiones, esta configuración puede provocar que se agote el tiempo de espera en medio de una transmisión de datos desde el dispositivo periférico. Para asegurarse de que un tiempo de espera solo puede producirse una vez finalizada esta transmisión, el controlador puede establecer ReadIntervalTimeout en un valor algo mayor que 15 milisegundos. Por ejemplo, si ReadIntervalTimeout se establece en 20 milisegundos, un intervalo de bytes de 30 milisegundos desencadena de forma confiable un tiempo de espera y un intervalo de 15 milisegundos o menos no desencadena un tiempo de espera.

Para obtener más información sobre cómo depende la precisión del temporizador en el reloj del sistema, consulte Precisión del temporizador.

Detalles del control de flujo

Como procedimiento recomendado, los controladores periféricos que usan puertos serie administrados por SerCx2 deben configurar estos puertos para usar el control de flujo de hardware para evitar que el FIFO de recepción se desborde. En ausencia de una solicitud de lectura pendiente, SerCx2 no proporciona ningún almacenamiento en búfer de software de los datos de recepción que supere la capacidad del FIFO de recepción. Si este FIFO puede desbordarse, se pierden los datos.

Para habilitar el control de flujo de hardware, un controlador periférico puede enviar una solicitud de IOCTL_SERIAL_SET_HANDFLOW para establecer la configuración del protocolo de enlace y el control de flujo para el puerto serie. O bien, el controlador puede enviar una solicitud de IOCTL_SERIAL_APPLY_DEFAULT_CONFIGURATION para configurar el puerto serie para usar un conjunto de opciones de hardware predeterminadas que incluyan el control de flujo de hardware. La solicitud IOCTL_SERIAL_SET_HANDFLOW usa la estructura SERIAL_HANDFLOW para describir la configuración del control de flujo. Una solicitud de IOCTL_SERIAL_APPLY_DEFAULT_CONFIGURATION puede contener información similar en un formato de datos especificado por el proveedor.

Si el controlador periférico usa una solicitud de IOCTL_SERIAL_SET_HANDFLOW para habilitar el control de flujo de hardware, el controlador debe establecer las marcas siguientes en la estructura SERIAL_HANDFLOW de esta solicitud:

  • Marca SERIAL_CTS_HANDSHAKE en el miembro ControlHandShake de la estructura. Esta marca permite que el puerto serie use el control de flujo para las operaciones de recepción.
  • Marcas SERIAL_RTS_CONTROL y SERIAL_RTS_HANDSHAKE en el miembro FlowReplace . Estas marcas permiten que el puerto serie use el control de flujo para las operaciones de transmisión.