Как написать драйвер com порта

24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

1

19.12.2016, 19:22. Показов 21196. Ответов 128


Всем здрасте…
Хотелось бы услышать мнения профессионалов. В частности Убежденного видел много сообщений от него..
Итак. Есть устройство usb, в данный момент используется виндовый usbser, но говорят работает плохо.
Мне поставили задачу(я на первом своём испытательном сроке) написать драйвер для данного устройства. Драйвер должен эмулировать COM порт(основной приоритет), а также возможно как сетевое устройство или сырой обмен, можно все вместе.
Знания драйверов у меня на уровне хелловорлд. Английский очень плохо. Читаю Уолтер Они, Комиссарова, Агуров, USB in Nutshell.
Вопрос первый — реально ли с моими знаниями хорошо сделать это за 2 месяца?
Вопрос второй — направьте меня на путь истинный)) дельные советы дайте

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



0



Ушел с форума

Эксперт С++

16456 / 7420 / 1186

Регистрация: 02.05.2013

Сообщений: 11,617

Записей в блоге: 1

19.12.2016, 21:12

2

Цитата
Сообщение от VD
Посмотреть сообщение

Хотелось бы услышать мнения профессионалов. В частности Убежденного

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

Цитата
Сообщение от VD
Посмотреть сообщение

Вопрос первый — реально ли с моими знаниями хорошо сделать это за 2 месяца?

Нет.

А как ты попал в разработку драйверов USB, — такую головоломную и сложную тему, —
со «знанием драйверов у меня на уровне хелловорлд» и английским, который «очень плохо»?

Цитата
Сообщение от VD
Посмотреть сообщение

Вопрос второй — направьте меня на путь истинный)) дельные советы дайте

Пиши код, исследуй, думай, задавай вопросы.
2 месяца — нет, не реально. Но за полгодика, думаю, вполне можно что-то наваять…



1



24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

22.12.2016, 11:44

 [ТС]

3

А может стоит начать с WDF. Может быстрее получится решить задачу?



0



Ушел с форума

Эксперт С++

16456 / 7420 / 1186

Регистрация: 02.05.2013

Сообщений: 11,617

Записей в блоге: 1

22.12.2016, 11:54

4

WDF хорош тем, что позволяет сконцентрироваться на задаче, не отвлекаясь на реализацию.
Но с WDF или без него — тебе все равно придется осваивать науку программирования в ядре:
устройство памяти, уровни привилегий, контексты, IRQL, синхронизация, стандартные
функции, планировщик, системные API и т.д. От этого никуда не денешься.



0



24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

22.12.2016, 12:04

 [ТС]

5

Да я бы и не спрашивал а начал c всего этого.. читал здесь комменты по этому поводу ваши.. просто время.. боюсь не успеть и не примут. А может набросать план действий для конкретной задачи? Сделать из USB устройства COM порт, а то сказали стандартный usbser глючит? План в смысле изучить…список глав например из Уолтера Они или еще что то. Может есть где пример какой. Может потренироваться с флешкой есть какие примеры несложные чтоб USB понять. А то в голове каша пока… т.к. в википедии написано: «WDM требует от разработчиков драйверов полного знакомства со множеством сложных технических деталей перед написанием даже простейшего драйвера.»



0



Ушел с форума

Эксперт С++

16456 / 7420 / 1186

Регистрация: 02.05.2013

Сообщений: 11,617

Записей в блоге: 1

22.12.2016, 12:36

6

Цитата
Сообщение от VD
Посмотреть сообщение

А то в голове каша пока… т.к. в википедии написано: «WDM требует от разработчиков драйверов полного знакомства со множеством сложных технических деталей перед написанием даже простейшего драйвера.»

Так оно и есть. И добавить к этому нечего.

«Приняли на работу хирургом, как скальпель держать правильно?
Может, есть какие-то видеоуроки, чтобы побыстрее начать оперировать?
А то в Википедии написано: хирургия требует от хирурга высокого мастерства и
знания множества технических деталей перед проведением даже самой
простой операции»…



0



24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

22.12.2016, 12:38

 [ТС]

7

Да я же не прошу у вас книжку как за 11 дней выучить С++. Я просто хочу выжать максимум из этого времени и не тратить время на вещи которые можно потом освоить



0



Ушел с форума

Эксперт С++

16456 / 7420 / 1186

Регистрация: 02.05.2013

Сообщений: 11,617

Записей в блоге: 1

22.12.2016, 12:44

8

Начни с чтения литературы. В первую очередь Уолтер Они и MSDN, главы, связанные с
общими вопросами программирования драйверов и USB в частности.

Скачай Windows Driver Kit и изучай исходники примеров для USB. Они сейчас есть онлайн.
Вопросов, которые будут возникать по ходу изучения, хватит для полной и глубокой
загрузки на много лет

А два месяца — нет, это совершенно нереально.



0



24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

26.12.2016, 19:31

 [ТС]

9

Взял пример stupid из Они, сделал инициализации в DriverEntry, в AddDevice создал device object, зарегистрировал в ней интерфейс COM порта, и посадил созданный девайс в стек. Взял валявшийся у меня usb rutoken, взял inf файл от его дров, там тоже прописал интерфейс для ком порта. В итоге когда я подключаю рутокен вызывается AddDevice. Я правильно двигаюсь? Теперь я так понимаю нужно сделать обработку IRP от PnP, Power и WMI т.к. все WDM драйверы должны это уметь? И для моих целей обработку Read Write? Получается есть наверно какая то спецификация по преобразованию запросов IRP для дальнейшей передачи их на драйвер шины? А можно в общих словах объяснить логику обработки PnP, Power и WMI например если устройство питается от USB и нет?



0



Ушел с форума

Эксперт С++

16456 / 7420 / 1186

Регистрация: 02.05.2013

Сообщений: 11,617

Записей в блоге: 1

26.12.2016, 19:49

10

Цитата
Сообщение от VD
Посмотреть сообщение

Взял пример stupid из Они, сделал инициализации в DriverEntry, в AddDevice создал device object, зарегистрировал в ней интерфейс COM порта, и посадил созданный девайс в стек. Взял валявшийся у меня usb rutoken, взял inf файл от его дров, там тоже прописал интерфейс для ком порта.

Ну что ж, поздравляю, это весьма глубокое продвижение за такой короткий срок!

Цитата
Сообщение от VD
Посмотреть сообщение

Я правильно двигаюсь?

Судя по успехам — да.

Цитата
Сообщение от VD
Посмотреть сообщение

Теперь я так понимаю нужно сделать обработку IRP от PnP, Power и WMI т.к. все WDM драйверы должны это уметь?

Да.
PnP и Power — обязательно. WMI — опционально.

Цитата
Сообщение от VD
Посмотреть сообщение

Получается есть наверно какая то спецификация по преобразованию запросов IRP для дальнейшей передачи их на драйвер шины?

Цитата
Сообщение от VD
Посмотреть сообщение

А можно в общих словах объяснить логику обработки PnP, Power и WMI например если устройство питается от USB и нет?

Логика обработки PnP и Power во всех драйверах одинакова на 90-95%.
5% — это специфика твоего драйвера и/или устройства, которым он управляет.
Если ты программируешь какое-то устройство, то у тебя должна быть спецификация для него.
Иначе это мало чем будет отличаться от реверс инжиниринга…



1



24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

27.12.2016, 21:24

 [ТС]

11

Вроде как появился COM3 в диспетчере устройств. IoRegisterDeviceInterface и IoSetDeviceInterfaceState вызываются. Но putty не подключается к нему, как будто его нет. Я что то не так понял или не дочитал?



0



Ушел с форума

Эксперт С++

16456 / 7420 / 1186

Регистрация: 02.05.2013

Сообщений: 11,617

Записей в блоге: 1

28.12.2016, 08:46

12

«Я написал программу. Но она не работает. Я что-то сделал не так?»

Давай уже конкретику.



0



VD

24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

28.12.2016, 11:17

 [ТС]

13

Нуу я не написал, я просто взял пример toaster/func из ddk 2600, и изменил там пару строчек

Добавлено через 1 час 35 минут

C++
1
2
3
4
5
6
7
8
// COM {4d36e978-e325-11ce-bfc1-08002be10318}
DEFINE_GUID(GUID_DEVINTERFACE_COM, 
        0x4d36e978L, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18);
...
    status = IoRegisterDeviceInterface(PhysicalDeviceObject, &GUID_DEVINTERFACE_COM, NULL, &fdoData->InterfaceName);
    DbgPrint("%wZ", &fdoData->InterfaceName);
...
status = IoSetDeviceInterfaceState(&FdoData->InterfaceName, TRUE);

После этого я могу обращаться к com порту например по com3 или еще что то нужно? Вроде почитал msdn не особо въехал. Написано что то типа пользовательские приложения могут использовать &fdoData->InterfaceName
&fdoData->InterfaceName

Добавлено через 37 минут
О вот на \.USB#Vid_………{4d36e978-e325-11ce-bfc1-08002be10318} реагирует, когда я ввожу это в pytty. Выдает код для STATUS_NOT_SUPPORTED. А как сделать так чтоб он на имя COM… реагировал?



0



Ушел с форума

Эксперт С++

16456 / 7420 / 1186

Регистрация: 02.05.2013

Сообщений: 11,617

Записей в блоге: 1

28.12.2016, 11:21

14

Создай символьную ссылку COM -> \.USB#Vid…
А вообще, здесь моя сфера знаний заканчивается. Я реальные устройства никогда не
программировал, занимался только безопасностью — перехват процессов, фильтрация на
разных уровнях, недокументированные возможности системы, сигнатурный поиск и т.п.
Так что на меня в вопросах программирования железа лучше не полагаться



0



VD

24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

29.12.2016, 10:52

 [ТС]

15

Да я в курсе читал уже в каком то посте про «безопасностью — перехват процессов, фильтрация на
разных уро….». Ладно спасибо..лихо там в примере все закручено буду разбираться

Добавлено через 23 часа 22 минуты
Создай символьную ссылку COM -> \.USB#Vid…
Что то не получается создать символьную ссылку на символьную ссылку

C++
1
2
3
4
5
6
7
8
status = IoRegisterDeviceInterface(PhysicalDeviceObject, &GUID_DEVINTERFACE_COM, NULL, &fdoData->InterfaceName);
status = IoCreateSymbolicLink(&fdoData->portName, &fdoData->InterfaceName);
if (!NT_SUCCESS (status)) 
{
    DbgPrint("  XXX   Filed Create Symbolic Link");
    DbgPrint("  XXX   %wZ", &fdoData->InterfaceName);
    DbgPrint("  XXX   %wZ", &fdoData->portName);
}

XXX Filed Create Symbolic Link
XXX ??USB#Vid_0a89&Pid_0020#5&18f54cb7&0&2#{4d36e978-e325-11ce-bfc1-08002be10318}
XXX COM3



0



24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

02.02.2017, 15:54

 [ТС]

16

Кто нибудь разбирается в запросах к USB CDC устройству
Например как отправить SET_CONTROL_LINE_STATE?
Накопал UsbBuildVendorRequest в MSDN с запросом GET_LINE_CODING получилось. А с SET_CONTROL_LINE_STATE не очень



0



1366 / 511 / 70

Регистрация: 21.07.2015

Сообщений: 1,290

07.02.2017, 12:32

17

VD, найди документацию на свой чип, там должно быть описание usb-запросов. Я думаю, что там одна или две дополнительные конечные точки, одна из них скорее всего имеет тип передачи по прерыванию. По второй данные записываются в порт, а возможно что и вообще через 0ю (контрольную) запись и управление идет. В любом случае для инициализации устройства нужно установить ему конфигурацию одноименным стандартным запросом. По умолчанию у USB устройств обычна установлена конфигурация ожидания, в которой по факту только могут отвечать на запросы (типа режим спячки такой). Также тебе потребуются запросы установки параметров обмена (скорости обмена и прочего). В крайнем случае залезь в исходники линуксового драйвера.
ЗЫ: я много работал с USB железом, но только не в винде (через свой самописный драйвер хост-контроллера). Поэтому могу просто подсказать по железной части, про программную модель USB видны не знаю и знать не хочу.



1



24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

08.02.2017, 08:12

 [ТС]

18

Спасибо за ответ. Да конфигурация уже была установлена и с этим разобрался в принципе, простой обмен прошел устройство отвечает. Оно соответствует спецификации CDC, узнал все из дескрипторов там 4 конечные точки. 2 для данных bulk, нулевая и прерывающая. Ни как не пойму как задействована прерывающая. Снифером смотрел как стандартный драйвер от майкрософт общается с устройством, но запросов к прерывающей точке не видел.

И как моему драйверу узнавать что есть данные для считывания. Прерываний для USB нет, вроде как хост опрашивает. В винде я так понимаю этим занимаются драйверы хоста и прочее их куча под моим. Может кто то из них оповещает мой драйвер? Может кто то знает кроме товарища shmkv, который не хочет об этом знать



0



1366 / 511 / 70

Регистрация: 21.07.2015

Сообщений: 1,290

08.02.2017, 13:46

19

Цитата
Сообщение от VD
Посмотреть сообщение

Снифером смотрел как стандартный драйвер от майкрософт общается с устройством, но запросов к прерывающей точке не видел.

А данные в этот момент принимаются?

Цитата
Сообщение от VD
Посмотреть сообщение

И как моему драйверу узнавать что есть данные для считывания.

Мне думалось, что для этого и предназначена interrupt-in КТ. Тогда всех проще посмотреть снифером какие команды и куда шлет виндовый драйвер и потом отыскать их в документации. Я думаю, что там какой-то запрос наличия данных в буфере постоянно высылается, а после него уже команда считывания данных. А непосредственно сами данные вчитываются из bulk-in. В винде должен быть механизм асинхронного уведомления о завершении обработки USB запроса.



0



24 / 13 / 3

Регистрация: 02.08.2012

Сообщений: 160

08.02.2017, 14:18

 [ТС]

20

Да данные в этот момент принимаются и нет запросов к прерывающей точке. Хост вроде как опрашивает все устройства на шине. Ну по идее он должен бы моему сообщить драйверу что есть данные для приема и я уже сигнализировать об этом приложению чтоб оно выдало запрос на чтение. Короче ни как пока не въеду



0



Микроконтроллеры К1986ВЕ1QI, К1986ВЕ92QI, К1901ВЦ1GI и К1986ВК01GI имеют контроллер USB-интерфейса, реализующий функции контроллера ведомого устройства (Device) и ведущего устройства (Host). В составе библиотеки SPL приведён пример для ведомого устройства (Device) под названием «VCOM_Echo», который позволяет использовать МК в качестве CDC USB устройства (Класс Коммуникационного Устройства), настроенного как виртуальный COM-порт. Чтобы ПК определял МК именно как устройство, подключенное по COM-порту, необходимо установить специальный драйвер. Ссылка на скачивание драйвера доступна в конце статьи.

В данной статье рассмотрена пошаговая установка драйвера Virtual COM порт в ОС Windows 7.

Установка драйвера

Для установки драйвера виртуального COM-порта необходимо иметь права администратора!

Загружаем в МК проект «VCOM_Echo» и подключаем отладочную плату к ПК с помощью кабеля USB A-B. На ПК открываем «Диспетчер устройств Windows», его можно найти в поиске меню «Пуск». Если драйвер не установлен, то после подключения МК по USB в диспетчере устройств появится «Неизвестное устройство». Открываем «свойства» нового устройства, как показано на рисунке 1.

Рисунок 1 — Диспетчер устройств Windows: неизвестное устройство

Если МК определился в группе «Контроллеры USB» и отображается как «Unknown Device», вероятно был нарушен протокол обмена по USB, и проблему следует искать в ПО МК.

В открывшемся окне «Свойства…» выбираем пункт «Изменить параметры» (рисунок 2), при этом возможно потребуется ввести пароль администратора.

Рисунок 2 — Свойства «неизвестного устройства»

В новом окне выбираем пункт «Обновить драйвер», как показано на рисунке 3.

Рисунок 3 — Обновление драйвера в окне «Свойства…»

Здесь необходимо выбрать «поиск драйверов на компьютере» (рисунок 4).

Рисунок 4 — Окно «Обновление драйверов»

Теперь необходимо разархивировать папку с драйверами в любую директорию на ПК, например, в корень диска С, после чего в открывшемся окне нужно указать путь к папке с драйвером и нажать кнопку «Далее» (рисунок 5).

Рисунок 5 — Окно «Обновление драйверов»: выбор директории с драйвером

В процессе установки Windows может вывести предупреждение, в котором необходимо выбрать пункт «Всё равно установить этот драйвер», как показано на рисунке 6.

Рисунок 6 — Окно с предупреждением при установке драйвера

После установки драйвера в диспетчере устройств во вкладке «Порты(COM и LPT)» должно появиться новое устройство «Milandr USB RS-232 Emulation Driver» (рисунок 7).

Рисунок 7 — Диспетчер устройств Windows: новое COM-устройство 

Если установить всё-таки не получается, то

Можно попробовать запустить операционную систему Windows в безопасном режиме или режиме с отключенной обязательной проверкой подписи драйверов. 

Для Windows 7 при запуске компьютера необходимо быстро нажимать клавишу F8, после чего появится окно аналогично тому, что представлено на рисунке 8. После этого выбрать либо безопасный режим, либо режим с отключенной обязательной проверкой подписи драйверов и попробовать установить драйвер снова.

Рисунок 8 — Дополнительные варианты загрузки Windows 7

Для Windows 8 и 10 есть несколько способов перейти в аналогичное Windows 7 меню выбора режима загрузки, но самый простой заключается в том, чтобы нажать кнопку «Перезагрузка» вместе с зажатой кнопкой Shift прямо в меню «Пуск» (рисунок 9).

Рисунок 9 — Алгоритм попадания в первоначальный загрузчик Windows

После перезагрузки всплывёт полностью синий экран с различными вариантами загрузки операционной системы, необходимо перейти в меню «Поиск и устранение неисправностей» > «Дополнительный параметры» > «Параметры загрузки». После этого всплывёт окно с выбором режима загрузки операционной системы, как на рисунке 10.

Рисунок 10 — Меню выбора режимов загрузки Windows 8 (10)

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

Сохранить статью в PDF

В статье описывается 2 проекта, основанные на библиотеке V-USBCDC-232 и CDC-IO. Автор — Osamu Tamura @ Recursion Co., Ltd.

Оба проекта представляют из себя простую схему на микроконтроллере AVR (ATtiny45/85, ATtiny461, ATtiny2313, ATmega8/48/88), которая при подключении к порту USB компьютера (далее просто PC) создает виртуальный COM-порт. В обоих проектах используется бесплатная библиотека V-USB, которая позволяет средствами firmware, прошитого в микроконтроллер AVR, поддержать работу интерфейса USB. Первый проект (CDC-232) создает на компьютере виртуальный COM-порт, через который можно обмениваться данными с каким-нибудь другим устройством, имеющим низковольтный RS-232C (например, с микроконтроллером AT89C51 Atmel). Второй проект (CDC-IO) тоже создает виртуальный COM-порт, но он предназначен для управления ресурсами микроконтроллера (регистрами внутреннего назначения). То есть посылкой простых текстовых команд в консольной программе Вы можете менять состояние ножек микроконтроллера AVR, читать их состояние, управлять таймерами — счетчиками, PWM, читать ADC и т. д. 

[CDC-232

CDC-232 создает виртуальный COM-порт на PC, даже если он не имеет реального порта RS-232C. Это позволяет производить обмен данными RS-232C (без сигналов управления) после подсоединения устройства и установки драйвера.

cdc232-fig.gif
Виртуальный COM-порт, работающий через программную реализацию USB

[Применение CDC-232]

Запрограммируйте AVR, спаяйте схему и подключите устройство в порт USB компьютера. Установите драйвер (если у Вас операционная система Windows). Получите доступ к устройству через сгенерированный виртуальный COM-порт из программы терминала или написанную Вами программу (которая работает с COM-портом). Сигналы управления (DTR, DTS, RTS, CTS) не используются, поэтому настройте программу терминала в режим «no flow-control» (без контроля потока).

Windows запросит установку драйвера заново всякий раз, когда Вы подключите устройство в другой порт USB. Ранее установленный драйвер детектируется автоматически. Будет назначен другой номер COM-порта. Если Вы установите серийный номер в AVR (пересоберите исходный код с новым usbconfig.h), Вы можете получить тот же самый номер COM-порта на любом порте USB. Но в этом случае Вы не можете подключить сразу несколько устройств CDC с одним и тем же серийным номером.

Перед тем, как отсоединить устройство, закройте COM-порт в терминальной программе или в Вашем самописном приложении. В противном случае Вы не сможете подключить устройство снова из-за неверного дескриптора файла (broken file handle). В этом случае перезапустите программу терминала или Ваше приложение. Переключиться в режим быстрой передачи можно использованием «lowcdc.vbs», при этом можно получить скорость выше 9600 bps.

cdc232-photo1.gif
Loop-back тест на версии ATtiny45

[Принципиальные схемы CDC-232]

Эти схемы рассчитаны на ATtiny45/85, ATtiny2313/AT90S2313 и ATmega8/48/88/168. У всех этих микроконтроллеров firmware программируется через ISP. Красный LED понижает напряжение USB от 5V до 3.3V, и предоставляет его для AVR. Ток потребления около 10mA, и его мало для питания других узлов. Когда подключаетесь к другому MCU (микроконтроллеру), соедините Gnd и соедините TxD и RxD крест-накрест. R4 ограничивает обратный ток, когда внешний MCU питается от Vcc 5V (Вы можете R4 не ставить, если напряжение питания внешнего MCU равно 3.3V). R5 защищает ножку TxD, когда она замкнута на Gnd. Вы можете опустить и R4 и R5, если Вы соединяетесь через RS-232C драйвер наподобие MAX232. Используйте кварцевый резонатор. Несмотря на то, что керамический резонатор в большинстве случаев работает хорошо, но для данного применения он не подходит, поскольку уход частоты слишком большой, и поэтому устройство может работать нестабильно.

ATtiny45/85 использует внутренний RC-генератор и PLL. Он откалиброван на частоту 16.5 МГц по частоте сигнала SOF (Start Of Frame) порта USB, когда устройство подключено к PC. UART в этом случае реализован программно. Он не может поддерживать высокую скорость передачи данных. Если TxD и RxD проинвертированы (пересоберите проект с опцией -DINVERT), Вы можете напрямую подключиться к сигналам RS-232C. Формат настройки порта 300-4800bps, 8N1.

cdc232-45.gif
CDC-232 для ATtiny45-20

Пример на ATtiny45 с использованием коннектора mini-B

У микроконтроллера ATtiny2313/AT90S2313 всего лишь 2 KB памяти программ. Механизм установки терминала опущен (т. е. автодетекта скорости нет). Установите переключатель DIP для смены скорости.

cdc232-2313.gifCDC-232 для ATtiny2313-20

У микроконтроллеров ATmega8/48/88’s внутренний UART конфигурируется от PC автоматически. Формат настройки 1200-57600bps, данные 7/8, четность N/E/O, количество стоп-бит 1/2

cdc232-48.gifCDC-232 для ATmega8/48/88-20

Подключение к физическим линиям RS-232C требует инверсии полярности TxD и RxD, а также соответствие уровней сигнала. Используйте специальную IC наподобие MAX232. Вы можете её заменить простыми схемами (см. далее).

cdc232-if1.gif

Когда целевой MCU имеет другое питание Vcc (отличное от 3.3V), образуются обратные токи утечки через сигнальные линии. Это искажает сигнал, либо подпитывает MCU без источника питания. Эта схема не очень хороша, но достаточна для большинства случаев.

cdc232-if2.gif

[CDC-IO

CDC-IO управляет регистрами специального назначения (Special Function Registers, SFR) микроконтроллера AVR через виртуальный COM-порт на PC. Это позволяет свободно читать/записывать параллельные порты MCU (ножки микроконтроллера). Работают также операции с таймерами/счетчиками, PWM, ADC, EEPROM, что позволяет приложению на PC достичь очень глубокого управления микроконтроллером и разрабатываемым на нем устройством.

cdcio-fig.gif
Внешний интерфейс с использованием программной реализации протокола USB

[Применение CDC-IO]

Инсталляция такая же, как и у CDC-232. Скорость COM-порта произвольна. Отправка текстовых команд происходит через программу терминала или из вашей программы на PC. Если Вы хотите получить более высокую скорость передачи, используйте «lowcdc.vbs» для переключения в bulk transfer mode.

Набор команд CDC-IO (Instruction Set)

Функция Команда Формат Ответ
Who @ @ «cdc-io», CR-LF
Get ? address ? data, CR-LF
Set = data address = CR-LF
AND & Set & data address & CR-LF
OR & Set | data address | CR-LF
EX-OR & Set ^ data address ^ CR-LF
Set Double $ data2 data1 address $ CR-LF

Версия с ATtiny2313 имеет только команды «Set», «Get», «Xor».

В таблице команд использованы следующие обозначения:

address: адрес регистра SFR, отображенный на память (memory mapped) в hex-формате
data: 8 бит данные в hex
разделитель:    Tab, Space, CR, LF
predefined addr (предопределенные символические адреса, case-insensitive, НЕ поддерживаются ATtiny2313): PINB, DDRB, PORTB PINC, DDRC, PORTC PIND, DDRD, PORTD

Примеры (‘_’ означает разделитель):

            DDRB_?_                  Возвращает значение DDRB вместе с CR-LF.
            12_34_=_                 Запись 0x12 по адресу 0x34, в ответ возвращает CR-LF.
            FB_PORTC_&_     Запись (PORTC & 0xFB) в PORTC, возвращает CR-LF.

(примеры для ATtiny2313)
            36_?_                        Возвращает величину PINB(0x36) вместе с CR-LF.
            12_37_=_                  Запись 0x12 по адресу DDRB(0x37), возвращает CR-LF.
            FB_38_^_                 Запись (PORTB ^ 0xFB) в PORTB(0x38), возвращает CR-LF.

Предыдущие данные и адрес могут быть использованы повторно. Просто введите символ команды для повтора.

Команда «Set Double» используется для записи в EEPROM.

Избегайте изменения бит порта, на котором присутствуют сигналы USB. Используйте ‘&’, ‘|’ или ‘^’ для модифицирования направления порта (вход или выход). Используйте PIN* для переключения бит в противоположное состояние (toggle), если порт назначен как выход (output).

Когда разрешены прерывания, сообщается номер вектора прерывания, когда оно вызывается.

Все регистры SFR доступны. См. даташит AVR для использования таймеров, ADC, EEPROM, и т. п.

[Принципиальные схемы CDC-IO]

Если напряжение питания Vcc целевой схемы равно 5V, и порты AVR сконфигурированы как входы, поставьте резисторы (3K3…10Kом) для предотвращения обратного тока. Используйте только кварцевый резонатор. Несмотря на то, что керамический резонатор в большинстве случаев работает хорошо, но для данного применения он не подходит, поскольку уход частоты слишком большой, и поэтому устройство может работать нестабильно.

ATtiny45/85 использует внутренний RC-генератор и PLL. Он откалиброван на частоту 16.5 МГц по частоте сигнала SOF (Start Of Frame) порта USB, когда устройство подключено к PC.

cdcio-45.gif
CDC-IO для ATtiny45-20

cdcio-48.gif

CDC-IO для ATtiny461-20

Для ATtiny2313 реализованы только команды «Set», «Get» и «Xor» из-за ограниченной памяти программ этого микроконтроллера. Эта версия также не имеет механизма interrupt-report.

cdcio-2313.gif
CDC-IO для ATtiny2313-20

cdcio-48.gif

CDC-IO для ATmega8/48/88-20

[Пример программы]

Это экспериментальная схема и пример программы для ATmega8/48. Программа написана на C, VB, VC, VC++ и C#. Вы можете использовать другие языки (или макросы), если они могут работать с портом RS-232C.

cdcio-photo.gif
На фото показан внешний вид экспериментальной схемы

cdcio-demo.gif
Регулятор изменяет тон пищалки и маску мигания светодиодов.

cdcio-dos.gif

[Пример управления без программы]

Операционные системы позволяют работать с COM-портами, как с обычными файлами. Вот так, например, под Windows Вы можете послать команду устройству, которое создает виртуальный COM-порт COM3 (в текстовом файле comands.txt записана последовательность команд):

c:temp>copy comands.txt COM3
        1 file(s) copied.

Что интересно — под Windows XP можно использовать только имена COM1..COM9. Имена COM10, COM11, COM12, COM13 и далее Windows не воспринимает как системные, и думает, что это не порт, а файл (даже если такой порт реально имеется в Диспетчере Устройств).

[Ссылки]

1. Исходные тексты программ и firmware, описанные в статье, документация, драйвер для w2k, XP, Vista.
2. Проект CDC-232, портированный на AVR-USB-MEGA16 (ATmega16 с кварцем на 16 МГц).
3. AVR-CDC — Virtual COM Port over Low-Speed USB site:recursion.jp — сайт AVR-CDC Osamu Tamura @ Recursion Co.
4. USB консоль для управления радиолюбительскими приборами.

Natur_Keks

Интересующийся

ru
Offline Offline


 Здравствуйте. На работе поставили задачу: написать драйвер, создающий виртуальный COM порт, к которому сторонняя прога подключается как к реальному, но все отправляемые данные должны перенаправляться моему приложению. Также и наоборот: все данные от моей проги должны через драйвер уходить в этот виртуальный COM порт(и соответственно стороннему приложению).
 И вот вопрос: можно ли создать виртуальный COM порт, одновременный доступ к которому разрешён нескольким (двум) приложениям? Причём так, чтобы данные, приходящие от одного, перенаправлялись другому?
 Или нужно два драйвера: 1) драйвер виртуального COM порта 2)просто драйвер ядра. К первому подсоединяется стороннее приложение, ко второму моё приложение, между драйверами наладить обмен данными.
 Если что, сильно не пинать Улыбаюсь, написанием драйверов никогда не занимался Жаль. Буду благодарен за любые советы, ссылки, исходники.
 

« Последнее редактирование: 29-06-2011 11:19 от Ochkarik »
Записан
RXL

Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW


http://sourceforge.net/projects/com0com/
Посмотри вот это.
Идея проста: два виртуальных COM-порта, также виртуально соединенных нуль-модемным кабелем.


Записан

… мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.

Natur_Keks

Интересующийся

ru
Offline Offline


http://sourceforge.net/projects/com0com/
Посмотри вот это.
Идея проста: два виртуальных COM-порта, также виртуально соединенных нуль-модемным кабелем.

Спасибо за ссылку, но данный вариант я уже предлагал начальству — ответ был отрицательный и до ужаса простой: зачем 2 виртуальных порта, когда нужен только один… Вот так Улыбаюсь


Записан
RXL

Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW


А как второе приложение будет общаться с драйвером — об этом они подумали? И вообще, нафига изобретать велосипед, если все уже давно придумано.


Записан

… мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.

Ochkarik


эээ… я не совсем понимаю что требуется.
во первых, если это должен быть как бы совсем стандартный по функциям COM порт… разве можно одновременно подключится к ОДНОМУ COM порту из двух приложений?))  ответ — нельзя принципиально! не реальные, ни виртуальные.
то есть в любом случае, COM порт в системе захватывается одним приложением — монопольно. таким образом в любом случае, если вам действительно нужна эмуляция COM в обоих приложениях — порта должно быть два.
в качестве довода привести этот факт — начальству, после чего с чистой совестью  использовать вышеуказанную ссылку)

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

Добавлено через 13 минут и 22 секунды:
ежели припрет, постараюсь подсказать с чего начать)

« Последнее редактирование: 29-06-2011 09:21 от Ochkarik »
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW…

Natur_Keks

Интересующийся

ru
Offline Offline


 Насчёт невозможности открытия одного виртуального COM порта — программа VSPE http://www.radioscanner.ru/files/miscsoftware/file9815) каким-то образом это позволяет,т.е. возможно создать виртуальный COM порт, который можно открыть несколькими приложениями (типа Hyper Terminala) одновременно (проверял — работает). Причём данные из одного приложения передаюся в другое.
 Получается, в принципе это возможно, только, интересно, насколько сложно Улыбаюсь.
 Во второй программе,да действительно, интерфейс COM эмулировать не нужно — она (по задумке) производит обмен данными напрямую с драйвером.
  постараюсь подсказать с чего начать) — очень бы хотелось Улыбаюсь


Записан
darkelf

Молодой специалист

hu
Offline Offline


Во второй программе,да действительно, интерфейс COM эмулировать не нужно — она (по задумке) производит обмен данными напрямую с драйвером.

Ну ведь она не телепатически с драйвером общается — с ним тоже должен быть определённый интерфейс, а если так — почему-бы ему не быть com-портовым.


Записан
Natur_Keks

Интересующийся

ru
Offline Offline


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


Записан
Ochkarik


VSPE свой драйвер подставляет.
ну тогда видимо выбора нет, надо писать драйвер…. можно для очистки совести на API посмотреть — что там позволено… может быть можно поставить hook на функции обращения к порту и перехватывать http://www.rsdn.ru/article/baseserv/IntercetionAPI.xml
и была еще какая то библиотека для перехвата ядра… но убей бог пока не вспомню названия…
… вспомнил! Detours. http://research.microsoft.com/en-us/projects/detours/

если драйвер… то, ща поищу с чего начать.

Добавлено через 1 час, 53 минуты и 51 секунду:
раздел msdn архитектуры последовательных COM портов
для драйвера, вам потребуется DDK. наверное лучше сразу новый с майкрософта, но подойдет и старый с сайта.
из литературы — Вальтер Они, Руссинович и msdn — ваши друзья)
компиляция драйвера — утилитой build.exe, либо настройками VS (темы были на форуме)

там есть примеры драйвера COM порта, но он вам не факт что подойдет, потому как использует железо. хотя теоретически его тоже можно обрезать до виртуального устройства.
обязательно стоит посмотреть исходники com0com. это почти ваш случай, хотя тоже много избыточный вариант.
файлы операций чтения/записи там выделены, можно попробовать внедрить туда свой API, если его там еще нет)

еще есть пример в DDK/WDF DDK6001.18001srcinputvserial
это какой то простенький виртуальный порт, для эмуляции планшетов… не знаю насколько он подойдет. но имеет смысл обязательно глянуть! особенно после того как напугает объем кода предыдущих источников)

да. сразу — в винде существует два подхода написания драйвера. при помощи «чистого» DDK (начиная с win98) и с использованием WDF (начиная с XP+SP, книга Пенни Орвик).
последнее более новое, и быть может незначительно проще, но скорее всего в интернете инфа об этом пока менее распространена.

« Последнее редактирование: 29-06-2011 13:35 от Ochkarik »
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW…

Natur_Keks

Интересующийся

ru
Offline Offline


 Спасибо за помощь  Улыбаюсь.
 На данный момент есть такой замысел:
 1) непосредственно драйвер виртуального порта (как самое сложное) создаётся в Compuware DriverStudio 3.2 — там на автомате создаётся проект WDM драйвера виртуального порта (компилируется, получаем драйвер — вроде работает: через Панель Управления->Добавление Оборудования добавлял последовательный порт в систему, подсовывал этот драйвер — состояние порта в итоге «Устройство работает нормально», приложения тоже новопоявившийся порт видят).
 2) написать фильтр-драйвер (это проще, типа legacy драйвер), который будет помещаться в стек над драйвером виртуального порта, перехватывать запросы READ/WRITE и работать с моим приложением. Фильтр-драйвер должен загружаться в систему динамически — при запуске моей проги (SCM менеджер).
 Понимаю, что это костыли конечно, но вроде как реально в относительно короткие сроки. 
 


Записан
Ochkarik


если DS создает такую «рыбу»(не знал;) — то лучше конечно использовать ее, иначе чей то сторонний драйвер виртуального порта все таки придется ставить? нумега оч хорошие «рыбы» варит) до сих пор пользуюсь)

но наверное оба способа имеют право на жизнь… DS — фильтры кстати тоже генерила.
посмотрите оба проекта мельком — что больше понравится то и используйте)
но ИМХО правильнее допилить сразу виртуальный драйвер)

PS или вы имели в виду, что хотите два драйвера собрать?
можно обойтись одним виртуальным портом) фильтр лишний.

« Последнее редактирование: 30-06-2011 18:42 от Ochkarik »
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW…

Natur_Keks

Интересующийся

ru
Offline Offline


Спасибо за помощь, работа над драйвером движется, но вот возникла одна проблема:
нужно задержать обработку запроса IOCTL_READ — и если я пишу в ReadDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp):


ReadIRP = Irp;                 // сохраняем IRP (ReadIRP — глобальная переменная)
IoMarkIrpPending(Irp);         // помечаем Irp как отложенный
status = STATUS_PENDING;       // выставляем статус «Отложенный»
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);

То как мне в дальнейшем его обработать?
Вариант просто написать (в обработчике другого IOCTLa) что-то типа:


user_buf = ReadIRP->AssociatedIrp.SystemBuffer;            // указатель на сист. буфер чтения/записи отложенного запроса
Out_Len = IoGetCurrentIrpStackLocation(ReadIRP)->Parameters.Read.Length;
RtlMoveMemory(user_buf, sys_buf, Out_Len);            // sys_buf[] — буфер, где хранятся необходимые для передачи данные      
ReadIRP->IoStatus.Information = In_Len;                    // In_Len — количество передаваемых байт
ReadIRP->IoStatus.Status = STATUS_SUCCESS;                 // завершаем отложенный IRP

приводит к синему экрану
***STOP: 0x0000008E(0xC0000005, 0xF8128406, 0xB1F4A904, 0x00000000)
***Driver_COM.sys — Address F8128406 base at F8120000, DateStemp 4e1e7308

Читал про очереди (queue), не совсем понятно как этот механизм реализуется.

« Последнее редактирование: 14-07-2011 10:12 от Natur_Keks »
Записан
Ochkarik


первое не совсем верно. точнее совсем не верно.
вы должны пометить пакет как отложенный (при помощи IoMarkIrpPending) и вернуть STATUS_PENDING из диспечерской функции (буквально return STATUS_PENDING )
и только когда вы решите, что уже все сделали, то должны вызвать IoCompleteRequest для этого IRP (предварительно заполнив Irp->IoStatus.Status/ReadIRP->IoStatus.Information)

кстати там достаточно  много нюансов связанных с различными случаями….
настоятельно рекомендую к очень-очень неспешному и внимательному прочтению несколько раз Уолтера Они, 5тую главу.
там и про очереди все написано, и про обработку IRP.

« Последнее редактирование: 14-07-2011 12:40 от Ochkarik »
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW…

Serge Roussak

Новенький

by
Offline Offline


Natur_Keks, скажите, получилось ли у Вас что-нибудь по этой теме?


Записан
Natur_Keks

Интересующийся

ru
Offline Offline


получилось процентов на 70 Улыбаюсь)  то есть взял по сути готовый драйвер виртуального com порта от NuMegaStudio, добавил свой обработчик IOSTL, ещё там кое-чего, получилось из-за отсутствия опыта достаточно  криво — возможны были «подвисания драйвера»(запрос приходит, ему статус «ожидания» выставляется и не освобождается), но для той локальной задачи для которой это всё делалось — типа устроило. И так и в некоторых местах нашей родины и работает этот мой кривоватый драйвер Улыбаюсь))


Записан

  1. Aids

    Aids

    New Member

    Публикаций:

    0

    Регистрация:
    30 ноя 2007
    Сообщения:
    275

    Я пытаюсь написать собственный драйвер для RS232. В ходе поиска я выяснил что микроконтроллером COM порта можно управлять инструкциями OUT и IN. Адреса портов я узнал в дисптчере задачь. COM1 3F8-3FE; COM2 2F8-2FE; но прежде чем пересылать или принимать данные надо сконфигурировать порт. Может кто знает какие байты надо пересылать для конфигурации порта?


  2. wasm_test

    wasm_test

    wasm test user

    Публикаций:

    0

    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582

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

    ВОобще, если честно, то гугл рулит.
    НО ладно, так и быть:

    1.         Read = KiInPort ( ComPorts[ComPortNumber] );
    2.     if( !CheckComPortConnected( Port  ) )
    3.         // Port is not connected.
    4.     USHORT Multiplier = (USHORT)(COMPORT_BASEFREQ / (16 * Frequency));
    5.     WRITE_COM(Port, 0, Multiplier & 0xFF);
    6.     WRITE_COM(Port, 0, Multiplier >> 8);
    7.              // READY   BR FixParity     ParityCheck     Stop    Size
    8.     Lcr = 7; //   0     0   0               00            1       11
    9.     if (GET_COMPORT_STATE(ComPortPreferred) & COMPORT_DATAREADY)
    10.         t = READ_COM (ComPortPreferred, 0);
    11.         if (ARGUMENT_PRESENT(Byte))
    12.     if (GET_COMPORT_STATE(ComPortPreferred) & COMPORT_READER_ERROR)
    13.     while( !(GET_COMPORT_STATE(ComPortPreferred) & COMPORT_READY_TO_WRITE) )
    14.     WRITE_COM( ComPortPreferred, 0, Byte );

    Константы очевидны:

    1. #define PORT_COM1_BASE 0x3F8
    2. #define PORT_COM2_BASE 0x2F8
    3. #define COMPORT_DATAREADY           0x01
    4. #define COMPORT_OVERFLOW_READERR    0x02
    5. #define COMPORT_PARITY_READERR      0x04
    6. #define COMPORT_SYNCH_READERR       0x08
    7. #define COMPORT_READER_ERROR  
    8.             (COMPORT_OVERFLOW_READERR | COMPORT_PARITY_READERR | COMPORT_SYNCH_READERR)
    9. #define COMPORT_READER  (COMPORT_DATAREADY | COMPORT_READER_ERROR)
    10. #define COMPORT_READY_TO_WRITE      0x20
    11. #define COMPORT_WRITE_COMPLETED     0x40
    12. #define COMPORT_WRITER (COMPORT_READY_TO_WRITE | COMPORT_WRITE_COMPLETED)
    13. #define READ_COM(N,OFS) KiInPort( ComPorts[N] + (OFS) )
    14. #define WRITE_COM(N,OFS,V) KiOutPort( ComPorts[N] + (OFS), V )
    15. #define GET_COMPORT_STATE(N) READ_COM( N, 5 )
    16. #define COMPORT_BASEFREQ 1843200

    Ну и как вызывать думаю ясно. InitializeComPort(0, 117500) например


  3. Aids

    Aids

    New Member

    Публикаций:

    0

    Регистрация:
    30 ноя 2007
    Сообщения:
    275

    Great Спасибо за пример. Ты не вкурсе где можно скачать документацию по системе команд других устройств? (Например контроллеру USB порта, команды на звуковую плату)


  4. Vov4ick

    Vov4ick

    Владимир

    Публикаций:

    0

    Регистрация:
    8 окт 2006
    Сообщения:
    581
    Адрес:
    МО

    Google -> <название устройства> specification
    Полную доку по послед. порту, на русском языке я выкладывал на этом форуме, либо на коденете. Поиск по форуму рулит.


WASM

Понравилась статья? Поделить с друзьями:
  • Как написать доуле
  • Как написать досье на человека образец
  • Как написать досудебную претензию на вайлдберриз
  • Как написать досудебную претензию застройщику
  • Как написать досудебную претензию должнику юридическому лицу