Поделиться через


Чтение данных из последовательного порта SerCx2-Managed

Последовательный контроллер (или UART) обычно включает прием fifo. Этот FIFO обеспечивает аппаратно-управляемую буферизацию данных, полученных с периферийного устройства, подключенного к последовательному порту. Чтобы считывать данные из получения FIFO, периферийный драйвер для этого устройства отправляет запросы на чтение (IRP_MJ_READ) на последовательный порт.

Если последовательный порт продолжает получать данные быстрее, чем периферийный драйвер может считывать данные, функция FIFO приема может переполнится. Чтобы предотвратить потерю данных из-за переполнения, драйвер периферийных устройств обычно должен настроить последовательный порт для использования управления потоком оборудования. При управлении потоком оборудование последовательного контроллера автоматически сообщает периферийным устройствам о прекращении отправки данных, когда получение FIFO почти заполнено. Как правило, последовательные порты, управляемые SerCx2, должны использовать аппаратное управление потоком. Дополнительные сведения см. в разделе Сведения об управлении потоком.

Однако управление потоком не следует использовать, чтобы запретить периферийное устройство отправлять данные слишком долго, иначе устройство может продолжать работать неправильно. Например, периферийное устройство может иметь внутренний буфер данных, который может переполнение, если устройство слишком долго не может отправлять данные из этого буфера в последовательный порт.

На этой странице

Использование асинхронных запросов на чтение

Чтобы избежать неправильной работы и возможной потери данных, периферийный драйвер отвечает за своевременное чтение данных из последовательного контроллера, получая FIFO. Как правило, перед получением данных периферийный драйвер отправляет асинхронный запрос на чтение на последовательный порт в ожидании будущего поступления данных с периферийного устройства. Этот запрос на чтение остается незавершенным в очереди ввода-вывода SerCx2 до тех пор, пока данные не будут доступны для чтения из получающего FIFO.

На большинстве аппаратных платформ для драйвера периферийных устройств не требуется одновременное ожидание нескольких таких запросов на чтение. В редких случаях драйверу может потребоваться несколько невыполненных запросов на чтение, если после получения данных обработка запроса на чтение занимает так много времени, прежде чем его можно будет завершить, что результирующая резервная копия данных приводит к потере данных на периферийном устройстве или к неправильному поведении.

Если драйвер периферийных устройств имеет только один такой запрос на чтение в данный момент времени, требуемый размер буфера данных в этом запросе в значительной степени зависит от известного поведения периферийного устройства. Например, если драйвер заранее знает, сколько байтов данных следует ожидать от устройства, драйвер устанавливает размер буфера в запросе на это количество байтов. Запрос на чтение выполняется сразу после заполнения буфера данными из получаемого FIFO. В ответ драйвер может асинхронно отправить новый запрос на чтение, чтобы дождаться следующего блока данных.

Однако драйвер периферийного устройства может не знать заранее, сколько данных следует ожидать от периферийного устройства. В этом случае драйвер задает буфер данных в запросе на чтение соответствующего размера, а затем использует интервал времени ожидания, чтобы определить конец данных с периферийного устройства. Выбор подходящего размера для буфера чтения может потребовать подробных знаний о работе периферийного устройства. Если буфер чтения слишком мал, драйверу придется отправить один или несколько дополнительных запросов на чтение, чтобы завершить чтение данных.

Сведения о времени ожидания интервала

Чтобы задать параметры времени ожидания для запросов на чтение и запись, периферийный драйвер может отправить запрос IOCTL_SERIAL_SET_TIMEOUTS на последовательный порт. Время ожидания для операций чтения определяется значениями параметров ReadIntervalTimeout, ReadTotalTimeoutMultiplier и ReadTotalTimeoutConstant в этом запросе. ReadIntervalTimeout задает максимальный интервал времени, допустимый между двумя последовательными байтами в транзакции получения. Если значения ReadTotalTimeoutMultiplier и ReadTotalTimeoutConstant равны нулю, а прием FIFO последовательного контроллера пуст при отправке запроса на чтение на последовательный порт, этот запрос не истечет (и поэтому остается ожидающим в очереди ввода-вывода SerCx2) до тех пор, пока порт не получит хотя бы один байт новых данных. Дополнительные сведения см. в разделе 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 в этом запросе:

  • Флаг SERIAL_CTS_HANDSHAKE в элементе ControlHandShake структуры. Этот флаг позволяет последовательному порту использовать управление потоком для операций получения.
  • Флаги SERIAL_RTS_CONTROL и SERIAL_RTS_HANDSHAKE в элементе FlowReplace . Эти флаги позволяют последовательному порту использовать управление потоком для операций передачи.