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


Атомарные операции шины

Чтобы использовать определенные аппаратные возможности периферийного устройства, подключенного к SPB, клиенту контроллера SPB (то есть периферийного драйвера) может потребоваться выполнить последовательность передачи данных на устройство и с устройства в качестве операции атомарной шины. Последовательность передачи является атомарной, так как ни один другой клиент не может передавать данные на устройство в шине или с устройства до завершения последовательности.

Типичный способ выполнения клиентом последовательности передачи в качестве операции атомарной шины — отправка запроса IOCTL_SPB_EXECUTE_SEQUENCE на целевое устройство. В этом запросе клиент указывает последовательность в виде списка простых операций чтения и записи. Список может быть произвольной длины. Операции чтения и записи выполняются в том порядке, в котором они перечислены, и каждое чтение или запись может передавать произвольное количество байтов. Большинство контроллеров SPB поддерживают запросы IOCTL_SPB_EXECUTE_SEQUENCE .

Блокировки контроллера SPB

Менее распространенным способом выполнения атомарной последовательности передачи является использование блокировки контроллера SPB. Клиент отправляет IOCTL_SPB_LOCK_CONTROLLER запрос на получение блокировки и IOCTL_SPB_UNLOCK_CONTROLLER запрос на освобождение блокировки. Когда клиент удерживает блокировку контроллера, любая последовательность простых запросов на чтение и запись (IRP_MJ_READ и IRP_MJ_WRITE), отправляемых клиентом на устройство, выполняется как атомарная операция на шине.

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

Например, устройство может реализовывать функции устройства, доступ к которым можно получить только с помощью операций чтения, изменения и записи, которые являются атомарными в шине. Для выполнения такой операции клиент отправляет следующие четыре запроса ввода-вывода (в указанном порядке):

  1. IOCTL_SPB_LOCK_CONTROLLER — получение блокировки контроллера.
  2. IRP_MJ_READ — чтение блока данных с целевого устройства.
  3. IRP_MJ_WRITE — запись измененных данных обратно на устройство.
  4. IOCTL_SPB_UNLOCK_CONTROLLER — отпустите блокировку контроллера.

После операции чтения в предыдущем списке клиент интерпретирует данные, считанные с устройства, и изменяет данные перед их записью на устройство.

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

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

Сигналы аппаратной шины

Для обработки запроса IOCTL_SPB_EXECUTE_SEQUENCE драйвер контроллера SPB настраивает оборудование контроллера для создания соответствующих сигналов в шине во время последовательности передачи. Периферийные устройства, подключенные к шине, могут полагаться на эти сигналы, чтобы определить, когда выполняется атомарная шина. Набор аппаратных сигналов, которые контроллер SPB использует для выполнения последовательности передачи в качестве операции с атомарной шиной, зависит от типа шины.

Для шины I2C контроллер запускает последовательность путем передачи начального бита в шине, а завершает последовательность, передавая стоп-бит. Между разрядами запуска и остановки последовательность передачи данных на устройство и с устройства выполняется как одна атомарная шина. За исключением окончательной передачи в последовательности, за каждой передачей следует операция перезапуска I2C (повторяющийся начальный бит, которому не предшествует стоп-бит).

Для шины SPI контроллер запускает последовательность, утверждая линию выбора микросхемы на целевом устройстве, и завершает последовательность, деассечивая линию chip-select. Если линия выбора микросхем постоянно утверждается во время последовательности передачи данных по шине, передача выполняется как единая атомарная шина.

Пример устройства I2C

Типичное периферийное устройство на шине I2C может реализовывать несколько внутренних функций устройства. Для доступа к некоторым из этих функций клиент может использовать запросы IOCTL_SPB_EXECUTE_SEQUENCE .

Например, периферийное устройствоI2C может содержать следующие два внутренних регистра:

  • Регистр адресов функции, в который клиент записывает внутренний адрес функции устройства для доступа.
  • Регистр данных, с помощью которого клиент считывает данные или записывает данные в указанный адрес функции.

Периферийное устройствоI2C в этом примере интерпретирует первый байт, записанный на устройство после начального бита, как адрес функции для загрузки в регистр function-address. Все дополнительные байты, передаваемые на устройство или с устройства до окончания последовательности (как указано стоп-битом), обрабатываются устройством как данные, передаваемые через регистр данных.

Для выполнения операции записи клиент отправляет запрос на запись (IRP_MJ_WRITE), в котором первый байт в буфере записи является адресом функции, а остальные байты буфера являются данными, которые необходимо записать в адрес функции.

Чтение с устройства сложнее. Предположим, что устройствоI2C в этом примере поддерживает функцию быстрого чтения, которая автоматически сбрасывает регистр адреса функции до значения по умолчанию 0 при обнаружении бита остановки в шине. С помощью этой функции клиент может считывать данные с адреса функции 0 без предварительной записи в регистр адресов-функций. Эта функция может повысить скорость операций чтения устройства, особенно если большинство операций чтения выполняются с адреса функции 0 и относительно коротки.

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

В следующем списке описывается ряд запросов ввода-вывода, которые клиент отправляет устройству I2C в этом примере для выполнения операции чтения, изменения и записи с данными, расположенными по адресу ненулевой функции на устройстве.

  1. IOCTL_SPB_EXECUTE_SEQUENCE . Выполнение последовательности передачи ввода-вывода для чтения данных с устройства. Первая передача в этой последовательности — запись в байт в регистр адреса функции. Вторая передача в последовательности — это чтение некоторого количества байтов из выбранного адреса функции. Эти две передачи выполняются атомарно на автобусе.
  2. IRP_MJ_WRITE — запись данных на устройство. Первый байт в буфере записи для этого запроса является значением для записи в регистр адреса функции. Оставшиеся байты в буфере являются данными для записи в адрес выбранной функции.

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

Чтобы выполнить чтение, изменение и запись по адресу функции 0 на этом устройстве, запрос IOCTL_SPB_EXECUTE_SEQUENCE на шаге 1 предыдущего списка можно заменить простым запросом на чтение (IRP_MJ_READ).