Опубликован: 24.04.2009 | Уровень: специалист | Доступ: платный
Лекция 9:

Введение в драйверы устройств ввода/вывода

< Лекция 8 || Лекция 9: 1234 || Лекция 10 >
Аннотация: В данной лекции основное внимание уделяется драйверам устройств ввода/вывода. Приводятся практические примеры и задачи для самостоятельного рассмотрения.


Эта телефонная система LG Electronics Voice over IP (VoIP) основывается на Windows Embedded CE. Фотография с разрешения Mike Hall.

Введение в драйверы устройств В/В

Драйверы устройств помогают создать слой абстракции между оборудованием и прикладными программами пользователя. Типичный пользователь, разрабатывающий приложение, не должен понимать низко-уровневые детали оборудования каждого интерфейса. Вместо этого прикладная программа вызывает API ОС, который вызывает драйвер устройства. Работая на более высоком уровне абстракции, используя ОС и драйверы устройств, программисты приложений могут быть более продуктивными. При использовании ОС и драйверов устройств приложения можно переносить на различные аппаратные платформы с меньшими усилиями, и система будет также более стабильной и безопасной. ОС является критически важной в планировании, размещении, и управлении устройствами, которые совместно используются несколькими процессами. В качестве примера представьте, что произойдет, если два приложения начнут одновременно посылать символьные данные непосредственно оборудованию принтера. В результате получится случайная смесь символов на каждой напечатанной странице.

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

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

Таблица 9.1. Библиотеки драйверов устройств CE
Библиотека Описание
Собственные библиотеки микропроцессора Драйверы устройств для тесной интеграции собственных периферийных устройств микропроцессора. Например, микропроцессор ARM, и его дополнительная микросхема интегрирует многие периферийные устройства микропроцессора, такие как LCD, последовательный порт, USB Host, функцию USB, и т.д. SDB или аппаратная платформа, которая использует специальный микропроцессор будут использовать то же самое множество собственных драйверов микропроцессора. В Windows Embedded CE большинство микропроцессоров являются высоко интегрированными микропроцессорами, которые содержат много собственной периферии. Они связаны с так называемыми драйверами SOC (система-на-микросхеме) и находятся в ..\WINCE600 \Platform\Common\Src\SOC.
Специфические для микропроцессора библиотеки поддержки OAL Функции OAL для устройств, таких как часы реального времени, таймер, и контроллер отладки Ethernet, который обычно присутствует в микропроцессоре. Эта библиотека минимизирует написанный код OAL. Они также называются драйверами SOC (система-на-микросхеме) и находятся в ..\WINCE600 \Platform\Common\Src\SOC.
BSP или драйверы специфические для аппаратной платформы Драйверы устройств для периферии, которые являются специфическими для заданного SDB или аппаратной платформы. Эти драйверы имеют специфический для аппаратной платформы код и могут использоваться только на этой аппаратной платформе. Эти драйверы находятся в ..\WINCE600\Platform\<Hardware Platform Name> \Src\Drivers.
Другие распространенные драйверы периферийных устройств Драйверы для стратегических периферийных наборов микросхем, которые обычно встречаются во многих SDB или конструкциях аппаратных платформ. Сюда входят такие устройства как Realtek RTL8139, базовый NE2000, наборы микросхем DEC/Intel 2114x Ethernet, MediaQ MQ200, наборы микросхем дисплея ATI Rage XL, и наборы микросхем аудио Ensoniq. Цель состоит в том, чтобы предоставить драйверы производственного качества для 50% стратегических наборов микросхем, которые покрывают более 75% аппаратных платформ, доступных на рынке. Они называются общими драйверами и находятся в . .\WINCE600\Public\Common\Oak\Drivers. Исходный код для модулей находится в каталоге Public.

Модель потокового интерфейса для драйверов устройств

Драйвером1Part of the material presented in this Chapter was obtained from or is derived from the CE 6.0 on-line help files, MEDC 2006 conference presentations by members of the Windows Embedded CE design team, and Microsoft’s Windows Embedded CE Professional Training Materials. Reprinted with Permission of Microsoft Corporation. с потоковым интерфейсом является любой драйвер, который предоставляет функции потокового интерфейса, независимо от типа устройства, которым управляет драйвер. Модель потокового интерфейса является простейшим способом реализации большинства драйверов пользователя, и приложения обращаются к ним с помощью обычных функций API файловой системы. Подобно многим свойствам ОС, подход на основе потокового интерфейса ведет свое начало из первых версий Unix.

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

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

Сами функции потокового интерфейса создаются таким образом, чтобы как можно ближе соответствовать семантике обычных интерфейсов прикладного программирования (API) файловых систем, таких как CreateFile, WriteFile, ReadFile, IOControl, и CloseHandle. В качестве побочного эффекта такого дизайна устройства, которые управляются потоковым интерфейсом, доступны для приложений через файловую систему; приложения взаимодействуют с драйвером, открывая специальные файлы в файловой системе.

Драйверы потокового интерфейса могут иметь монолитную архитектуру или архитектуру с двумя слоями, MDD и PDD, как показано на рисунке 9.1.

Две альтернативные архитектуры драйвера потокового интерфейса. Монолитный драйвер потокового интерфейса или Разделенный на слои драйвер потокового интерфейса. В разделенной на слои архитектуре драйвера в CE два слоя называются MDD и PDD

Рис. 9.1. Две альтернативные архитектуры драйвера потокового интерфейса. Монолитный драйвер потокового интерфейса или Разделенный на слои драйвер потокового интерфейса. В разделенной на слои архитектуре драйвера в CE два слоя называются MDD и PDD

Интерпретация устройств как специальных файлов распространена во многих операционных системах, включая настольные версии Microsoft Windows и даже первые версия Unix. Там устройства печати традиционно представлялись именами специальных файлов LPTx:, а последовательные порты именами специальных файлов COMx:, и т.д.

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

В некоторых менее распространенных случаях драйверы потокового интерфейса могут переупаковывать существующие ресурсы, обычно таким образом, который специфические приложения смогут более легко использовать. Например, такой тип драйвера потокового интерфейса может управлять приемником системы глобального позиционирования (GPS) с последовательным интерфейсом. В этом примере ISV может выбрать создание специального драйвера потокового интерфейса для работы в соединении с приложением отображения GPS. Многие приемники GPS соединяются с последовательными портами. Приложение отображения GPS может, поэтому, открыть специальный файл COMx:, соответствующий последовательному порту и непосредственно взаимодействовать с приемником GPS.

Однако приемник GPS может предоставлять данные позиционирования в неудобном формате, или создатель приложения может захотеть сохранить скрытыми детали управления специальными моделями приемников GPS. Поэтому можно написать драйвер потокового интерфейса для обеспечения взаимодействия между приложением и приемником GPS. Драйвер будет взаимодействовать с приемником GPS как и раньше через специальный файл COMx:, но может переупаковывать данные позиционирования в более удобном формате для приложения. Драйвер может предоставлять свои собственные службы как специальный файл GPSx:, который будет открывать приложение, чтобы прочитать данные позиционирования.

Драйвер потокового интерфейса получает команды от Device Manager или из приложений посредством вызовов файловой системы. Драйвер инкапсулирует всю информацию, которая необходима для трансляции этих команд в соответствующие действия на устройствах, которыми он управляет.

Все драйверы потоковых интерфейсов, управляют ли они встроенными устройствами или устанавливаемыми устройствами, загружаются ли они во время начальной загрузки или загружаются динамически, имеют похожие взаимодействия с другими системными компонентами. Рисунок 9.2 показывает архитектуру драйверов потокового интерфейса для встроенных устройств, которые загружаются Device Manager во время начальной загрузки.

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

Можно реализовать драйвер только с точками входа Init и Deinit и без префикса устройства. Невозможно получить доступ к этому драйверу с помощью CreateFile. PCIBUS и RegEnum являются двумя примерами такого типа драйвера. Эти драйверы находятся в каталогах ..\WINCE600\Public\Common\OAK\Drivers\PCIbus и ..\WINCE600\Public\Common\ OAK\Drivers\RegEnum.

Архитектура потокового интерфейса

Рис. 9.2. Архитектура потокового интерфейса

Если DEVFLAGS_NAKEDENTRIES определен в подключе реестра Flags драйвера, то имена точек входа могут быть лишены отличий; например, Open, Close, и т. д. Пример драйвера батареи, который находится в ..\WINCE600\Public\Common\OAK\Drivers\Battdrvr, является примером драйвера, который использует точки входа без отличий. Настройки реестра драйвера батареи должны тем не менее включать префикс.

Реализации этих точек входа должны объявляться для экспорта из DLL, размещая __declspec(dllexport) перед объявлением функции. При разработке в C++, точки входа должны также объявляться как внешние "C".

Таблица 9.2 показывает функции драйвера потокового интерфейса с описанием назначения каждой из них. XXX в имени каждой функции заменяется трехсимвольным именем устройства. Эти функции определяются внутренне только для менеджера устройств, а не для приложений пользователя.

Таблица 9.2. Функции драйвера потокового интерфейса.
Программный элемент Описание
XXX_Close Эта функция закрывает контекст устройства, определенный hOpenContext. Эта функция требуется для доступа к устройству с помощью CreateFile. Если вы реализуете XXX_Close, вы должны реализовать XXX_Open.
XXX_Deinit Эта функция де-инициализирует устройство. Ее вызывает Device Manager. Эта функция требуется драйверам, загружаемым ActivateDeviceEx, ActivateDevice, или RegisterDevice.
XXX_Init Эта функция инициализирует устройство. Ее вызывает Device Manager. Эта функция требуется драйверам, загружаемым ActivateDeviceEx, ActivateDevice, или RegisterDevice.
XXX_IOControl Эта функция посылает команду на устройство. Эта функция может требоваться или нет, в зависимости от возможностей устройства, которые предоставляет драйвер. Эта функция требует реализации XXX_Open и XXX_Close.
XXX_Open Эта функция открывает устройство для чтения, записи, или того и другого. Приложение неявно вызывает эту функцию, когда вызывает CreateFile для получения указателя на устройство. Эта функция требуется для доступа к устройству с помощью CreateFile.
XXX_PowerDown Не обязательная. Эта функция выключает питание устройства. Она будет полезна только с устройствами, которые можно выключить с помощью программного управления.
XXX_PowerUp Не обязательная. Эта функция восстанавливает питание в устройстве.
XXX_PreClose Не обязательная. Эта функция помечает закрывающий указатель как недействительный, и пробуждает все спящие потоки.
XXX_PreDeinit Эта функция помечает экземпляр устройства как недействительный и пробуждает спящие потоки. Эта функция требуется, если реализована функция XXX_PreClose.
XXX_Read Эта функция считывает данные из устройства, идентифицированного открытым контекстом. Эта функция может требоваться или нет, в зависимости от возможностей устройства, которые предоставляет драйвер. Эта функция требует реализации XXX_Open и XXX_Close.
XXX_Seek Эта функция перемещает указатель данных в устройстве. Эта функция может требоваться или нет, в зависимости от возможностей устройства, которые предоставляет драйвер. Эта функция требует реализации XXX_Open и XXX_Close.
XXX_Write Эта функция записывает данные в устройство. Эта функция может требоваться или нет, в зависимости от возможностей устройства, которые предоставляет драйвер. Эта функция требует реализации XXX_Open и XXX_Close.

Так как периферийные устройства доступны приложениям как файлы, когда создается потоковый интерфейс, то нужно предоставить реализацию такого файла. Поэтому, рассмотрите, будет ли это практично, на основе возможностей устройства, которые предоставляет драйвер, чтобы позволить нескольким приложениям иметь одновременный доступ к файлу, который представляет устройство. То есть, рассмотрите, может ли драйвер иметь несколько открытых указателей файлов на своем устройстве. Драйвер потокового интерфейса может реализовать одиночный доступ или множественный доступ, используя параметр hOpenContext, передаваемый всем функциям В/В файла.

Чтобы реализовать множественный доступ, каждый вызов функции XXX_Open должен возвращать различное значение для hOpenContext. Драйвер устройства должен отслеживать, какие возвращаемые значения из XXX_Open используются. Последующие обращения к XXX_Close, XXX_Read, XXX_Write, XXX_Seek, и XXX_IOControl передают эти значения назад драйверу устройства, позволяя драйверу идентифицировать, какими внутренними структурами данных манипулировать.

Для реализации одиночного доступа, только первый вызов XXX_Open должен возвращать действительное значение hOpenContext. Пока это значение остается действительным, что будет иметь место, пока для этого значения не будет вызвана функция XXX_Close, последующие обращения к XXX_Open должны возвращать NULL вызывающему приложению, чтобы указать на отказ.

< Лекция 8 || Лекция 9: 1234 || Лекция 10 >
Бахтиёр Бутаев
Бахтиёр Бутаев
Таджикистан, Душанбе, Таджикский Технический Университет (ТТУ), 2013
Ярославй Грива
Ярославй Грива
Россия, г. Санкт-Петербург