Stm32 virtual com port in fs mode driver windows 7
STM Урок 33. HAL. USB. Virtual Com Port
Урок 33
HAL. USB. Virtual Com Port
Отладочную плату ипользуем ту же: STM32F4-DISCOVERY.
Проект создаём из проекта I2CLCD80. Назовем его USB_OTG_CDC. Запустим проект в Cube, включим USB_OTG_FS в режим Device_Only
В USB_DEVICE в разделе Class For FS IP выберем пункт Communication Device Class (Virtual Port Com).
Лапки портов PD4-PD7, PB8, PB9 отключим, это пережиток прошлых занятий
В Clock Configuration выберем следующие делители (нажмите на картинку для увеличения изображения)
В Configuration ничего не трогаем, т.к. прерывания там выставились сами.
Сгенерируем и запустим проект, подключим lcd.c и настроим программатор на автоперезагрузку.
Соберем проект. Прошьём контроллер. У нас появится неизвестное устройство, скачаем драйвер на наше виртуальное устройство usb. Для этого зайдем на сайт st.com, в строке поиска там вводим virtual com port, скачиваем и устанавливаем драйвер. Затем желательно зайти в папку с установленным драйвером, выбрать папку, соответствующую разрядности нашей операционной системы, и запускаем также установку и оттуда.
У нас скорей всего устройство установится с ошибкой (код 10)
Есть несколько типов решений, мне понравился именно этот, т.к. более простой: в файле usbd_cdc.h заменим размер пакета, вместо 512 напишем 256 в данной строке:
#define CDC_DATA_HS_MAX_PACKET_SIZE 256 /* Endpoint IN & OUT Packet size */
Соберём, прошьём и увидим, что ошибка исчезла.
Сначала попытаемся передать данные на ПК.
Для этого мы сначала откроем файл usbd_cdc_if.c и исправим там в 2х строчках 4 на 64
/* It’s up to user to redefine and/or remove those define */
#define APP_RX_DATA_SIZE 64
#define APP_TX_DATA_SIZE 64
В файле main.c закомментируем весь пользовательский код кроме инициализации и очистки дисплея
Также в main.c подключим файл usbd_cdc_if.h для видимости функций приема и передачи
/* USER CODE BEGIN Includes */
Немного изменим в главной функции строковую переменную, убавив в ней размер и добавив префикс tx
В файле usbd_cdc_if.c добавим прототип функции передачи, скопировав объявление из реализации данной функции в том же файле
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
В main() внесём данные в строку
В бесконечном цикле попробуем эти данные отправить в порт USB, используя функцию, прототип которой мы добавили
CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));
/* USER CODE END WHILE */
Соберём код, прошьём контроллер и посмотрим результат в терминальной программе.
Вроде передать нам что-то удалось. Теперь попробуем что-нибудь принять. Здесь чуть посложнее, т.к. для этого используется уже обработчик прерывания, коим является в файле usbd_cdc_if.c функция CDC_Receive_FS.
Добавим ещё одну строковую глобальную переменную в main()
/* USER CODE BEGIN PV */
Объявим её также и в файле usbd_cdc_if.c
/* USER CODE BEGIN PRIVATE_VARIABLES */
extern char str_rx[21];
/* USER CODE END PRIVATE_VARIABLES */
В функцию CDC_Receive_FS в этом же файле добавим некоторый код и кое-что закомментируем
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
Добавим переменную в main()
Занесенные в наш буфер данные попробуем вывести на дисплей, для этого в бесконечном цикле в функции main() добавим определённый код
CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));
Соберём проект. Прошьём код и посмотрим результат, вводя в терминальной программе и отправляя в порт USB какие-нибудь строки.
20 комментариев на “ STM Урок 33. HAL. USB. Virtual Com Port ”
«Есть несколько типов решений, мне понравился именно этот, т.к. более простой: в файле usbd_cdc.h заменим размер пакета, вместо 512 напишем 256 в данной строке….»
Просто измените размер кучи (Minimum Heap Size) в настройка CubeMX. Вместо значения 0x200 задайте 0x400.
И комп увидит устройство без ошибок.
При инициализации структур компилятору элементарно не хватает места, заданного по умолчанию, для выделения памяти.
Пардон, очепятка вышла. Не компилятору, а функции malloc.
Спасибо, так действительно проще.
Сначала не смог реализовать данный пример на SystemWorkbench в части приёма данных и передачи их из функции приёма в main посредством массива str_rx с модификатором extern – компилятор ругается на использование неопределённых переменных, а если задать ему какие-нибудь значения, то только эти заданные значения и будут передаваться. Вышел из положения объявив массив обмена str_rx в заголовочном файле usbd_cdc_if.h
Спасибо.Я сделал так.В хидер usbd_cdc_if.h добавил две строчки
extern uint8_t UserRxBufferFS[1000];
uint8_t receiveBufLen;
В метод CDC_Receive_FS добавил перед return receiveBufLen = *Len;
И в main ловил данные просто одним условием
if(receiveBufLen > 0)// если получены данные от ПК
<
HAL_Delay(250);
CDC_Transmit_FS((uint8_t*) UserRxBufferFS,receiveBufLen);
// эхо для наглядности
receiveBufLen = 0;// сброс получения
>
Всё просто,а UserRxBufferFS чистить не нужно от мусора,он сам чистится.
Здравствуйте! Спасибо огромное за ваши уроки, тут пожалуй лучший ресурс с уроками по стм32!
Хочу спросить, а как использовать CDC_Receive_FS в main.c? Я проделал в usbd_cdc_if.c «эхо», но мне нужно принимать из него и гнать дальше. Наверное вопрос больше в целом по си чем по контроллеру, а то иначе мне получается надо много всего переносить в usbd_cdc_if.c.
Думаю, что следует добавить в main.c функцию, а в файле usbd_cdc_if.c – на неё прототип и вызвать её в CDC_Receive_FS, И весь свой пользовательский код затем писать в файле main.c.
Это именно СИ. Так что обязательно подтяните свои знания по языку.
Ох, видимо сперва надо читать коментарии, прочитал тот что выше.
При переходе на USB cтолкнулся с такой проблемой. Скажем, конструкция, приведённая в примере, а именно
sprintf(str_tx,»USB Transmit\r\n»);
CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));
работает без проблем. Но, если я делаю так
sprintf(str_tx,»USB Transmit»);
CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));
CDC_Transmit_FS((unsigned char*)»\r\n», 2);
то CDC_Transmit_FS((unsigned char*)»\r\n», 2); не срабатывает (не успевает) и данные летят без переноса строки. Если ставить задержку, то работает как надо. По неопытности, может, это я и принял бы как должное, если бы перед этим не работал бы с UART где такая же конструкция работает без проблем. Для работы с UART уже написана довольно хорошая часть программы и менять её структуру очень не хочется, тем более, что данные передаются не в текстовом формате а в посылке имеется несколько меток. Что можно сделать, чтобы посылки могли идти подряд без задержки?
Скорей всего придется делать конкатенацию передаваемых строк с помощью strcat. Была аналогичная проблема при использовании CDC. Автор применял этот метод в одном из уроков.
Здравствуйте
А если я хочу передавать данные с микроконтроллера на компьютер?
Константин:
А мы их туда и передали.
Установил различные драйвера VCP от STM, но при этом плата не определяется при подключении её к компьютеру. только виден STLink Virtual COM Port. Кто уже сталкивался с такой проблемой.
Оказалась, что проблема с дровами. Надо их полностью сносить и устанавливать заново.
You can use(for example):
sprintf(str_tx,»ADC:%d \r\n»,ADC_Data);
CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));
where ADC_Data is your ADC value.
Спасибо за примеры. С USB в базовой библиотеке что-то не так. При первом подключении ком порт работает, но при передергивании USB – становится неизвестным устройством, иногда не сразу а через 5-10 секунд после повторного подключения…
Сейчас копаю в сторону функций вызываемых на отключение и подключение USB. Первое что кажется подозрительным, то что на подключение вызывается инициализация а на отключение USBD_LL_Suspend, затем на подключение снова инициализация, хотя есть USBD_LL_Resume. Пока дальнейших идей нет. Может что-то подскажете?
могу скачать драйвера для виртуального ком порта. У меня STM32F415RG, может есть у кого?
Драйвер виртуального com-порта
Скидка 5%—> Спецпредложения—> Скидка 5% Вакансии Сделать заказ Помощь в подборе Расчёт влажности Техподдержка Фото и видео Наши клиенты
25 лет на рынке контрольно-измерительных приборов
российское производство КИП
собственный научно-исследовательский центр
выгодные цены от производителя
изготовление приборов под ваши уникальные задачи
Южная промзона, проезд 4922
(Озерная аллея), строение 2
г. Москва, Зеленоград
Заполняя любую форму на сайте, вы соглашаетесь с политикой конфиденциальности.
Согласие на обработку персональных данных
Для регистрации и оформления заказа на сайте www.eksis.ru (далее – Сайт), в соответствии с Федеральным законом от 27 июля 2006 года № 152-ФЗ «О персональных данных» Пользователь дает АО «ЭКСИС» (далее – Оператор), зарегистрированному по адресу 124460, город Москва, город Зеленоград, проезд 4922-й, дом 4, строение 2, пом I, ком. 25г свое согласие на обработку любой информации, размещенной на Сайте (включая, без ограничения: сбор, систематизацию, накопление, хранение, уточнение (обновление, изменение), использование, распространение (в том числе передачу), обезличивание, блокирование, уничтожение, а также осуществление любых иных действий с персональными данными с учетом действующего законодательства РФ) и подтверждает, что давая такое согласие, Пользователь действует по своей воле и в своем интересе, а также в интересах третьих лиц.
Своим согласием Пользователь подтверждает согласие третьих лиц, информация о которых размещается на Сайте, на передачу и обработку их персональных данных и предоставляет право Оператору на осуществление любых действий в отношении персональных данных третьих лиц, которые необходимы для достижения целей обработки персональных данных, указанных в Политике обработки персональных данных.
Согласие на обработку персональных данных, загруженных на Сайт Пользователем считается полученным Оператором от Пользователя с момента выбора варианта «Зарегистрироваться», расположенного в конце формы регистрации на Сайте.
Настоящее согласие на обработку персональных данных действует до момента его отзыва Пользователем. Согласие на обработку персональных данных может быть отозвано в любое время путем направления Оператору официального запрос в порядке предусмотренным Политикой обработки персональных данных.
Оператор Системы обязуется в течение 30 (тридцати) рабочих дней с момента получения уведомления об отзыве согласия на обработку персональных данных Пользователя прекратить их обработку, уничтожить и уведомить Пользователя об уничтожении персональных данных.
Настоящее согласие распространяется исключительно на персональные данные Пользователя, размещенные на Сайте.
© 2003-2021 АО «ЭКСИС» – гигрометры, термогигрометры, газоанализаторы, анемометры и другие контрольно-измерительные приборы.
Раз у камня есть аппаратный USB, то грех им не пользоваться. Один из способов плюнуть байтом в компьютер и чтобы он при этом не очень обиделся — это организация виртуального COM-порта.
Все в железе пробовалось на камне STM32F103ZE, на аналогах тоже должно взлететь.
Забиваем.
Как я уже говорил, пока я сторонник библиотечных решений. Памяти хватает, байтовыцарапыванием заниматься рано. Так что пойдем по легкому пути.
Точные названия я привожу на случай если на сайте производителя будет какая-нибудь реорганизация и ссылки станут невалидными.
Не забываем дрова виртуального ком-порта. У меня вообще-то оно само все нашлось, но я много чего ставил от STM, может там в комплекте и пришлись.
Также нам пригодятся следующие стандарты
USB 2.0 Specification
USB CDC
В составе библиотеки есть пример как раз организации виртуального COM-порта. Правда там он сделан как мост USART-USB, но мы же не боимся трудностей?
Цель этой статьи — разобрать приложение, делающее следующее:
Поджигаем
Собираем проект из нужных нам библиотек: CMSIS, SPD, USB. Дерево проекта прилагаю.
Как обычно, самое интересное в папочке /src. Вот её-то и будем разбирать.
Неторопливо курим
Начнем с раскуривания библиотеки от STM
Эта библиотека предназначена и для connectivity-line устройств (это STM32F105/107), у них не просто USB FS, а USB OTG. Поскольку камней с OTG у меня пока нет, сконцентрируемся на простом USB FS.
В примере, который мы взяли за основу, есть куча дефайнов, как раз на случай отличить connectivity-line от других демоплат. Я эти дефайны повырезал, чтобы глаза не мозолили.
Cо всей картинки нас интересует High Layer — синенькие квадратики, которые и составляют, собственно, пользовательскую часть библиотеки. Их мы меняем под свои нужды, все остальное остается неизменным. Если заглянуть в папочку /src, то видно, что все эти файлики там и собраны.
Первая затяжка — usb_conf.h
Самые общие настройки библиотеки.
Указано сколько у нас будет endpoints (а нам их надо 4 штуки — нулевой для начального конфигурирования устройства, один для команд, один для приема и один для передачи).
Также расписаны, какие нам будут нужны коллбэки. Все взаимодействие библиотеки и пользовательской программы построено на обратных вызовах: в случае возникновения какого-либо события вызывается функция с заданным названием. А уже содержание этой функции — проблема разработчика.
Нам будет нужен SOF_CALLBACK – сигнал начала фрейма (Start Of Frame). По нему будем выплевывать то, что накопилось в буфере передачи.
Также резервируем еще два коллбэка — на прием и передачу. По приему символа будем мигать светодиодами, чтобы уж как-нибудь задействовать канал приема.
Упс, кончился файл. Короткая получилась затяжка.
Файл берем из примера, ничего не меняем.
Вторая затяжка — usb_desc.h / usb_desc.c
В этих файлах находятся дескрипторы устройства и эндпоинтов.
Информация по стандартным дескрипторам есть в стандарте USB, в разделе 9.6 Standard USB Descriptor Definitions
Специфические дескрипторы описаны в USB CDC, раздел 5 (так и называется Descriptors),
Эти все тонны текста в стандартах для того, чтобы USB стала действительно Universal. Поэтому тщательно выведена классификация устройств и интерфейсов — чтобы глянув на дескриптор хост сразу понял, что с этим делать.
Особо подробно разбирать смысла не вижу — это не характерно для STM32, это общая боль разработчиков USB устройств.
Файл берем из примеров, ничего не меняем.
Продолжение дескрипторов — usb_prop.h / usb_prop.c
В этих файлах описана таблица реакции на запросы. Все запросы к устройству пронумерованы и стандартизованы. В этих файлах определяется массивы функций Device_Property, User_Standard_Requests и просто массивы String_Descriptor, например. Это все используется ядром. Когда в устройство приходит определенный запрос, например «Выдай мне дескриптор устройства», то ядро посмотрит в таблице, какая функция обрабатывает этот запрос, вызовет эту функцию, а оно уже отработает:
Опять же, берем файл из примеров.
Прерываемся — usb_istr.h / usb_istr.c
Тоже два коротеньких файла. В них находится то, что надо вызывать при приходе прерывания от USB. Поскольку прерывание одно, то по значениям флагов определяется событие и вызывается соответствующий коллбэк.
Прерывание будет настраиваться в файле hw_config.c, обработчик выглядит очень просто:
void USB_LP_CAN1_RX0_IRQHandler(void)
<
USB_Istr();
>
его можно разместить в файлах stm32f10x_it.*, а в данном проекте, чтобы не растекаться мысью по древу, я его включил в файл main.c
И тут особо ничего не меняем, все как в примере.
Питание — usb_pwr.h / usb_pwr.c
Здесь все, что касается питания. По стандарту, устройство может быть переведено в режим спячки, тогда, если оно питается от порта, нужно позаботиться об отключении жрущей периферии. Поскольку у нас плата питается отдельно, то особого смысла в управлении питанием нет. Просто устройство формально переводится в состояние SUSPENDED.
Ничего не меняем, файл из примеров.
Коллбэки — usb_endp.c
Этот файл я переписал, поскольку у нас не будет работы с USART, как это было в примере. Приведу код с комментариями:
Работа с железом — hw_config.h / hw_config.c
В этом файле собраны функции инициализации периферии, прерываний, функции управления светодиодами и работы с буфером отправки.
USB-порт и подтяжки на моей плате сделаны по такой схеме:
И USB_EN заведен на пин PF11. Значит надо не забыть его проинициализировать и дернуть вовремя.
По сравнению с примером, выкинуты функции инициализации и работы с USART, добавлена функция мигания светодиодом.
По приему символов ‘A’, ‘B’, ‘C’, ‘D’ – зажигаются соответствующие светодиоды, ‘a’, ‘b’, ‘c’, ‘d’ – гасятся.
‘1’ и ‘0’ — соответственно зажигают и гасят все светодиоды.
Ну и все, что будет передано функции USB_Send_Data() попадает в буфер, а затем и через USB – в комп.
Уфф. С USB вроде закончили.
Теперь в головной программе можно просто вызывать USB_Send_Data() и посимвольно передавать данные в комп.
Если мы на этом остановимся, то размер кода будет порядка 11 кБ:
Более двух килобайт bss – это буферы приема и передачи. Понятное дело, их можно уменьшить.
Выдыхаем — printf()
Но мы же хотим, чтобы вывод функции printf() перенаправлялся в наш свежесозданный COM-порт. Подключаем и офигеваем от количества ошибок линковки:
А тут все просто — стандартная библиотека ввода-вывода подразумевает работу с файлами, но в больших системах есть ОС, которая собственно и занимается организацией файлов для программ пользователя. А поскольку у нас нет никакой ОС, то библиотека вполне справедливо недоумевает «А что же мне делать-то?»
Вот, чтобы это обойти, в проект включается файл newlib_stubs.c
В нем находятся функции-заглушки ко всем вышеперечисленным ошибкам. Но и кроме этого, есть одна функция, которую нам и надо переписать, чтобы весь вывод шел в USB:
Видим, что как раз и вызывается наша функция USB_Send_Data()
Все, компилим, собираем, запускаем.
Архив с проектом прилагаю — это на случай, если кто не заметит маленькие буковки внизу 🙂
Stm32 virtual com port in fs mode driver windows 7
Источники питания электронной аппаратуры, импульсные и линейные регуляторы. Топологии AC-DC, DC-DC преобразователей (Forward, Flyback, Buck, Boost, Push-Pull, SEPIC, Cuk, Full-Bridge, Half-Bridge). Драйвера ключевых элементов, динамика, алгоритмы управления, защита. Синхронное выпрямление, коррекция коэффициента мощности (PFC)
Обратная Связь, Стабилизация, Регулирование, Компенсация
Организация обратных связей в цепях регулирования, выбор топологии, обеспечение стабильности, схемотехника, расчёт
Первичные и Вторичные Химические Источники Питания
Li-ion, Li-pol, литиевые, Ni-MH, Ni-Cd, свинцово-кислотные аккумуляторы. Солевые, щелочные (алкалиновые), литиевые первичные элементы. Применение, зарядные устройства, методы и алгоритмы заряда, условия эксплуатации. Системы бесперебойного и резервного питания
Высоковольтные выпрямители, умножители напряжения, делители напряжения, высоковольтная развязка, изоляция, электрическая прочность. Высоковольтная наносекундная импульсная техника
Электрические машины, Электропривод и Управление
Электропривод постоянного тока, асинхронный электропривод, шаговый электропривод, сервопривод. Синхронные, асинхронные, вентильные электродвигатели, генераторы
Технологии, теория и практика индукционного нагрева
Системы Охлаждения, Тепловой Расчет – Cooling Systems
Охлаждение компонентов, систем, корпусов, расчёт параметров охладителей
Моделирование и Анализ Силовых Устройств – Power Supply Simulation
Моделирование силовых устройств в популярных САПР, самостоятельных симуляторах и специализированных программах. Анализ устойчивости источников питания, непрерывные модели устройств, модели компонентов
Силовые полупроводниковые приборы (MOSFET, BJT, IGBT, SCR, GTO, диоды). Силовые трансформаторы, дроссели, фильтры (проектирование, экранирование, изготовление), конденсаторы, разъемы, электромеханические изделия, датчики, микросхемы для ИП. Электротехнические и изоляционные материалы.
Интерфейсы
Форумы по интерфейсам
все интерфейсы здесь
Поставщики компонентов для электроники
Поставщики всего остального
от транзисторов до проводов
Компоненты
Закачка тех. документации, обмен опытом, прочие вопросы.
Майнеры криптовалют и их разработка, BitCoin, LightCoin, Dash, Zcash, Эфир
Обсуждение Майнеров, их поставки и производства
наблюдается очень большой спрос на данные устройства.
Встречи и поздравления
Предложения встретиться, поздравления участников форума и обсуждение мест и поводов для встреч.
Ищу работу
Предлагаю работу
нужен постоянный работник, разовое предложение, совместные проекты, кто возьмется за работу, нужно сделать.
Куплю
микросхему; устройство; то, что предложишь ты 🙂
Продам
Объявления пользователей
Тренинги, семинары, анонсы и прочие события
Общение заказчиков и потребителей электронных разработок
Обсуждение проектов, исполнителей и конкурсов
STM32. Виртуальный СОМ порт. Часть 1. Основные сведения о USB
Александр Левчук dslev@yandex.ru
Предисловие
Создание виртуального СОМ порта (USB CDC) становится первоочередной задачей, если создаваемое вами устройство нуждается в какой-либо настройке, например в установке и коррекции часов(RTC STM32F103xx).
Интерфейс USB весьма сложен в изучении, но для прикладного программиста в большинстве случаев достаточно понимать общие принципы построения интерфейса USB. Производители устройств реализуют интерфейс USB как аппаратно, так и сопровождают свои устройства драйверами и библиотеками. STMicroelectronics поставляет библиотеку CubeMX, которая позволяет легко реализовать виртуальный СОМ порт. Необходимо только наполнить готовое решение своим содержанием.
Для осознаного написания кода необходимо иметь общее представление об интерфейсе USB. В сети имеется много информации по интерфейсу USB. Однако она либо слишком обширна и требует много времени и усилий для изучения, либо содержит сведения по отдельным аспектам USB. Данная статья позволит читателю получить понимание основ USB применительно к задаче создания виртуального СОМ порта с использованием возможностей библиотеки CubeMX.
Архитектура USB
Архитектура USB строится по схеме многоярусной звезды. Компьютер (хост) имеет в своём составе концентратор USB, который называется корневой хаб. К корневому хабу подключаются периферийные устройства. Устройства могут быть простым устройством, выполняющим одну функцию, хабом или композитным устройством, имеющим несколько функций. На рисунке показана упрощённая схема многоярусной звезды. Каждый хаб является центром следующей звезды.
Устройства, функции, порты и классы USB
В USB слова функция, устройство и порт имеют специфический смысл.
Функция USB представляет собой один или набор из нескольких связанных интерфейсов, которые описывают возможности устройства. Хост определяет функции устройства, запрашивая дескриптор устройства и один или несколько дескрипторов интерфейса устройства. Дескрипторы представляют собой структуры данных, содержащие информацию об устройстве.
Устройством USB является логический или физический объект, который выполняет одну или несколько функций. Хабы и периферия компьютера являются устройствами. Устройство, содержащее несколько функций, называется композитным. Хост обрабатывает композитное устройство как отдельные физические устройства. Композитное устройство имеет один адрес шины, но несколько независимых интерфейсов, каждый из которых предоставляет определенную функцию. Интерфейсы могут использовать собственные драйверы на хосте. Например, композитное устройство может иметь интерфейсы для клавиатуры и подключения запоминающего устройства. Композитное устройство может иметь несколько конфигураций. Если устройство поддерживает несколько конфигураций, драйвер должен решить, какую конфигурацию запросить, основываясь на информации драйвера о свойствах устройства, или драйвер может запросить пользователя, что делать, или просто выбрать первую конфигурацию. Большинство драйверов выбирают первую конфигурацию. Получив запрос, устройство устанавливает запрошенную конфигурацию.
CubeMX для контроллеров STM32f103хх предоставляет возможность создания устройств следующих классов:
• Звуковые устройства (Audio Device Class).
• Виртуальный СОМ порт, класс CDC (Communication Device Class).
• Загрузчик прошивки, класс DFU (Download Firmware Update Class).
• Класс связи устройств с человеком, клавиатура, мышь и т.д. Human Interface Device Class (HID).
• Настраиваемый класс HID.
• Класс передачи данных массивами (Mass Storage Class).
Для реализации виртуального СОМ порта предоставляется драйвер, который нужно скачать с сайта STM и установить в системе обычным образом.
Конечные точки и дескрипторы устройств
Конечные точки устройства – логическое понятие. Конечная точка это буфер определенного размера для приема и/или передачи данных. Устройство обязательно имеет одну конечную точку для приема/передачи управляющей информации и возможно данных. Другие конечные точки делятся на приемные и передающие. Все конечные точки нумеруются, управляющая конечная точка всегда имеет номер нуль. Например, виртуальный СОМ порт имеет управляющую конечную точку и две конечных точки, одну для приема данных и одну для передачи данных.
• Дескриптор устройства.
• Дескриптор конфигурации.
• Дескриптор интерфейса, может быть несколько.
• Дескриптор конечной точки, может быть несколько.
Все эти виды дескрипторов должны обязательно присутствовать в USB устройстве. Конечные точки объединяются в интерфейс. Каждому интерфейсу соответствует драйвер операционной системы хоста. Некоторые устройства могут иметь несколько интерфейсов, которые могут функционировать одновременно. Несколько интерфейсов, могут объединяться в конфигурацию. У USB устройства может быть несколько конфигураций, но не может быть активными несколько конфигураций одновременно. Конфигурации могут переключаться.
Кроме базовых дескрипторов, которые являются основными, устройство может иметь и другие дескрипторы.
Обмен данными
Для реализации проекта вам не нужно знать все подробности о USB передачах, но понимание того, как выполняются передачи, может помочь в выборе типа передачи, написании прошивки устройства и при отладке.
Обмен данными всегда производится по инициативе хоста. В работе любого USB устройства, есть две различные стадии, стадия настройки (конфигурирования) и рабочий режим обмена. Конфигурирование выполняется во время перечисления и создания списка устройств. Когда перечисление завершено, хост может начать обмен данными с устройствами. Во время перечисления устройства отвечают на серию стандартных запросов из хоста. Устройство декодирует запросы и возвращает необходимую информацию хосту.
На компьютерах с ОС Windows операционная система производит перечисление устройств без программирования приложений, средствами ОС. Когда устройство подключается или отключается, менеджер Plug-and-Play (PnP) найходит INF-файл, в котором определено имя и расположение файлов драйверов для данного устройства. Если файлы доступны, процесс перечисления обычно невидим для пользователей. После того, как хост найдет устройство, и драйвер будет загружен, приложение может начаться обмен данными.
Каждая передача использует определенный формат данных, который определяется типом передачи и ее направлением. Механизм передачи данных является асинхронным и блочным. Каждая передача USB состоит из одной или нескольких транзакций, которые могут передавать данные в конечную точку или из нее.
В каждой транзакции возможен обмен только между USB устройством и хостом. Транзакция USB 2.0 начинается, когда хост отправляет пакет-маркер в шину. Пакет-маркер содержит номер конечной точки и направление передачи. Пакет IN (передача в хост) запрашивает данные у конечной точки. Пакет OUT (передача из хоста) передает данные из хоста. Помимо данных, каждый пакет данных содержит биты для проверки ошибок и идентификатор пакета (PID). Большинство транзакций также содержат завершающий пакет (handshake), в котором получатель данных сообщает об успешности или неудаче транзакции. Для транзакций USB 3.0 типы пакетов и протоколов отличаются, но транзакции содержат похожие значения адресации, проверки ошибок и последовательности данных. Рисунок отображает структуру передачи.
Пакеты
Информация по каналу передается в виде пакетов (packet). Каждый пакет начинается с поля синхронизации SYNC, за которым следует идентификатор пакета PID. Поле Check представляет собой побитовую инверсию PID. Поле EOP сигнализирует о завершении пакета.
Типы передач
Спецификация шины определяет четыре различных типа передачи данных для конечных точек.
Управляющие передачи (control transfers) — используются хостом для конфигурирования устройства во время подключения, для управления устройством и получения статусной информации в процессе работы. Протокол обеспечивает гарантированную доставку таких посылок. Длина поля данных управляющей посылки не может превышать 64 байта на полной скорости и 8 байтов на низкой. Для таких посылок хост гарантированно выделяет 10% полосы пропускания.
В управляющей передаче хост запрашивает дескрипторы устройства. Дескрипторы предоставляют информацию о возможностях устройства, что позволяет хосту назначить драйвер для устройства. Управляющие передачи осуществляются в три этапа:
1. Настройка (Setup).
2. Данные (необязательно).
3. Состояние (Status).
Передачи массивов данных (bulk data transfers) — применяются при необходимости обеспечения гарантированной доставки данных от хоста к функции или от функции к хосту, но время доставки не ограничено. Такая передача занимает всю доступную полосу пропускания шины. Пакеты имеют поле данных размером 8, 16, 32 или 64 байт. Приоритет у таких передач самый низкий, они могут приостанавливаться при большой загрузке шины. Допускаются только на полной скорости передачи. Такие посылки используются, например, принтерами или сканерами;
Передачи по прерываниям (interrupt transfers) — используются в том случае, когда требуется передавать одиночные пакеты данных небольшого размера. Каждый пакет требуется передать за ограниченное время. Поле данных может содержать до 64 байтов при передаче на полной скорости и до 8 байтов на низкой. Предел времени обслуживания устанавливается в диапазоне 1—255 мс для полной скорости и 10—255 мс — для низкой. Такие передачи используются в устройствах ввода, таких как мышь и клавиатура;
Изохронные передачи (isochronous transfers) — применяются для обмена данными в «реальном времени», когда на каждом временном интервале требуется передавать строго определенное количество данных, но доставка информации не гарантирована (передача данных ведется без повторения при сбоях, допускается потеря пакетов). Такие передачи занимают предварительно согласованную часть пропускной способности шины и имеют заданную задержку доставки. Изохронные передачи обычно используются в мультимедийных устройствах для передачи аудио и видеоданных. Изохронные передачи разделяются по способу синхронизации конечных точек с системой, различают асинхронный, синхронный и адаптивный классы устройств, каждому из которых соответствует свой тип канала USB.
Данные драйвера в диспетчере устройств и регистре
При подключении нового устройства хост должен определить, какой драйвер необходимо назначить данному устройству. Рассмотрим, как диспетчер устройств и системный регистр сохраняют информацию об устройствах и как Windows выбирает драйвер для устройства.
Диспетчер устройств
Диспетчер устройств хранит информацию о всех устройствах компьютера, как подключенных в данный момент, так и отключенных. Диспетчер устройств может быть вызван из «панель управления/система» и позволяет увидеть устройства в нескольких режимах. Просмотр устройств по типу показывает устройства, группируемые по выполнимым функциям. Просмотр устройств по подключению показывает физическое соединение устройства с каждым хост контроллером, корневым хабом и любыми дополнительными хабами, подключенными к устройству. По умолчанию диспетчер устройств показывает только подключенные устройства, для просмотра устройств, которые удалены, но имеют установленные драйверы, следует в меню диспетчера выбрать пункт «Показать скрытые устройства».
Каждое устройство в диспетчере устройств имеет свою страницу свойств, где можно увидеть всю дополнительную информацию об устройстве, пример для виртуального СОМ порта показан на рисунке.
Информация об устройствах в регистре
В регистре сохраняется информация о USB устройствах, которые были установлены, включая не подключенные устройства. После перечисления устройств, часть информации регистр получает от шины USB и часть информации регистр получает из файла INF при назначении драйвера устройству. Информация об устройствах сохраняется в регистре под ключом HKEY_LOCAL_MACHINE\SYSTEM. Данные о USB устройствах хранятся в соответствующих подключах Enum\USB key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB
Под данным ключом хранится информация обо всех, когда-либо участвующих в перечислении, устройствах USB. Устройства перечисляются по идентификаторам Vendor ID и Product ID. На рисунке ниже показан ключ для виртуального порта USB. Иногда можно заметить, что под одним и тем же ID есть две записи для порта СОМ (USB), первая запись для СОМ7 правильная, а например, вторая для СОМххх неправильная, возникшая в процессе отладки прошивки контроллера. Также много записей для порта СОМ возникает в процессе подключения и отключения различных устройств, которые имеют виртуальный СОМ порт. Порты СОМ нумеруются системой, если есть аппаратный порт, он всегда появляется, как СОМ1, виртуальным портам присваиваются номера в зависимости от номера порта USB и числа подключаемых устройств. Каждому подключаемому новому устройству, имеющему виртуальный СОМ порт, присваивается свой номер. Максимальный номер порта может достигать значения 256. Однажды может возникнуть ситуация, когда при подключении устройства, программа управления данным устройством не сможет определить СОМ порт, поскольку его номер будет выходить за диапазон предусмотренный программой. Искать и удалять ненужные записи долго и сложно, можно ошибиться. Для облегчения задачи существует хорошая утилита USBDeview, позволяющая просмотреть все свойства устройств, подключить, отключить или легко удалить ненужные устройства с удалением записей в реестре.
Ключ класса
Под ключом HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class сохраняется информация об устройстве, полученная при установке. Подключи для каждого устройства, именуются по GUID. Каждый подключ может иметь папку свойств (Properties), которая недоступна для просмотра даже под правами администратора. Зачастую эта папка пустая, для ее просмотра следует изменить права доступа. На рисунке ниже показан ключ для портов, папка свойств для портов пустая.
Кроме папки свойств каждый ключ устройства может иметь ключи драйверов устройств, которые маркируются четырьмя цифрами, начиная с 0000. На рисунке показан ключ драйвера для виртуального СОМ порта.
Сервисный ключ
Сервисный ключ содержит информацию о драйвере и располагается в ветке HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services. Сервисный ключ существует для каждого типа контроллера и хаба хоста. На рисунке ниже показан ключ реестра для виртуального СОМ порта.
Файл INF
Файл INF является текстовым файлом, содержащий информацию об устройстве или устройствах, которая используется в процессе установки драйвера устройства. Поставщик драйвера устройства должен также обеспечить поставку файла INF.
При установке драйвера Windows определяет, имеет ли файл каталога (.cat) цифровую подпись. Цифровая подпись позволяет Windows проверить, что файлы драйвера не были изменены с момента подписания драйвера, и идентифицировать источник или издателя драйвера. Файлы INF считаются элементами драйверов устройств. Любое изменение в файле INF, включая редактирование или добавление идентификатора продукта, требует новой цифровой подписи для файла каталога. Получение цифровой подписи для драйвера требует тестирования и уплаты пошлины. Однако многие USB устройства могут использовать системные драйверы или другие драйверы с цифровой подписью, а также файлы INF.
Структура файла
Содержимое файла INF соответствует определенным правилам:
Ниже показан пример файла INF, поставляемый STM32 с драйвером виртуального СОМ порта.
; STMicroelectronics Comunication Device Class driver (CDC) INF FILE