Инициатива STMCube™ была разработана компанией STMicroelectronics (далее просто ST) для упрощения жизни разработчикам в процессе разработки, снижая их усилия, время и цену работ. Библиотека STM32Cube версии 1.x включает:
• STM32CubeMX, графическая утилита конфигурирования, которая позволяет генерировать код инициализации на языке C. это делается с помощью графических визардов.
• Продвинутая программная платформа, нацеленная на каждую из серий микроконтроллеров (такую как STM32CubeF4 для серии STM32F4).
– STM32Cube HAL, слой абстракции встроенного программного обеспечения, гарантирующий максимальное портирование между семействами STM32. – Набор промежуточных программных компонентов, таких как RTOS, стеки USB, TCP/IP, графические библиотеки. – Все встраиваемое программное обеспечение поставляется с полным набором примеров.
Шина USB - самое полезное в истории персональных компьютеров средство для подключения различных устройств, таких как мышь, геймпады, джойстики, сканеры, принтеры, цифровые камеры и т. д. USB также встраивается в большинство потребительской и мобильной электроники.
Это руководство (перевод UM1734 [1]) описывает библиотеку устройств USB STM32Cube, которая входит как часть в пакет STM32Cube. Этот пакет можно бесплатно загрузить с сайта ST (http://www.st.com/stm32cube). Здесь описывается, как начать разрабатывать и реализовать приложения устройства USB основных классов (HID, MSC, Audio, CDC...) на базе стека устройства USB, поддерживаемого всеми сериями микроконтроллеров STM32.
Примечание: этот документ применим ко всем сериям STM32, которые имеют на борту периферийное устройство USB. Однако для упрощения изложения в качестве образцовой платформы выбрана разновидность микроконтроллеров STM32F4xx и пакет STM32CubeF4. Чтобы получить дополнительную информацию по примерам реализации на Вашем STM32, обратитесь к файлу readme, предоставленному в соответствующем пакете STM32Cube.
API Application Programming Interface (программный интерфейс доступа к функциям библиотеки).
BOT Bulk Only Transfer, передача только блоками.
CBW Command Block Wrapper, блок команды SCSI, который содержит информацию длины команды, направление, логический юнит (LUT), куда отправляется команда, и уникальный идентификатор, который будет возвращен в ответ от устройства, который может использоваться для проверки соответствия ответа запросу хоста. Command Block Wrapper отправляется устройству с использованием первого направления Out конечной точки Block интерфейса перед тем, как любые данные будут отправлены устройству или приняты из него. Затем хосту устройством отправляется финальный CSW, содержащий результаты операции.
CDC Communication Device Class.
CSW Command Status Wrapper, блок протокола SCSI.
DFU Device Firmware Upgrade, класс и протокол для обновления программного обеспечения (firmware) встраиваемого устройства.
firmware встраиваемое программное обеспечение микроконтроллера, так называемая "прошивка".
FS Full Speed, полная скорость (12 мегабит/сек).
HAL Hardware Abstraction Layer, программный уровень библиотек (драйверов) для абстрагирования от версии аппаратуры.
HCD Host Controller Driver.
HID Human Interface Device.
HS High Speed, высокая скорость (480 мегабит/сек).
HSI high-speed internal oscillator, внутренний генератор на 8 МГц.
I2C популярная последовательная шина для обмена данными в электронной аппаратуре.
I2S Inter-IC Sound, последовательный стандартный интерфейс для соединения друг с другом звуковых устройств. Альтернативно вместо I2S используют аббревиатуру IIS.
LBA Logical Block Address.
LUN Logical Unit, термин протокола SCSI.
Mbps Megabit per second, мегабит/сек.
MCU MicroController Unit, микроконтроллер.
MSC Mass Storage Class, класс устройства хранения данных. Иногда этот класс называют аббревиатурой MSD (Mass Storage Device).
MSP MCU Support Package.
MUN Max Unit Number, максимальный номер LUN.
OTG On-The-Go: периферийное устройство, поддерживающее OTG, может на лету переключаться между ролями HOST/DEVICE.
• USB Host library user manual (UM1720), руководство библиотеки реализации хоста USB. • Описание драйверов STM32F4xx HAL (UM1725), где можно найти описания двух стандартных драйвера (HCD для хоста и PCD для устройства).
[Внешние ссылки]
• Universal Serial Bus Specification, Revision 2.0, http: //www.usb.org • USB device class specifications (Audio, HID, MSC, etc.), http://www.usb.org
[Описание библиотеки устройства USB]
ST предоставляет своим клиентам новые стеки USB (стек устройства и стек хоста) которые поддерживают все STM32 MCU, вместе с многими инструментами разработки, такими как Atollic® TrueSTUDIO, IAR Embedded Workbench for ARM® и Keil uVision®.
Этот документ фокусируется на стеке устройства USB. Для стека хоста обратитесь к соответствующему руководству.
Библиотека устройства USB является стандартной для всех микроконтроллеров STM32, и только слой HAL адаптируется для каждого отдельного устройства STM32.
Библиотека устройства USB работает поверх HAL-драйвера STM32Cube для USB устройства, и предоставляет все необходимое API для разработки приложения устройства USB. Представленный документ описывает промежуточный модуль библиотеки STM32Cube устройства USB, и иллюстрирует, как пользователь может с помощью этого модуля просто разработать собственное приложение устройства USB.
Библиотека устройства USB является частью пакета STM32Cube для каждой серии STM32. Она содержит:
• Низкоуровневый драйвер USB. • Драйверы общеизвестных классов USB. • Набор приложений для большинства классов устройства USB, поддерживающих типы передач USB Full speed и High speed (control, interrupt, bulk и isochronous).
Библиотека устройства USB предоставляет как минимум по одному демонстрационному примеру firmware для каждого типа передач USB:
• Human Interface Device HID. Демонстрируется HID-джойстик, основанный на оценочных платах (EVAL board), также есть примеры пользовательского устройства (Custom HID example). • Audio streaming. Звуковое устройство для потоковых аудиоданных. • Communication Device (CDC), коммуникационное устройство. Мост VCP USB-RS232 для реализации виртуального COM-порта. • Mass storage. Демонстрируется устройство хранения на основе карты microSD, слот для которой есть на платах EVAL. • Device Firmware Upgrade, обновление прошивки. Устройство DFU предназначено для загрузки и выгрузки firmware. • Dual Core devices demonstration. Демонстрационные примеры сдвоенных устройств, основанные на mass storage + HID и mass storage + CDC.
Рассматриваются следующие темы:
• Архитектура библиотеки устройства USB. • Описание библиотеки устройства USB. • Обзор машины состояний библиотеки устройства USB. • Обзор классов устройства USB.
Функции библиотеки. Основные функции библиотеки устройства USB:
• Поддержка функции многопакетной передачи, что позволяет отправлять большое количество данных без разделения из на пакеты максимально допустимого размера. • Поддерживает до трек back-to-back передач на управляющих контрольных точках, control endpoints (совместимо с контроллерами OHCI). • Конфигурационные файлы для изменения настроек ядра и библиотек без изменения самого кода библиотеки (Read Only). • Структуры с выравниванием данных на 32 бита (4 байта), чтобы обрабатывать передачи на основе DMA в режимах High speed. • Поддерживаются несколько экземпляров ядра USB OTG из уровня пользователя (конфигурационный файл).
Замечание: библиотека устройства USB может использоваться как вместе с RTOS, так и отдельно; используется обертка (CMSIS RTOS wrapper) для реализации абстракции с ядром операционной системы. Примеры устройства USB не отображают сообщения лога.
Рис. 1. STM32Cube USB device library (библиотека устройства USB).
На рисунке выше приложение пользователя показано зеленым цветом, ядро библиотеки USB желтым и драйвер USB Device HAL синим.
[Архитектура библиотеки устройства USB]
Библиотека устройства USB разделена на три основных слоя. Приложение разрабатывается над самым верхним слоем, как показано на рис. 2.
Рис. 2. Архитектура USB device library.
На этом рисунке блоки ядра библиотеки USB показаны желтым цветом, конфигурация устройства USB (USB Device Configuration) фиолетовым, и синим показан драйвер USB HAL.
Первый слой состоит из драйверов ядра и драйверов класса USB.
Драйверы ядра (Core drivers). Ядро библиотеки составлено из 4 основных блоков:
– Модуль ядра USB, который предоставляет полный набор API для управления внутренним состоянием библиотеки машины устройства USB и процессами обратных вызовов (callback) из прерываний USB. – Модуль обработки запросов USB (в соответствии с Главой 9 стандарта USB). – Модуль обработки низкоуровневых запросов ввода/вывода USB. – Модуль лога и отладки USB, который настраивается на уровень вывода отладочных сообщений макросом USB_DEBUG_LEVEL. Модуль выводит сообщения пользователя, лога, ошибок и отладки.
Драйверы класса. Классы устройств USB представлены набором драйверов, которые могут быть состыкованы с ядром USB через подпрограмму USBD_RegisterClass().
Библиотека устройства USB это стандартный стек, совместимый с USB 2.0 и со всеми ядрами STM32 USB. Он может быть просто состыкован с любым драйвером USB HAL благодаря конфигурационному файлу обертки, который обходит зависимости между библиотекой USB и драйверами низкого уровня.
[Слой USB OTG HAL]
Рис. 3. Обзор архитектуры драйвера.
Архитектура драйвера:
• Нижний слой (Low Layer USB driver) предоставляет общее API для режимов устройства и OTG. Он выполняет инициализацию ядра в каждом режиме и управляет потоком передач. • Слой Peripheral Controller Driver (PCD) предоставляет API для доступа в режиме устройства, и главную подпрограмму прерывания для этого режима. • Слой драйвера контроллера OTG предоставляет API для доступа в режиме OTG главную подпрограмму прерывания для этого режима.
Примечание: для дополнительной информации по использованию драйвера PCD пожалуйста обратитесь к документу UM1725, где описаны все вызовы API драйвера PCD.
[Программирование драйвера USB]
Конфигурирование структуры драйвера, инициализация.
Инициализация устройства. Устройство инициализируется использованием следующей функции, содержащейся в файле stm32fxxx_hal_pcd.c:
Конфигурация конечной точки. Как только ядро USB инициализировано, верхний слой может вызвать драйвер низкого уровня, чтобы открыть или закрыть активную конечную точку с целью перемещения данных. Могут использоваться следующие 2 API-вызова:
Здесь ep_addr, ep_mps и ep_type это адрес конечной точки, максимум передачи данных и тип передачи соответственно.
Структура ядра устройства. Основная структура, используемая в библиотеке устройства, это дескриптор устройства (device handle) типа USBD_HandleTypedef:
Глобальная структура устройства USB содержит все переменные и структуры, чтобы хранить информацию реального времени, относящуюся к устройству, а также для хранения состояний машины управления передачами(control transfer state machine), и информации/статуса конечной точки.
В этой структуре dev_config хранит текущую конфигурацию устройства USB, и ep0_state управляет машиной, которая принимает следующие состояния:
/* Состояние управляющей конечной точки (EP0 State) */
#define USBD_EP0_IDLE 0
#define USBD_EP0_SETUP 1
#define USBD_EP0_DATA_IN 2
#define USBD_EP0_DATA_OUT 3
#define USBD_EP0_STATUS_IN 4
#define USBD_EP0_STATUS_OUT 5
#define USBD_EP0_STALL 6
В этой структуре dev_state определяет соединение, конфигурацию и состояние питания:
/* Состояние устройства */
#define USBD_DEFAULT 1
#define USBD_ADDRESSED 2
#define USBD_CONFIGURED 3
#define USBD_SUSPENDED 4
Спецификация USB определяет 6 состояний устройства USB:
Attached: устройство подключено к шине USB, однако не получает питание. Powered: устройство подключено к шине USB и получает питание, однако пока не получило никакой запрос сброса (reset request). Default: устройство подключено к USB. Оно запитано и сброшено, однако ему не был назначен уникальный адрес. Address: устройство подключено к USB, запитано и сброшено, и получило уникальный адрес. Configured: устройство уже находится в адресованном состоянии и сконфигурировано. Это не состояние приостановки (suspend). Suspended: устройство подключено и сконфигурировано, но как минимум 3 мс по шине не было обнаружено связанной с ним активности.
Поток перемещения данных USB. Слой PCD предоставляет все API-вызовы, которые требуются для запуска и управления потоком передачи. Это делает следующий набор функций:
Слой PCD содержит одну функцию, которая должна быть вызвана прерыванием USB:
voidHAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd);
Файл stm32fxxx_hal_pcd.h содержит прототипы функций, вызываемых из слоя ядра библиотеки, чтобы обработать события USB.
Почти все библиотечные функции возвращают состояние типа USBD_StatusTypeDef. Приложение пользователя должно всегда проверять возвращенное состояние. Ниже показано определение этого типа (перечисление значений), и в таблице 3 описаны возможные возвращаемые состояния.
Будет возвращено, когда операция завершилась успешно.
USBH_BUSY
Будет возвращено, когда операция еще не завершилась (устройство занято).
USBH_FAIL
Будет возвращено, когда операция потерпела неудачу из-за низкоуровневой ошибки или ошибки в обработке протокола.
[Обзор библиотеки устройства USB]
Библиотека устройства USB основана на стандартном драйвере USB низкого уровня. ПО было разработано для поддержки режимов Full speed и High speed.
Реализована машина состояний устройства USB, как это было определено спецификацией USB 2.0. Библиотечные функции находятся в файлах папки Core из пакета USB device library firmware package (см. рис. 5). Модули класса USB (папка Class) разработаны для обеспечения совместимости со спецификацией протокола.
Рис. 5. Структура каталогов библиотеки устройства USB.
Обработка control endpoint. Спецификация USB определяет 4 типа передач: control, interrupt, bulk и isochronous. Хост USB отправляет запросы к устройству через управляющую точку, control endpoint (в этом случае control endpoint является конечной точкой с номером 0). Запросы отправляются в устройство как пакеты SETUP. Эти запросы можно классифицировать на 3 категории: standard, class-specific и vendor-specific. Поскольку стандартные запросы являются общими для всех видов устройств USB, библиотека принимает и обрабатывает все стандартные запросы на control endpoint 0.
Формат и смысл специфичных для класса запросов и специфичных для вендора запросов не совпадают для всех устройств USB.
Все запросы SETUP обрабатываются в машине состояний, реализованной в модели прерывания. Прерывание генерируется по окончании корректной передачи USB. Код библиотеки принимает это прерывание. В подпрограмме обработки прерывания (ISR) идентифицируется триггер конечной точки. Если событие это настройка (setup) на endpoint 0, то полезная нагрузка принятой настройки сохраняется, и запускается машина состояний.
Транзакции на других конечных точках. Ядро, специфическое для класса, использует конечные точки, не относящиеся к конечной точке управления путем вызова набора функций для отправки или приема данных через callback-стадии data IN и data OUT.
Структура данных для пакета SETUP. Когда поступает новый пакет SETUP, все 8 байт пакета SETUP копируются во внутреннюю структуру USB_SETUP_REQ req, чтобы во время обработки следующий пакет SETUP не мог перезаписать предыдущий. Эта внутренняя структура определена следующим образом:
Стандартные запросы. Большинство запросов спецификации USB, показанных в таблице 4, обрабатываются библиотекой как стандартные. Таблица 4 перечисляет все эти стандартные запросы и их допустимые в библиотеке параметры. Запросы, которых нет в таблице 4, считаются нестандартными.
Таблица 4. Стандартные запросы USB.
Комментарии
CLEAR_FEATURE
A, C
00
01
00
00
00
00
Очищает функцию remote wakeup устройства.
C
02
00
00
EP
00
00
Очищает состояние STALL конечной точки EP. EP не относится к EP0.
SET_FEATURE
A, C
00
01
00
00
00
00
Устанавливает функцию remote wakeup устройства.
C
02
00
00
EP
00
00
Устанавливает состояние STALL конечной точки EP. EP не относится к EP0.
SET_ADDRESS
D, A
00
N
00
00
00
00
Устанавливает адрес устройства, N допустимый адрес устройства.
GET_DESCRIPTOR
Все сост.
80
00
01
00
00
не 0
Получает дескриптор устройства.
80
N
02
00
00
не 0
Получает дескриптор конфигурации, где N допустимый индекс конфигурации.
80
N
03
LangID
не 0
Получает строковый дескриптор, где N допустимый индекс строки. Этот запрос допустим только когда поддерживается строковый дескриптор.
GET_CONFIGURATION
A, C
80
00
00
00
00
1
Получает конфигурацию устройства.
SET_CONFIGURATION
A, C
80
N
00
00
00
00
Устанавливает конфигурацию устройства, где N допустимый номер конфигурации устройства.
GET_INTERFACE
C
81
00
00
N
00
1
Получает альтернативную настройку интерфейса. Здесь N допустимый номер интерфейса.
SET_INTERFACE
C
01
M
00
N
00
00
Устанавливает альтернативную установку N интерфейса M. Здесь N это допустимый номер интерфейса, M это допустимая альтернативная установка интерфейса N.
Примечание: в столбце State применены следующие обозначения состояний. D = Default state (состояние по умолчанию), A = Address state (состояние адресации), C = Configured state (состояние "сконфигурировано"). Значение EP: D0-D3 = адрес конечной точки, D4-D6 = эти биты зарезервированы как нули, D7 = 0: OUT endpoint, 1: IN endpoint.
Нестандартные запросы. Все нестандартные запросы через callback-функции передаются в код, специфичный для класса.
• SETUP stage
Библиотека передает все нестандартные запросы в специфичный для класса код через callback-функцию pdev->pClass->Setup (pdev, req).
Нестандартные запросы включают интерпретируемые пользователем запросы и неправильные запросы (invalid requests). Интерпретируемые пользователем запросы это запросы, специфические для класса, специфические для вендора или запросы, которые библиотека считает недопустимыми (invalid), так что приложение может захотеть обработать их для себя как допустимые.
Invalid-запросы это такие запросы, которые не являются стандартными, и поэтому не могут быть интерпретированы библиотекой. Поскольку pdev->pClass->Setup (pdev, req) вызывается после SETUP stage и перед DATA stage, то код пользователя в pdev->pClass->Setup (pdev, req) отвечает за парсинг содержимого пакета SETUP (req). Если запрос недопустим, то код пользователя должен вызвать USBD_CtlError(pdev, req) и вернуть управление в код, который вызвал pdev->pClass->Setup (pdev, req).
Для запроса, интерпретируемого пользователем, код пользователя подготавливает буфер данных для последующего DATA stage, если в запросе есть стадия данных; иначе пользовательский код выполнит запрос и вернет управление в код, который вызывал pdev->pClass->Setup (pdev, req).
• DATA stage
Слой класса использует стандартные USBD_CtlSendData и USBD_CtlPrepareRx для отправки или приема данных. Поток переноса данных обрабатывается внутренним кодом библиотеки, и пользователю не нужно делить данные в пакеты размера ep_size.
• Status stage
Стадия статуса обрабатывается библиотекой после возврата из callback-функции pdev->pClass->Setup (pdev, req).
Рис. 7. Обработка в библиотеке устройства USB.
Примечание: красный текст идентифицирует конфигурацию устройства USB.
Как показано на рис. 7, для программирования USB нужны только следующие модули: библиотека USB, класс устройства USB и основное приложение.
Главное приложение выполняет программу пользователя. Модули main.c, stm32fxx_it.c, usbd_conf.c и usbd_desc.c вместе с их заголовочными файлами - все, что пользователю нужно для разработки своего собственного приложения. Пользователь может изменить из в соответствии с требованиями своего приложения (драйвер класса).
Делаются только простые API-вызовы. Они позволяют установить взаимосвязь между слоем приложения и модулем библиотеки USB, который обрабатывает инициализацию USB и получает текущее состояние USB.
Чтобы инициализировать драйвер USB HAL, библиотеку устройства USB и аппаратуру на используемой плате (BSP), и запустить библиотеку, приложение пользователя должно сделать 3 вызова API:
• USBD_Init(): эта функция инициализирует стек устройства и загружает драйвер класса. Дескриптор устройства сохраняется в файлах usbd_desc.c и usbd_desc.h (используется для конфигурации типа дескриптора). • USBD_RegisterClass(): эта функция привязывает драйвер класса к ядру устройства. • USBD_Start(): эта функция позволяет запустить ядро устройства USB.
Например, пользователь может добавить дополнительные конечные точки в файле usbd_conf, в зависимости от требований класса. Это делается вызовом функции USBD_LL_Init(). В переменной dev_endpoints должно содержаться количество требуемых конечных точек по спецификации класса USB.
Благодаря файлу usbd_conf.h библиотека устройства USB предоставляет несколько конфигураций (для дополнительной информации см. далее секцию "Конфигурирование firmware библиотеки устройства USB").
Замечание: инициализация библиотеки HAL осуществляется вызовом HAL_Init() API в модуле stm32fxxx_hal.c. Эта функция выполняет следующие операции:
- Сбрасывает все периферийные устройства. - Конфигурирует выборку инструкций и кэш (Flash prefetch, Instruction cache, Data cache). - Разрешает SysTick и конфигурирует тик 1 мс (такты по умолчанию после Reset HSI).
Поток данных устройства USB. Библиотека USB (USB core и слой USB class) обрабатывают данные на конечной точке 0 (EP0) через слой запроса I/O, когда необходима обертка для управления функцией multi-packet на control endpoint, или напрямую из слоя stm32fxxx_hal_pcd, когда используются другие конечные точки, поскольку ядро USB OTG поддерживает функцию multi-packet. Рис. 8 показывает эту схему потока данных.
Рис. 8. Схема потока данных в устройстве (USB device data flow).
Интерфейс ядра с драйвером низкого уровня. Как упоминалось ранее, библиотека устройства USB подключается к низкоуровневому драйверу STM32Cube™ HAL с помощью слоя низкоуровневого интерфейса, который действует как слой соединения (link layer) с STM32Cube™ HAL.
Этот низкоуровневый интерфейс реализует API-функции низкого уровня и вызывает некоторые callback-функции ядра библиотеки при некоторых событиях USB.
В пакете кода STM32Cube™ реализация низкоуровневого интерфейса предоставлена как часть примеров устройства USB, поскольку некоторые части низкоуровневого интерфейса зависят от платы и системы.
Таблица 5 перечисляет низкоуровневые функции API.
Таблица 5. Описание API низкого уровня.
Функция
Описание
USBD_LL_Init
Инициализация низкого уровня.
USBD_LL_DeInit
Отмена инициализации низкого уровня.
USBD_LL_Start
Запуск низкого уровня.
USBH_LL_Stop
Остановка низкого уровня.
USBD_LL_OpenEP
Инициализация конечной точки.
USBD_LL_CloseEP
Закрытие конечной точки и отмена инициализации её состояния.
USBD_LL_FlushEP
Сбрасывает (flush) данные в конечной точке драйверу низкого уровня.
USBD_LL_StallEP
Устанавливает состояние STALL на конечной точке для драйвера низкого уровня.
USBD_LL_ClearStallEP
Очищает состояние STALL на конечной точке для драйвера низкого уровня.
USBD_LL_IsStallEP
Возвращает информацию, находится ли конечная точка в состоянии STALL.
USBD_LL_SetUSBAddress
Назначает адрес устройству USB.
USBD_LL_Transmit
Передает данные через конечную точку.
USBD_LL_PrepareReceive
Подготавливает конечную точку к приему данных.
USBD_LL_GetRxDataSize
Вернет размер данных последнего принятого пакета.
Примечание: это API предоставлено файлов конфигурации устройства USB (usbd_conf.c). Оно должно быть реализована в файлах пользователя и адаптировано для драйвера контроллера устройства USB (USB Device Controller Driver). Пользователь может начать создавать свой файл конфигурации, беря в качестве примера файл usbd_conf.c из пакета STM32Cube™. Этот файл можно также скопировать в папку приложения и изменить в зависимости от требований приложения.
Модель интерфейса библиотеки устройства USB. Библиотека устройства USB построена вокруг стандартных центральных портируемых модулей класса.
Рис. 9. Модель интерфейса библиотеки устройства USB.
Таблица 6 показывает все callback-функции библиотеки устройства, которые вызываются из низкоуровневого интерфейса в ответ на некоторые события USB.
Таблица 6. Callback-функции событий низкого уровня.
Функция
Описание
HAL_PCD_ConnectCallback
Событие подключения устройства USB к шине.
HAL_PCD_DataInStageCallback
Стадия Data IN.
HAL_PCD_DataOutStageCallback
Стадия Data OUT.
HAL_PCD_DisconnectCallback
Событие отключения устройства USB.
HAL_PCD_ISOINIncompleteCallback
Событие незавершенной изохронной транзакции IN (сокращенно ISO IN).
HAL_PCD_ISOOUTIncompleteCallback
Событие незавершенной изохронной транзакции OUT (сокращенно ISO OUT).
HAL_PCD_ResetCallback
Событие сброса по шине USB.
HAL_PCD_ResumeCallback
Событие возобновления работы.
HAL_PCD_SetupStageCallback
Событие стадии настройки.
HAL_PCD_SOFCallback
Событие начала фрейма (Start Of Frame, SOF).
HAL_PCD_SuspendCallback
Событие приостановки работы.
Конфигурирование firmware библиотеки устройства USB. The USB device library can be configured using the usbd_conf.h file.
Файл usbd_conf.h - специальный конфигурационный файл, используемый для определения некоторых глобальных параметров и специальных конфигураций. Этот файл используется для подключения библиотеке верхнего уровня вместе с драйверами HAL и драйверами BSP.
Таблица 7. Конфигурация библиотеки USB.
Конфигурация
Параметр
Описание
Общая
USBD_MAX_NUM_CONFIGURATION
Максимальное количество поддерживаемых конфигураций [1..255].
USBD_MAX_NUM_INTERFACES
Максимальное количество поддерживаемых интерфейсов [1..255].
USBD_MAX_STR_DESC_SIZ
Максимальный размер строковых дескрипторов [uint16].
USBD_SELF_POWERED
Разрешает функцию самостоятельного питания [0/1].
USBD_DEBUG_LEVEL
Уровень вывода сообщений отладки и лога.
USBD_SUPPORT_USER_STRING
Разрешает поддержку строк пользователя [0/1].
MSC_MEDIA_PACKET
Размер буфера ввода/вывода носителя, делящийся нацело на 512 [от 512 байт до 32 килобайт].
HID
-
Недоступно.
DFU
USBD_DFU_MAX_ITF_NUM
Максимальный номер интерфейса носителя [1..255].
USBD_DFU_XFER_SIZE
Размер буфера ввода/вывода носителя, делящийся нацело на 512 [от 512 байт до 32 килобайт].
USBD_DFU_APP_DEFAULT_ADD
Адрес приложения (0x0800C000).
CDC
-
Недоступно.
Audio
USBD_AUDIO_FREQ
Частота дискретизации 8..48 кГц.
Примечание: пользователь может начать работу с файла usbd_conf.c, предоставленного в пакете STM32Cube™. Этот файл также может быть скопирован в папку разрабатываемого приложения, и изменен в зависимости от нужд приложения.
По умолчанию для примеров устройств USB библиотечные и пользовательские сообщения не отображаются на LCD. Однако пользователь может реализовать свои собственные сообщения. Для перенаправления библиотечных сообщений на экран LCD к фалам исходного кода приложения должен быть добавлен драйвер lcd_log.c. Он может выбрать, какие сообщения отображать, путем изменения значений #define в конфигурационном файле usbd_conf.h, который должен находиться среди подключаемых файлов проекта. Например:
0: не выводить сообщения лога/отладки. 1: разрешены сообщения лога. 2: разрешены сообщения и лога, и отладки.
Функции управления USB
Device reset. Когда устройство получает сигнал сброса от шины USB, библиотека сбрасывает и инициализирует и программное обеспечение, и аппаратуру приложения. Эта функция - часть подпрограммы обработки прерывания.
Device suspend. Когда устройство определяет состояние (suspend condition) приостановки на шине USB, библиотека останавливает все происходящие операции и переводит систему в состояние приостановки, suspend state (если разрешен режим пониженного энергопотребления в файле usbd_conf.c).
Device resume. Когда устройство определяет сигнал возобновления работы (resume) на шине USB, библиотека восстанавливает тактирование ядра USB и переводит систему в состояние ожидания, idle state (если разрешен режим пониженного энергопотребления в файле usbd_conf.c).
[Функции библиотеки устройства USB]
В папке Core содержатся машины библиотеки устройства USB, как это определено в спецификации USB ревизии 2.0.
Таблица 8. Файлы ядра устройства USB.
Файлы
Описание
usbd_core.c, usbd_core.h
Функции для обработки всех коммуникаций и машины состояния.
usbd_req.c, usbd_req.h
Реализация запросов, перечисленных в Главе 9 спецификации стандарта USB.
usbd_ctlreq.c, usbd_ctlreq.h
Обработка результатов транзакций USB.
usbd_conf_template.c, usbd_conf_template.h
Шаблон для низкоуровневого интерфейса, должен быть переделан пользователем и подключен к проекту приложения.
usbd_def.c, usbd_def.h
Общие определения библиотеки.
Папка Class содержит все файлы, относящиеся к реализации класса, и они соответствуют спецификации протокола этих классов.
Таблица 9. Файлы драйверов классов устройств USB.
Класс USB
Файлы
Описание
MSC (устройство хранения данных)
usbh_msc.c, usbh_msc.h
Handler класса MSC.
usbh_msc_bot.c, usbh_msc_bot.h
Handler протокола транзакций Bulk-only.
usbh_msc_scsi.c, usbh_msc_scsi.h
Команды SCSI.
usbd_msc_data.c, usbd_msc_data.h
Важные страницы запроса и чувствительные данные.
HID (Joystick, mouse)
usbh_hid.c, usbh_hid.h
Handler состояний класса HID.
Custom HID
usbd_customhid.c, usbd_customhid.h
Handler пользовательского класса HID.
Audio speaker
usbh_audio.c, usbh_audio.h
Handler класса Audio.
CDC (коммуникационное устройство)
usbh_cdc.c, usbh_cdc.h
Handler класса CDC (виртуальный последовательный порт).
DFU (устройство обновления firmware)
usbd_dfu.c, usbd_dfu.h
Handler класса DFU.
Ниже приведено краткое описание назначения функций в различных модулях библиотеки.
Таблица 10. usbd_core.c, usbd_core.h.
Функция
Описание
USBD_Init
Инициализирует библиотеку устройства, загружает драйвер класса и callback-функции пользователя.
Структура USB Class callback. Класс USB выбирается при инициализации библиотеки устройства USB путем выбора соответствующей callback-структуры класса. Эта структура класса определена следующим образом:
В этой структуре определены указатели на следующие callback-функции:
Init: вызывается, когда устройство принимает USB-запрос установки конфигурации; в этой функции открываются конечные точки, используемые в интерфейсе класса. DeInit: вызывается, когда принят USB-запрос очистки конфигурации; эта функция закрывает конечные точки, используемые в интерфейсе класса. Setup: вызывается для обработки специфичных для класса запросов настройки (class setup request). EP0_TxSent: вызывается, когда завершается состояние отправки пакета из управляющей конечной точки. EP0_RxSent: вызывается, когда завершается состояние приема пакета на управляющей конечной точке. DataIn: вызывается для выполнения обработки принятых данных, относящихся к не управляющим конечным точкам. DataOut: вызывается для выполнения обработки передаваемых данных, относящихся к не управляющим конечным точкам. SOF: вызывается, когда принято прерывание SOF (сигнал начала фрейма); этот callback может использоваться для синхронизации некоторых процессов с сигналом SOF. IsoINIncomplete: вызывается, когда не завершена последняя изохронная транзакция типа IN (isochronous IN transfer). IsoOUTIncomplete: вызывается, когда не завершена последняя изохронная транзакция типа OUT (isochronous OUT transfer). GetHSConfigDescriptor: этот callback вернет дескриптор USB-конфигурации HS. GetFSConfigDescriptor: этот callback вернет дескриптор USB-конфигурации FS. GetOtherSpeedConfigDescriptor: этот callback вернет другой дескриптор конфигурации используемого класса в режиме High Speed. GetDeviceQualifierDescriptor: этот callback вернет дескриптор квалификатора устройства.
Структура дескрипторов устройства USB. Библиотека также предоставляет callback-структуру дескрипторов, что позволяет управлять устройством и строковыми дескрипторами во время работы приложения (run time). Эта структура дескрипторов определена следующим образом:
GetDeviceDescriptor: этот callback вернет дескриптор устройства. GetLangIDStrDescriptor: этот callback вернет строковый дескриптор идентификатора языка (Language ID). GetManufacturerStrDescriptor: этот callback вернет строковый дескриптор производителя. GetProductStrDescriptor: этот callback вернет the строковый дескриптор продукта. GetSerialStrDescriptor: этот callback вернет строковый дескриптор серийного номера. GetConfigurationStrDescriptor: этот callback вернет строковый дескриптор конфигурации. GetInterfaceStrDescriptor: этот callback вернет строковый дескриптор интерфейса.
Примечание: в файле usbd_desc.c, предоставляемом с примерами устройства USB, реализованы тела этих callback-функций.
[Модуль класса библиотеки устройства USB]
Модуль класса содержит все файлы, относящиеся к реализации какого-либо класса устройства USB. Они соответствуют спецификации протокола, встроенного в эти классы. Таблица 13 показывает файлы класса устройства USB для классов MSC, HID, DFU, Audio, CDC.
Таблица 13. Файлы классов устройства USB.
Класс USB
Файлы
Описание
MSC (устройство хранения данных)
usbd_msc.c, usbd_msc.h
Здесь содержатся callback-функции класса MSC (драйвер) и дескрипторы конфигурации, относящиеся к этому классу.
usbd_bot.c, usbd_bot.h
Обработка протокола транзакций Bulk-only.
usbd_scsi.c, usbd_scsi.h
Обработка команд SCSI.
usbd_msc_data.c, usbd_msc_data.h
Важные страницы запроса и чувствительные данные устройства хранения.
Шаблон драйвера, который позволит Вам реализовать дополнительные интерфейсы к памяти класса DFU.
[Класс USB HID]
Реализация класса HID. Этот модуль содержит HID class V1.11, в соответствии со спецификацией "Device Class Definition for Human Interface Devices (HID) Version 1.11 June 27, 2001".
Примечание: спецификацию HID можно найти поиском по ключевому слову hidpage на сайте www.st.com.
Этот драйвер реализует следующие аспекты спецификации:
Пользовательский интерфейс HID. Входные репорты (input reports) отправляются через канал прерывания IN (Interrupt In pipe, см. пример HID mouse).
Репорты Feature и Output должны инициироваться хостом через управляющий канал (Control pipe) или канал прерывания OUT (Interrupt Out pipe, см. пример Custom HID).
Примечание: направления IN и OUT обозначаются по отношению к хосту USB (хост это обычно компьютер или смартфон). Таким образом, канал IN это канал для данных от устройства USB к хосту, а канал OUT это канал для данных от хоста к устройству USB.
Приложением HID mouse для отправки HID-репортов может использоваться функция USBD_HID_SendReport. В этом релизе драйвер HID обрабатывает только трафик IN. Ниже показан пример использования этой функции:
static __IO uint32_t counter=0;
HAL_IncTick();/* Проверка состояния джойстика каждые 10 мс */if (counter++==10)
{
GetPointerData(HID_Buffer);
/* Отправка данных через конечную точку IN */if((HID_Buffer[1] !=0) || (HID_Buffer[2] !=0))
{
USBD_HID_SendReport(&USBD_Device, HID_Buffer, 4);
}
counter =0;
}
Toggle_Leds();
HID Class Driver API. Ниже в таблице суммарно показаны API-функции драйвера HID-класса, определенные в модуле usbd_hid.c.
Таблица 14. Функции в файлах usbd_hid.c, usbd_hid.h.
Функция
Описание
USBD_HID_Init
Инициализирует интерфейс HID и откроет используемые конечные точки.
USBD_HID_DeInit
Отменяет инициализацию слоя HID и закрывает используемые конечные точки.
Стек HID инициализируется вызовом USBD_HID_Init(), затем приложение должно вызывать функцию USBD_HID_SendReport() для отправки репортов HID.
Через конечную точку 0 (EP0, Control, конечная точка управления) реализованы следующие запросы, специфичные для HID:
#define HID_REQ_SET_PROTOCOL 0x0B
#define HID_REQ_GET_PROTOCOL 0x03
#define HID_REQ_SET_IDLE 0x0A
#define HID_REQ_GET_IDLE 0x02
#define HID_REQ_SET_REPORT 0x09
#define HID_REQ_GET_REPORT 0x01
Адрес конечной точки IN и максимальное количество байт, которое можно отправить, задаются определениями:
#define HID_EPIN_ADDR 0x81
#define HID_EPIN_SIZE 0x04
[Класс Mass Storage (USB MSC)]
Реализация класса Mass Storage. Этот модуль обслуживает MSC class V1.0 в соответствии со спецификацией "Universal Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0 Sep. 31, 1999".
Драйвер реализует следующие аспекты спецификации:
• Протокол транспорта Bulk-only (только пакетные передачи). • Подкласс: SCSI transparent command set (прозрачный набор команд SCSI, основной набор команд SCSI Primary Commands - 3).
Класс USB mass storage построен вокруг Bulk Only Transfer (BOT). Он использует прозрачный набор команд SCSI.
Стандартная BOT-транзакция основана на простой машине состояний. Она начинается с ready state (idle state). Если от хоста принят CBW, могут обслуживается 3 случая:
• DATA-OUT-STAGE: когда флаг направления установлен в "0", устройство должно быть подготовлено к приему количества данных, показанного полем cbw.dDataLength блока CBW. По окончанию передачи данных возвращается CSW с оставшейся длиной данных и поле STATUS. • DATA-IN-STAGE: когда флаг направления установлен в "1", устройство должно быть подготовлено к отправке количества данных, указанного полем cbw.dDataLength в блоке CBW. По окончанию передачи данных возвращается CSW с оставшейся длиной данных и поле STATUS. • ZERO DATA: в этом случае не требуется стадия данных, и сразу после CBW отправляется блок CSW.
Рис. 13. Архитектура протокола BOT.
В следующей таблице показаны поддерживаемые команды SCSI.
Таблица 15. Команды SCSI.
Команда
Комментарий
SCSI_PREVENT_REMOVAL
SCSI_START_STOP_UNIT
SCSI_TEST_UNIT_READY
SCSI_INQUIRY
SCSI_READ_CAPACITY10
SCSI_READ_FORMAT_CAPACITY
READ_FORMAT_CAPACITY (0x23) это команда UFI.
SCSI_MODE_SENSE6
SCSI_MODE_SENSE10
SCSI_READ10
SCSI_WRITE10
SCSI_VERIFY10
Реализован запрос сброса устройства хранения (Bulk-only mass storage reset request, это запрос, специфический для класса), как того требует спецификация BOT. Это запрос используется для сброса устройства хранения (mass storage device) и связанного с ним интерфейса. Этот специфический для класса запрос должен подготовить устройство для поступления от хоста следующего CBW.
Чтобы генерировать BOT Mass Storage Reset, хост должен отправить запрос устройству на канале по умолчанию (default pipe):
• bmRequestType: тип запроса Class, interface, от хоста к устройству • поле bRequest, установленное в 255 (FFh) • поле wValue, установленное в 0 • поле wIndex, установленное в номер интерфейса • поле wLength, установленное в 0
Get Max MUN (специфический для класса запрос). Устройство может реализовать несколько логических юнитов (LUN), которые используют общие характеристики устройства. Хост использует bCBWLUN, чтобы показать, какой LUN устройства является пунктом назначения для CBW. Запрос к устройству Get Max LUN используется для того, чтобы определить количество LUN, поддерживаемых устройством.
Для генерации запроса Get Max LUN для устройства, хост отправляет запрос на канале по умолчанию (default pipe):
• bmRequestType: тип запроса Class, Interface, от устройства к хосту • поле bRequest, установленное в 254 (FEh) • поле wValue, установленное в 0 • поле wIndex, установленное в номер интерфейса • поле wLength, установленное в 1
Файлы ядра MSC. Ниже в таблицах показаны модули класса устройства хранения и их функции с кратким описанием.
Таблица 16. Функции в файлах usbd_msc.c, usbd_msc.h.
Функция
Описание
USBD_MSC_Init
Инициализирует интерфейс MSC и откроет используемые конечные точки.
USBD_MSC_DeInit
Отменяет инициализацию слоя MSC и закрывает используемые конечные точки.
USBD_MSC_Setup
Обрабатывает специфические запросы MSC.
USBD_MSC_DataIn
Обрабатывает стадию получения данных (MSC Data In).
USBD_MSC_DataOut
Обрабатывает стадию отправки данных (MSC Data Out).
Примечание: MicroSD - интерфейс носителя памяти по умолчанию (default media interface), предоставленный в библиотеке. Однако Вы можете добавить другие носители данных (память Flash, SDRAM, и т. п.), используя файл шаблона usbd_msc_storage_template.c.
Функция callback хранилища для класса MSC добавляется в приложение пользователя путем вызова USBD_MSC_RegisterStorage(&USBD_Device, &USBD_DISK_fops).
Данные стандартного запроса предоставляются пользователем в массиве STORAGE_Inquiry. Он должен быть определен следующим образом:
Ядро класса DFU обслуживает протокол в соответствии со стандартом "Device Class Specification for Device Firmware Upgrade Version 1.1 Aug 5, 2004".
Реализованы следующие аспекты спецификации:
• Обслуживание дескриптора устройства. • Обслуживание дескриптора конфигурации. • Энумерация на шине USB как устройства DFU (только в режиме DFU). • Обслуживание запросов (поддержка разновидности протокола ST DFU). • Обслуживания запроса к памяти (Download / Upload / Erase / Detach / GetState / GetStatus). • Машина состояний DFU.
Примечание: разновидность протокола DFU от компании ST (ST DFU sub-protocol) совместима с протоколом DFU. Она использует sub-запросы для обслуживания адресации памяти, обработки команд, специфических операций с памятью (стирание памяти, чтение, запись, и т. д.).
Как требует спецификация DFU, в этом приложении используется только конечная точка 0 (EP0, endpoint 0, или конечная точка управления).
В приложение могут быть добавлены другие конечные точки и функции (HID, и т. п.).
Эти аспекты могут быть расширены или изменены для определенного пользовательского приложения.
Драйвер USB не реализует режим Manifestation Tolerant, определенный в спецификации. Однако есть возможность обслуживать эту функцию путем модификации драйвера.
Реализация класса DFU. Транзакции DFU основаны на endpoint 0 (EP0, управляющая конечная точка). Все запросы и управление состоянием отправляются/принимаются через EP0.
Машина DFU основывается на следующих состояниях:
Таблица 20. Состояния DFU.
Состояние
Код состояния
appIDLE
0x00
appDETACH
0x01
dfuIDLE
0x02
dfuDNLOAD-SYNC
0x03
dfuDNBUSY
0x04
dfuDNLOAD-IDLE
0x05
dfuMANIFEST-SYNC
0x06
dfuMANIFEST
0x07
dfuMANIFEST-WAIT-RESET
0x08
dfuUPLOAD-IDLE
0x09
dfuERROR
0x0A
Разрешенные переходы между состояниями описаны в документе спецификации DFU.
Рис. 16. Диаграмма перехода состояний интерфейса DFU.
Чтобы защитить приложение от случайных доступов перед инициализацией, начальное состояние ядра DFU (после запуска) будет dfuERROR. Тогда хост должен очистить это состояние путем отправки запроса DFU_CLRSTATE перед генерацией любого другого запроса.
Ядро DFU обслуживает все поддерживаемые запросы (см. таблицу 21).
Таблица 21. Поддерживаемые запросы DFU.
Запрос
Код
Подробности
DFU_DETACH
0x00
Когда установится бит 3 в поле bmAttributes (бит WillDetach), устройство генерирует последовательность отсоединения-подсоединения (detach-attach sequence) на шине, когда получит этот запрос.
DFU_DNLOAD
0x01
Образ firmware загружается через транзакции управления-записи (control-write transfer), инициированный запросом DFU_DNLOAD, специфичным для класса DFU.
DFU_UPLOAD
0x02
Назначение этого запроса - дать возможности считать прошивку firmware с целью её архивирования.
DFU_GETSTATUS
0x03
Хост применяет запрос DFU_GETSTATUS, чтобы упростить синхронизацию с устройством (оно может быть занято стиранием памяти, записью данных или другими операциями).
DFU_CLRSTATUS
0x04
При получении запроса DFU_CLRSTATUS устройство установит статус OK и перейдет в состояние dfuIDLE.
DFU_GETSTATE
0x05
Этот запрос требует отсчета о состоянии устройства.
DFU_ABORT
0x06
Запрос DFU_ABORT позволяет хосту выйти из определенных состояний и вернуться в состояние DFU_IDLE.
Каждая транзакция к EP0 одной из двух категорий.
• Data transfer: эти транзакции используются для:
– получения некоторых данных из устройства (DFU_GETSTATUS, DFU_GETSTATE и DFU_UPLOAD). – или для отправки данных в устройство (DFU_DNLOAD).
• No-Data transfer: эти транзакции используются для отправки запросов управления от хоста к устройству (DFU_CLRSTATUS, DFU_ABORT и DFU_DETACH).
Файлы ядра класса DFU. Реализация этого драйвера находится в модуле usbd_dfu.c и его заголовочном файле usbd_dfu.h. Здесь обслуживаются все запросы DFU и машина состояний DFU. Модуль не работает напрямую с носителем памяти (это осуществляется драйверами низкого уровня).
Таблица 22. Функции в файлах usbd_dfu.c, usbd_dfu.h.
Обрабатывает запрос sub-протокола DFU для выхода из режима DFU (происходит выход из режима DFU и сброс устройства для запуска загруженного пользователем кода firmware).
Примечание: внутренняя память Flash это память по умолчанию, которая обслуживается библиотекой. Однако Вы можете добавить другие носители памяти, используя файл шаблона usbd_dfu_media_template.c.
1. Задайте в файле usbd_conf.h следующие параметры:
– количество поддерживаемых носителей (видов памяти) в #define USBD_DFU_MAX_ITF_NUM. – адрес приложения по умолчанию (куда должен быть загружен образ двоичного кода) в #define USBD_DFU_APP_DEFAULT_ADD.
2. Вызовите функцию USBD_DFU_Init() для инициализации всех интерфейсов памяти и машины состояний DFU.
3. Все операции управления/запроса (control/request) выполняются через EP0 с помощью функций USBD_DFU_Setup() и USBD_DFU_EP0_TxReady(). Эти функции можно использовать для вызова callback каждой памяти (read / write /erase / get state, ...), в зависимости от сгенерированных запросов DFU. Для этих операций от пользователя не требуется никаких действий.
4. Чтобы закрыть коммуникацию, вызовите функцию USBD_DFU_DeInit().
Примечание: когда запускается приложение DFU, то по умолчанию состояние его машины DFU_STATE_ERROR. Это состояние установлено, чтобы защитить приложение от случайных операций перед тем, как будет установлена корректная конфигурация устройства.
[Класс USB Audio]
Драйвер реализует Audio Class 1.0 в соответствии со стандартом "USB Device Class Definition for Audio Devices V1.0 Mar 18, 98". Реализованы следующие аспекты спецификации:
• Обслуживание дескриптора устройства. • Обслуживание дескриптора конфигурации. • Обслуживание стандартного дескриптора интерфейса класса аудио (Standard AC Interface Descriptor). • 1 Audio Streaming Interface (с одним каналом, PCM, режим Stereo). • 1 Audio Streaming endpoint. • 1 Audio Terminal Input (1 канал). • Audio Class-Specific AC Interfaces. • Audio Class-Specific AS Interfaces. • Audio Control Requests: поддерживаются только запросы SET_CUR и GET_CUR (для функции Mute). • Audio Feature Unit (ограниченный управлением Mute). • Audio Synchronization type: Asynchronous. • Одна фиксированная скорость следования выборок звука (audio sampling rate, конфигурируется в файлеusbd_conf.h).
Примечание: Audio Class 1.0 основан на USB 1.0, и поэтому поддерживаются только режимы скоростей Low Speed и Full Speed (транзакции High Speed не поддерживаются). За подробностями обращайтесь к стандарту "USB Device Class Definition for Audio Devices V1.0 Mar 18, 98".
Перечисленные аспекты могут быть расширены или модифицированы для специфичного приложения пользователя.
В этом драйвере не реализованы следующие аспекты спецификации (однако их можно обслуживать путем некоторых модификаций драйвера):
• Управление Audio Control endpoint. • Другие запросы Audio Control, кроме реализованных SET_CUR и GET_CUR. • Слой абстракции для запросов Audio Control (в настоящий момент обслуживается только функция mute). • Audio Synchronization type: Adaptive. • Модули и интерфейсы Audio Compression. • Интерфейсы и модули MIDI. • Юниты Mixer / Selector / Processing / Extension (представлен только юнит управления функцией Mute). • Другие модули, специфичные для приложения. • Несколько вариантов частоты выборок, переменная частота выборок. • Audio Out Streaming Endpoint / Interface (микрофон, оцифровка звука).
Реализация класса Audio. Транзакции звука основаны на isochronous endpoint. Запросы управления (Audio control request) также обслуживаются через control endpoint (endpoint 0).
В каждом фрейме передается пакет данных звука, и он должен быть обработан (преобразован в звук) в течение этого фрейма (перед поступления следующего фрейма). Качество звука зависит от синхронизации между транзакциями данных и воспроизведением данных в качестве звука. Этот драйвер реализует простой механизм синхронизации процессов передачи и воспроизведения, полагаясь на точность передаваемой тактовой частоты I2S. В каждом начале фрейма драйвер проверяет, были ли израсходованы данные предыдущего пакета, обрывает запрос передачи, если предыдущие данные все еще воспроизводятся. Для предотвращения перезаписи данных используются 2 основных механизма защиты:
• DMA для перемещения данных между буфером USB и регистрами устройства вывода (I2S). • Использование нескольких буферов для хранения данных, поступающих от USB.
На основе этого механизма, если точность тактов или частота воспроизведения недостаточно высока, то получится плохое качество звука. Этот механизм может быть улучшен путем реализации более гибкого управления потоком звуковых данных наподобие режима USB feedback, динамической коррекции тактирования звука или генерации/управления тактами звука на основе события начала фрейма (SOF event).
Этот драйвер также поддерживает базовые запросы управления звуком (Audio Control). Чтобы упростить драйвер, реализована обработка только двух запросов. Однако другие запросы могут быть поддержаны путем незначительной модификации драйвера.
Таблица 23. Запросы Audio control.
Запрос
Поддерживается
Назначение
SET_CUR
ДА
Устанавливает режим Mute в состояние On или Off (может быть также обновлено для установки уровня громкости).
SET_MIN
нет
-
SET_MAX
нет
-
SET_RES
нет
-
SET_MEM
нет
-
GET_CUR
ДА
Получает текущее состояние режима Mute (может быть обновлено до получения текущего уровня громкости).
GET_MIN
нет
-
GET_MAX
нет
-
GET_RES
нет
-
GET_MEM
нет
-
Файлы класса Audio. Основной код драйвера реализован в модуле usbd_audio_core.c и его заголовочном файле usbd_audio_core.h. Он управляет транзакциями audio-данных и запросами управления (control request). Драйвер не работает напрямую с аппаратурой звука (это обслуживается низкоуровневыми драйверами).
Таблица 24. Функции в файлах usbd_audio_core.c, usbd_audio_core.h.
Функция
Описание
USBD_AUDIO_Init
Инициализирует интерфейс класса AUDIO.
USBD_AUDIO_DeInit
Отменяет инициализацию интерфейса класса AUDIO.
USBD_AUDIO_Setup
Обрабатывает запросы, специфические для класса AUDIO.
Каждый звуковой аппаратный интерфейс драйвер должен предоставить указатель на структуру типа USBD_AUDIO_ItfTypeDef. Функции и константы, на которые указывает эта структура, перечислены в следующих секциях. Если какая-то функциональность не поддерживается в имеющемся интерфейсе памяти, то соответствующее поле устанавливается в значение NULL.
usbd_audio_if.c, usbd_audio_if.h. Этот драйвер на низком уровне управляет аппаратурой звука - интерфейсом Audio Out (обслуживание преобразования данных USB в звук динамика / наушников). Пользователь может вызвать низкоуровневый драйвер кодека (Codec driver, например stm324xg_eval_audio.c, stm324xg_eval_audio.h) для базовых операций со звуком (play / pause / volume control, ...).
Этот драйвер предоставляет указатель на структуру:
extern USBD_AUDIO_ItfTypeDef USBD_AUDIO_fops;
Таблица 25. Функции usbd_audio_if.c, usbd_audio_if.h.
Функция
Описание
Audio_Init
Инициализирует интерфейс звука.
Audio_DeInit
Отменяет инициализацию интерфейса звука и используемых ресурсов.
Audio_PlaybackCmd
Обрабатывает команды плеера (play, pause, ...).
Audio_VolumeCtl
Обрабатывает громкостью плеера.
Audio_MuteCtl
Обрабатывает состояние режима Mute плеера.
Audio_PeriodicTC
Обрабатывает окончание текущей передачи пакета (не требуется для текущей версии драйвера).
Примечание: файлы шаблона (usbd_audio_if_template.c, usbd_audio_if_template.h) предоставляют базовый пример драйвера, который позволит Вам реализовать дополнительные функции для своего приложения Audio.
Обслуживаются состояния приложения Audio player, показанные в таблице ниже.
Таблица 26. Состояния Audio player.
Состояние
Код
Описание
AUDIO_CMD_START
0x00
Аудиоплеер инициализирован и готов к работе.
AUDIO_CMD_PLAY
0x01
Аудиоплеер воспроизводит звук.
AUDIO_CMD_STOP
0x02
Аудиоплеер остановил воспроизведение звука.
Как использовать драйвер USB Audio. Этот драйвер использует слой абстракции от драйвера аппаратуры (например аппаратный кодек, интерфейс I2S, интерфейс управления через I2C, и т. п.). Эта абстракция выполняется через модуль нижнего слоя (например usbd_audio_if.c), который Вы можете модифицировать в зависимости от аппаратуры, доступной для приложения.
Для использования драйвера выполните следующие действия:
2. При запуске приложения вызовите функцию USBD_AUDIO_Init() для конфигурирования всех необходимых программных и аппаратных компонентов (функции конфигурирования аппаратуры, специфичные для приложения, также вызываются из этой функции). Аппаратные компоненты управляются через низкоуровневый интерфейс (например usbd_audio_if.c), и это может быть изменено пользователем в зависимости от требований приложения.
3. Транзакция полностью обслуживается функциями (пользователю не нужно вызывать никакую функцию для out-транзакций) usbd_audio_DataIn() и usbd_audio_DataOut(), которые обновляют буферы звука принятыми или переданными данными. Для Out-транзакций, когда принимаются данные, они напрямую копируются в звуковой буфер, и инкрементируется указатель буфера записи (wr_ptr).
4. Запросы управления Audio Control обслуживаются функциями USBD_AUDIO_Setup() и USBD_AUDIO_EP0_RxReady(). Эти функции перенаправляют запросы Audio Control на нижний уровень (например, usbd_audio_if.c). В текущей версии драйвера поддерживаются только запросы SET_CUR и GET_CUR для управления функцией выключения звука (mute control).
Известные ограничения:
• Если сконфигурирована низкая частота выборок (#define USBD_AUDIO_FREQ ниже 24 кГц), то могут быть помехи в звуке при операциях pause / resume / stop. Причина в интервале времени между остановкой тактов I2S и отправкой команды mute внешнему кодеку (external Codec). • Этим драйвером поддерживаются скорости выборок от 96 кГц до 24 кГц (не поддерживаются частоты, которые не делятся нацело на 1 кГц, наподобие 11.025 кГц, 22.05 кГц или 44.1 кГц). Для частот, делящихся на 1000 Гц, хост будет отправлять целое количество байт в каждом фрейме (с частотой 1 мс). Когда частота выборок звука не делится нацело на 1000 Гц, хост должен отправлять не целое количество байт во фрейме. Фактически это приведет к отправке фреймов с разными размерами (например, для частоты выборок 22.05 кГц хост будет отправлять 19 фреймов по 22 байта и один фрейм с 23 байтами). Это различие в размерах не поддерживается ядром драйвера Audio, и дополнительный байт будет игнорироваться. Рекомендуется установить высокую и стандартную частоту выборок, чтобы получить самое лучшее качество звука (например 96 кГц или 48 кГц). Обратите внимание, что максимально допустимая частота звука 96 кГц, это ограничение происходит из-за используемого кодека (Codec) на оценочной плате (Evaluation board). Блок STM32 I2S позволяет достичь частоты выборок 192 кГц.
[Класс USB CDC]
Драйвер класса коммуникационного устройства USB (Communication device class, CDC) работает в соответствии со стандартом "Universal Serial Bus Class Definitions for Communications Devices Revision 1.2 November 16, 2007" и sub-протоколом "Universal Serial Bus Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007".
Этот драйвер реализует следующие аспекты спецификации:
• Обслуживание дескриптора устройства. • Обслуживание дескриптора конфигурации. • Энумерация как устройства CDC с двумя конечными точками данных (IN и OUT), и одной конечной точкой команд (IN). • Обслуживание запроса (как это описано в секции 6.2 спецификации). • Совместимость с Abstract Control Model. • Коллекция Union Functional (для управления используется одна конечная точка IN). • Класс интерфейса данных.
Эти аспекты могут быть расширены и улучшены для специфического приложения пользователя.
Примечание: для поддержки Abstract Control Model эта реализация только передает запросы на диспетчер нижнего уровня (например usbd_cdc_vcp.c/usbd_cdc_vcp.h), которые должен обслуживать каждый запрос и выполняет соответствующие действия.
Этот драйвер не реализует следующие аспекты спецификации (однако можно обслужить эти функции путем некоторых модификаций кода драйвера):
• Любой специфический для класса аспект, относящийся к коммуникационному классу, должен обрабатываться приложением пользователя. • Не обслуживаются все коммуникационные классы, кроме PSTN.
Ядро CDC использует два типа конечных точек/транзакций:
• Конечные точки Bulk endpoint для передач данных (1 OUT endpoint и 1 IN endpoint). • Конечные точки Interrupt endpoint для управления коммуникацией (запросы CDC; 1 IN endpoint).
Передачи данных для транзакций IN и OUT обслуживаются по-разному.
Обслуживание Data IN transfer (от устройства к хосту). Транзакция данных обслуживается периодически, в зависимости от запроса хоста (устройство задает интервал между пакетами запроса). По этой причине для сохранения отправляемых в терминал данных используется статический буфер (например USART в случае терминала Virtual COM Port).
Обслуживание Data OUT transfer (от хоста к устройству). Обычно канал передачи данных USB намного быстрее, чем вывод терминала (например, максимальная скорость бит для USART составляет 115.2 Kbps, в то время как скорость USB составляет 12 Mbps для режима Full Speed и 480 Mbps в режиме High Speed). Соответственно перед отправкой новых пакетов хост ждет, пока устройство не завершит обработку данных, которые ранее передал хост. Таким образом, не требуется кольцевой буфер, когда данные принимаются от хоста: драйвер вызывает функцию низкого уровня для OUT транзакции и ждет, пока эта функция не завершится, перед тем, как будут разрешены новые транзакции на OUT endpoint (при этом пакеты OUT будут отклоняться, NACK).
Обслуживание Command request. В этом драйвере управляющая конечная точка (control endpoint, endpoint 0, EP0) используется для обслуживания запросов управления. Однако для обслуживания команд также может использоваться data interrupt endpoint. Если размер данных запроса не превышает 64 байт, то размер endpoint 0 достаточен для обслуживания этих запросов.
Драйвер CDC не делает парсинг командных запросов. Вместо этого он вызывает функцию низкоуровневого драйвера управления с кодом запроса, длиной и буфером данных. Тогда эта функция должна обработать запрос, и выполнить соответствующие требуемые действия.
Файлы драйвера USB CDC. Ядро драйвера находится в файлах usbd_cdc.c, usbd_cdc.h. Этот код обслуживает транзакции данных и запросы управления. Он не работает напрямую с аппаратурой CDC (это обслуживается драйверами низкого уровня).
Таблица 27. Функции в файлах usbd_cdc.c, usbd_cdc.h.
Каждый драйвер аппаратного интерфейса должен предоставить указатель на структуру типа USBD_CDC_ItfTypeDef. Функции, на которые указывают поля в этой структуры, перечислены в последующих секциях. Если какая-то функция не поддерживается, то соответствующее поле должно быть установлено в значение NULL.
Замечание: чтобы достичь самой высокой производительности, рекомендуется вычислить значения, необходимые для следующих параметров (все они конфигурируются в файлах usbd_cdc.h и usbd_cdc_interface.h), см. таблицу 28.
Таблица 28. Конфигурируемые параметры CDC.
Определение #define
Параметр
Типовое значение
Full Speed
High Speed
CDC_DATA_HS_IN_PACKET_SIZE
Размер каждого пакета данных IN.
64
512
CDC_DATA_FS_IN_PACKET_SIZE
CDC_DATA_HS_OUT_PACKET_SIZE
Размер каждого пакета данных OUT.
64
512
CDC_DATA_FS_OUT_PACKET_SIZE
APP_TX_DATA_SIZE
Общий размер кольцевого временного буфера для OUT-транзакций данных.
2048
2048
APP_RX_DATA_SIZE
Общий размер кольцевого временного буфера для IN-транзакций данных.
2048
2048
usbd_cdc_interface.c, usbd_cdc_interface.h. Этот драйвер может быть частью приложения пользователя. Он не предоставлен в библиотеке, однако можно использовать шаблон (usbd_cdc_if_template.c, usbd_cdc_if_template.h), чтобы создать собственный драйвер, и предоставлен пример для интерфейса USART. Он обслуживает нижний слой аппаратуры CDC. Драйвер usbd_cdc_interface.c / usbd_cdc_interface.c.h управляет интерфейсом терминала и обменом данными (например конфигурацией интерфейса USART и передачей / приемом данных).
Этот драйвер предоставляет указатель на структуру:
Чтобы ускорить обслуживание данных для транзакций IN/OUT, низкоуровневый драйвер использует следующие глобальные переменные (находятся в usbd_cdc_interface.c / usbd_cdc_interface.h):
Таблица 30. Переменные, используемые в usbd_cdc_xxx_if.c, / usbd_cdc_xxx_if.h.
Переменная
Использование
uint8_t UserRxBuffer[APP_RX_DATA_SIZE];
Записывает принятые из USART данные в этот буфер. Эти данные отправляются через конечную точку USB IN в функциях ядра CDC.
uint32_t UserTxBufPtrOut;
Это указатель инкрементируется или возвращается в начало, когда принятые данные записываются в буфер UserRxBuffer.
uint8_t UserTxBuffer[APP_TX_DATA_SIZE];
В этот буфер записываются принятые CDC данные. Эти данные принимаются из конечной точки USB OUT в функциях ядра CDC.
uint32_t UserTxBufPtrIn;
Этот указатель инкрементируется или возвращается в начало, когда данные принимаются через USART.
Как использовать драйвер USB CDC. В драйвере применен уровень абстракции для низкоуровневого драйвера аппаратуры CDC (например, интерфейс управления USART). Эта абстракция низкого уровня (например stm32fxxx_hal_msp.c) позволяет Вам модифицировать адаптировать приложение к имеющейся аппаратуре.
Чтобы использовать драйвер, выполните следующее.
1. В файлах usbd_cdc.h и usbd_cdc_interface.h сконфигурируйте параметры:
– размеры пакетов Data IN, OUT и команд (определения #define CDC_DATA_XX_IN_PACKET_SIZE, CDC_DATA_XX_OUT_PACKET_SIZE). Здесь вместо "XX" надо подставить FS или HS, в зависимости от режима скорости Fast Speed или High Speed. – размер временного кольцевого буфера для транзакций данных IN/OUT (#define APP_RX_DATA_SIZE и APP_TX_DATA_SIZE). – строковые дескрипторы устройства.
2. Вызовите функцию USBD_CDC_Init() при запуске приложения, чтобы сконфигурировать все необходимые программные и аппаратные компоненты (эта функция также вызовет зависящие от приложения функции конфигурации оборудования). Компоненты аппаратуры управляются низкоуровневым интерфейсом (например usbd_cdc_interface.c) и это может быть изменено пользователем в зависимости от требований приложения.
3. CDC-транзакции данных IN и OUT управляются двумя функциями:
– USBD_CDC_SetTxBuffer должна быть вызвана из приложения пользователя каждый раз, когда имеются данные для отправки хосту USB. – USBD_CDC_SetRxBuffer вызывается ядром CDC всякий раз, когда приняты данные от хоста, и они должны быть переданы через аппаратуру терминала. Из этой функции должен произойти выход только когда все данные в буфере были отправлены (ядро CDC на это время блокирует все поступающие пакеты OUT, пока эта функция не завершит обработку данных предыдущего пакета).
4. Запросы управления (CDC control requests) должны быть обработаны функцией Controllability(). Эта функция вызывается каждый раз, когда принят запрос от хоста, и доступны все соответствующие данные, если таковые имеются. Эта функция должна парсить запрос, и выполнять требуемые запросом действия.
5. Чтобы закрыть обмен, вызовите функцию USBD_CDC_DeInit(). Она закрывает используемые конечные точки, и вызывает низкоуровневые функции, отменяющие сделанные ранее инициализации.
Известные ограничения CDC. Когда этот драйвер используется с ядром OTG HS, разрешение режима DMA (#define USB_OTG_HS_INTERNAL_DMA_ENABLED в файле usb_conf.h) приведет к тому, что количество отправляемых данных всегда будет нацело делиться на 4. Причина в том, что фактически USB DMA не позволяет передавать данные, не выровненные по адресу на границу слова. Для этого специфичного приложения не рекомендуется разрешать эту опцию без специальной необходимости.
[Добавление пользовательского класса USB]
В этой секции описывается, как создать новый пользовательский класс USB (custom class), основанный на существующем классе USB.
Чтобы создать новый custom Class, выполните следующие шаги:
1. Добавьте USBD_CustomClass_cb (чтобы принимать различные события шины USB) как это описано выше в разделе "Интерфейс класса устройства USB", в usbd_template.c / usbd_template.h, находящемся в каталоге Class/Template. Этот шаблон содержит все функции, которые должны быть адаптированы к потребностям приложения, и он может использоваться для реализации любого типа класса устройства USB.
2. Настройте дескрипторы. Эти дескрипторы запрашивает хост, и они должны быть сконфигурированы, чтобы описать устройство, в зависимости от спецификации класса устройства приложения. Следующий список не полный, однако дает обзор различных дескрипторов, которые могут потребоваться:
– стандартный дескриптор устройства – стандартный дескриптор интерфейса – стандартный дескриптор интерфейса для реализуемого класса устройства USB – стандартные дескрипторы конечных точек для IN endpoint и OUT endpoint.
3. Программа должна сконфигурировать STM32, чтобы разрешить транзакции USB (isochronous, Bulk, Interrupt или Control), в зависимости от приложения пользователя:
– В функциях DataIn и DataOut пользователь может реализовать внутренний протокол или машину состояний. – В функции Setup реализуется обработка запросов, специфичных для класса. Добавляется дескриптор как массив, и передается библиотеке устройства USB. – Функция GetConfigDescriptor должна вернуть указатель на дескриптор конфигурации USB и его длину. – Могут быть добавлены дополнительные функции, как IsoINIncomplete и IsoOUTIncomplete, которые используются при необходимости для обработки неполных изохронных транзакций (для дополнительной информации см. пример USB audio device). – По мере необходимости должны использоваться EP0_TxSent и EP0_RxReady, когда приложению нужно обработать события, происходящие перед пакетами нулевой длины (Zero Length Packets, см. пример устройства DFU).
4. Процесс выделения памяти: память выделяется приложением с использованием malloc (USBD_malloc):
– USBD_malloc(sizeof (USBD_CUSTOM_CLASS_HandleTypeDef)): это динамически выделяемая память для структуры класса.
[Оптимизация кода библиотеки USB]
В этой секции мы рассмотрим некоторые базовые советы (возможно банальные) для оптимизации памяти программ и данных и быстродействия, когда программа использует библиотеку устройства USB.
Уменьшение размера используемой памяти в примерах USB всегда является важным вопросом для микроконтроллеров STM32, особенно для тех, у которых маленькие объемы памяти Flash/RAM, таких как серии STM32L0 и F0.
Уменьшение размера кучи и стека (настройка в файле линкера). Стек это область оперативной памяти, где программа сохраняет:
• Локальные переменные, аргументы функции • Адреса возврата • Временные переменные, которое использует компилятор • Контексты прерывания
Куча это специальная область памяти, из которой можно динамически (во время выполнения программы, run time) выделять блоки памяти нужного размера. Во многих встраиваемых приложениях куча вообще не используется.
Если Ваша конфигурация линкера резервирует слишком много памяти для кучи и стека, то Вы можете уточнить количество памяти, которое на самом деле требуется программе.
Старайтесь всегда, если это возможно, использовать локальные переменные вместо глобальных. Если переменная используется только в одной функции, и её значение не нужно сохранять между отдельными вызовами этой функции, то такая переменная должна быть определена как локальная переменная.
Константы должны выделяться из памяти flash. Рекомендуется все глобальные переменные, которые не изменяются, определить как константы в секции памяти, предназначенной только для чтения. Например, дескрипторы USB это хорошие кандидаты для декларации в виде констант, используя ключевое слово const языка C.
Используйте статическую память вместо malloc. Библиотека устройства USB использует динамическую память для выделения памяти под структуру класса (class handle structure), чтобы можно было поддерживать несколько экземпляров объектов (в случае работы в двухядерной среде). Это означает, к примеру, что мы можем иметь иметь два экземпляра одного и того же класса USB (HS и FS).
Вторая причина использования динамического выделения памяти - возможность её освобождения, когда USB больше не используется.
Однако динамическое выделение вносит некоторые дополнительные затраты как памяти кода, так и памяти данных, особенно в памяти кода. По этой причине рекомендуется использовать статическое выделение памяти вместо динамического для устройств STM32 с малым объемом памяти, или когда не требуется поддержка несколько экземпляров (вариантов) стека USB. Для этого необходимо декларировать статический буфер достаточного размера, чтобы в нем разместилась структура класса USB (class handle structure).
Ниже показан пример реализации:
1. В файле usbd_conf.h определите статическое выделение памяти и подпрограммы для этого:
USBD_static_malloc()and USBD_static_free()
#define MAX_STATIC_ALLOC_SIZE 4 /* HID Class structure size */
1. Как можно на лету модифицировать дескриптор устройства и строковые дескрипторы?
В файле usbd_desc.c дескриптор, относящийся к устройству и строки могут быть изменены в помощью callback-вызовов Get Descriptor. Приложение может вернуть корректный буфер дескриптора относительно индекса приложения, используя оператор switch/case.
2. Как драйверу класса устройства хранения (mass storage class, MSC) поддержать больше одного логического юнита (LUN)?
В файле usbd_msc_storage_template.c определено все API, необходимое для использования физического носителя данных (physical media). Каждая функция поставляется с параметром LUN для выбора адресованного носителя.
Количество поддерживаемых The LUN можно поменять с помощью изменения #define STORAGE_LUN_NBR в файле usbd_msc_storage_xxx.c (здесь xxx обозначает используемый носитель).
Для запроса данных буфер STORAGE_Inquirydata содержит стандартные данные запроса для каждого LUN. Ниже показан пример использования двух LUN.
Адреса конечных точек определены в файле заголовка драйвера класса. В случае MSC demo, например, адреса конечных точке IN/OUT определены в файле usbd_msc.h следующим образом:
#define MSC_EPIN_ADDR 0x81 // для Endpoint 1 IN
#define MSC_EPOUT_ADDR 0x01 // для Endpoint 1 OUT
4. Может ли библиотека устройства USB быть сконфигурированной для работы либо в режиме High Speed, либо в режиме Full Speed?
Да, библиотека может обработать USB OTG HS и USB OTG FS, и если ядро USB OTG FS может работать только в Full Speed mode, то USB OTG HS может работать и режимах High Speed и Full Speed.
Для выбора подходящего ядра To USB, с которым нужно работать, пользователь должен добавить следующие макроопределения для препроцессора компилятора (это уже сделано в заранее сконфигурированных проектах примеров):
- "USE_USB_HS" когда используется ядро USB High Speed (HS) - "USE_USB_FS" когда используется ядро USB Full Speed (FS) - "USE_USB_HS" и "USE_USB_HS_IN_FS" когда ядро USB High Speed (HS) может использоваться и в режиме в FS.
5. Как можно использовать измененные конечные точки в драйвере класса устройства USB?
Для изменения конечных точке или добавления новой конечной точки:
a) Выполните инициализацию конечной точки с помощью USBD_LL_OpenEP(). b) Сконфигурируйте размер Tx FIFO или Rx FIFO Новых определяемых конечных точек в файле usb_conf.c с помощью следующих вызовов APIs в файле USBD_LL_Init().
Для серий STM32F2 и STM32F4 (ядра FS и HS):
HAL_PCD_SetRxFiFo()
HAL_PCD_SetTxFiFo()
Общий размер Rx FIFO и Tx FIFO должен быть меньше, чем общий размер FIFO, используемого ядром, 320 x 32 бит (1.25 килобайт) для ядра USB OTG FS и 1024 x 32 бит (4 килобайта) для ядра USB OTG HS.
Для серий STM32F0, STM32L0, STM32F1 и STM32F3 (только ядро FS):
HAL_PCD_PMA_Config()
6. Совместима ли библиотека устройства USB с операционной системой реального времени (RTOS)?
Да, библиотека устройства USB может использоваться вместе с RTOS, обертка CMSIS RTOS wrapper используется при создании абстракции для ядра операционной системы (OS kernel).
Подскажите, а в структуре _USBD_HandleTypeDef есть поле, по которому можно определить, со стороны хоста "подключена" какая-нибудь программа? Например, чтобы при открытии Терминала СОМ-порта вывести "приветственное меню"?
microsin: чтобы определить подключение клиента к хосту CDC, обрабатывайте событие HOST_USER_CONNECTION в функции USBH_UserProcess (см. модуль usb_host.c).
Комментарии
microsin: чтобы определить подключение клиента к хосту CDC, обрабатывайте событие HOST_USER_CONNE CTION в функции USBH_UserProces s (см. модуль usb_host.c).
RSS лента комментариев этой записи