Русский
Русский
English
Статистика
Реклама

Составное устройство USB на STM32. Часть 3 Звуковое устройство отдельно, виртуальный СОМ-порт отдельно


В третьей части публикации о составном устройстве USB я расскажу о том, как переделать сгенерированный в STM32CubeMX USB Audio Speaker, описанный во второй части публикации, в дуплексное звуковое устройство.

Затем мы создадим в STM32CubeMX драйвер виртуального COM-порта.

Зачем мы всё это делаем, подробно описано в первой части публикации.

Ссылки на первую и вторую части публикации:
Составное устройство USB на STM32. Часть 1: Предпосылки
Составное устройство USB на STM32. Часть 2: USB Audio Speaker

Исходные коды публикуемой реализации составного устройства USB, состоящего из виртуального COM-порта и дуплексной звуковой карты находятся здесь: http://github.com/dmitrii-rudnev/selenite-habr

Доработка дескриптора


Дорабатываемый дескриптор размещается STM32CubeMX в файле usbd_audio.c. В работе использовались документы [2] и [3].

Обилие в сгенерированном дескрипторе макросов, заданных в файле usbd_audio.h, на мой взгляд, затрудняет работу с ним. Поэтому я заменил большую часть макросов на шестнадцатеричные значения, чтобы части дескриптора выглядели подобно их описанию в таблицах из [2] и [3], а также как в листинге, сгенерированном утилитой Thesycon USB Descriptor Dumper.

Однако, для удобства конфигурирования отдельные макросы пришлось оставить, а также добавить несколько новых:
// Размер дескриптора конфигурации#define USB_AUDIO_CONFIG_DESC_SIZ  192U// Номера интерфейсов#define AUDIO_CTRL_IF              0x00U#define AUDIO_OUT_IF               0x01U#define AUDIO_IN_IF                0x02U// Номера конечных точек (EP)#define AUDIO_OUT_EP               0x01U#define AUDIO_IN_EP                0x81U// Размер пакета и размер циклического буфера#define AUDIO_OUT_PACKET_NUM       4U // 80U#define USBD_AUDIO_FREQ            48000U#define AUDIO_OUT_PACKET           (uint16_t)(((USBD_AUDIO_FREQ * 2U * 2U) / 1000U))#define AUDIO_TOTAL_BUF_SIZE       (uint16_t)(AUDIO_OUT_PACKET * AUDIO_OUT_PACKET_NUM))

Хотел бы заострить внимание на том, что размеры циклических буферов трактов записи и воспроизведения определяются значением AUDIO_OUT_PACKET_NUM. Для стабильной работы драйвера достаточно использовать буферы размером 4 пакета, в то время как размер по умолчанию равен 80 пакетам.

Доработанный дескриптор описывает дуплексное звуковое устройство USB со структурой, приведённой на рисунке ниже:


Устройства ID2 и ID5 (Feature Unit) оставлены в структуре звукового устройства на вырост. Управление ими осуществляется через Class-Specific Requests. При обработке этих запросов драйвер звукового устройства должен передавать оконечному устройству набор команд для управления уровнями громкости, настройками эквалайзера, звукового процессора и т.п. В доработанном дескрипторе набор этот состоит пока из одной только команды MUTE.

Посмотреть листинг доработанного дескриптора
Information for device STM32 Audio Class (VID=0x0483 PID=0x5740):Connection Information:------------------------------Device current bus speed: FullSpeedDevice supports USB 1.1 specificationDevice supports USB 2.0 specificationDevice address: 0x0008Current configuration value: 0x01Number of open pipes: 0Device Descriptor:------------------------------0x12bLength0x01bDescriptorType0x0201bcdUSB0x00bDeviceClass      0x00bDeviceSubClass   0x00bDeviceProtocol   0x40bMaxPacketSize0   (64 bytes)0x0483idVendor0x5740idProduct0x0200bcdDevice0x01iManufacturer   "STMicroelectronics"0x02iProduct   "STM32 Audio Class"0x03iSerialNumber   "317C33753434"0x01bNumConfigurationsConfiguration Descriptor:------------------------------0x09bLength0x02bDescriptorType0x00C0wTotalLength   (192 bytes)0x03bNumInterfaces0x01bConfigurationValue0x00iConfiguration0xC0bmAttributes   (Self-powered Device)0xFAbMaxPower      (500 mA)Interface Descriptor:------------------------------0x09bLength0x04bDescriptorType0x00bInterfaceNumber0x00bAlternateSetting0x00bNumEndPoints0x01bInterfaceClass      (Audio Device Class)0x01bInterfaceSubClass   (Audio Control Interface)0x00bInterfaceProtocol   0x00iInterfaceAC Interface Header Descriptor:------------------------------0x0AbLength0x24bDescriptorType0x01bDescriptorSubtype0x0100bcdADC0x0046wTotalLength   (70 bytes)0x02bInCollection0x01baInterfaceNr(1)0x02baInterfaceNr(2)AC Input Terminal Descriptor:------------------------------0x0CbLength0x24bDescriptorType0x02bDescriptorSubtype0x01bTerminalID0x0101wTerminalType   (USB Streaming)0x00bAssocTerminal0x02bNrChannels   (2 channels)0x0003wChannelConfig0x00iChannelNames0x00iTerminalAC Feature Unit Descriptor:------------------------------0x09bLength0x24bDescriptorType0x06bDescriptorSubtype0x02bUnitID0x01bSourceID0x01bControlSizebmaControls:  0x01Channel(0) 0x00Channel(1)0x00iFeatureAC Output Terminal Descriptor:------------------------------0x09bLength0x24bDescriptorType0x03bDescriptorSubtype0x03bTerminalID0x0301wTerminalType   (Speaker)0x00bAssocTerminal0x02bSourceID0x00iTerminalAC Input Terminal Descriptor:------------------------------0x0CbLength0x24bDescriptorType0x02bDescriptorSubtype0x04bTerminalID0x0200wTerminalType   (Input Undefined)0x00bAssocTerminal0x02bNrChannels   (2 channels)0x0003wChannelConfig0x00iChannelNames0x00iTerminalAC Feature Unit Descriptor:------------------------------0x09bLength0x24bDescriptorType0x06bDescriptorSubtype0x05bUnitID0x04bSourceID0x01bControlSizebmaControls:  0x01Channel(0) 0x00Channel(1)0x00iFeatureAC Output Terminal Descriptor:------------------------------0x09bLength0x24bDescriptorType0x03bDescriptorSubtype0x06bTerminalID0x0101wTerminalType   (USB Streaming)0x00bAssocTerminal0x05bSourceID0x00iTerminalInterface Descriptor:------------------------------0x09bLength0x04bDescriptorType0x01bInterfaceNumber0x00bAlternateSetting0x00bNumEndPoints0x01bInterfaceClass      (Audio Device Class)0x02bInterfaceSubClass   (Audio Streaming Interface)0x00bInterfaceProtocol   0x00iInterfaceInterface Descriptor:------------------------------0x09bLength0x04bDescriptorType0x01bInterfaceNumber0x01bAlternateSetting0x01bNumEndPoints0x01bInterfaceClass      (Audio Device Class)0x02bInterfaceSubClass   (Audio Streaming Interface)0x00bInterfaceProtocol   0x00iInterfaceAS Interface Descriptor:------------------------------0x07bLength0x24bDescriptorType0x01bDescriptorSubtype0x01bTerminalLink0x01bDelay0x0001wFormatTag   (PCM)AS Format Type 1 Descriptor:------------------------------0x0BbLength0x24bDescriptorType0x02bDescriptorSubtype0x01bFormatType   (FORMAT_TYPE_1)0x02bNrChannels   (2 channels)0x02bSubframeSize0x10bBitResolution   (16 bits per sample)0x01bSamFreqType   (Discrete sampling frequencies)0x00BB80 tSamFreq(1)   (48000 Hz)Endpoint Descriptor (Audio/MIDI 1.0):------------------------------0x09bLength0x05bDescriptorType0x01bEndpointAddress  (OUT endpoint 1)0x01bmAttributes      (Transfer: Isochronous / Synch: None / Usage: Data)0x00C0wMaxPacketSize    (1 x 192 bytes)0x01bInterval         (1 frames)0x00bRefresh0x00bSynchAddressAS Isochronous Data Endpoint Descriptor:------------------------------0x07bLength0x25bDescriptorType0x01bDescriptorSubtype0x00bmAttributes0x00bLockDelayUnits   (undefined)0x0000wLockDelayInterface Descriptor:------------------------------0x09bLength0x04bDescriptorType0x02bInterfaceNumber0x00bAlternateSetting0x00bNumEndPoints0x01bInterfaceClass      (Audio Device Class)0x02bInterfaceSubClass   (Audio Streaming Interface)0x00bInterfaceProtocol   0x00iInterfaceInterface Descriptor:------------------------------0x09bLength0x04bDescriptorType0x02bInterfaceNumber0x01bAlternateSetting0x01bNumEndPoints0x01bInterfaceClass      (Audio Device Class)0x02bInterfaceSubClass   (Audio Streaming Interface)0x00bInterfaceProtocol   0x00iInterfaceAS Interface Descriptor:------------------------------0x07bLength0x24bDescriptorType0x01bDescriptorSubtype0x06bTerminalLink0x01bDelay0x0001wFormatTag   (PCM)AS Format Type 1 Descriptor:------------------------------0x0BbLength0x24bDescriptorType0x02bDescriptorSubtype0x01bFormatType   (FORMAT_TYPE_1)0x02bNrChannels   (2 channels)0x02bSubframeSize0x10bBitResolution   (16 bits per sample)0x01bSamFreqType   (Discrete sampling frequencies)0x00BB80 tSamFreq(1)   (48000 Hz)Endpoint Descriptor (Audio/MIDI 1.0):------------------------------0x09bLength0x05bDescriptorType0x81bEndpointAddress  (IN endpoint 1)0x01bmAttributes      (Transfer: Isochronous / Synch: None / Usage: Data)0x00C0wMaxPacketSize    (1 x 192 bytes)0x01bInterval         (1 frames)0x00bRefresh0x00bSynchAddressAS Isochronous Data Endpoint Descriptor:------------------------------0x07bLength0x25bDescriptorType0x01bDescriptorSubtype0x00bmAttributes0x00bLockDelayUnits   (undefined)0x0000wLockDelayMicrosoft OS Descriptor is not available. Error code: 0x0000001FString Descriptor Table--------------------------------Index  LANGID  String0x00   0x0000  0x0409 0x01   0x0409  "STMicroelectronics"0x02   0x0409  "STM32 Audio Class"0x03   0x0409  "317C33753434"------------------------------Connection path for device: xHCI-??????????? ????-?????????? USBRoot HubSTM32 Audio Class (VID=0x0483 PID=0x5740) Port: 2Running on: Windows 10 or greaterBrought to you by TDD v2.11.0, Mar 26 2018, 09:54:50


Доработка драйвера звукового устройства USB


При доработке драйвера в структуру звукового устройства был добавлен циклический буфер тракта записи, а состав команд, передаваемых пользовательскому интерфейсу, расширен командами AUDIO_CMD_STOP и AUDIO_CMD_RECORD.

Тракт записи дуплексного звукового устройства USB начинает работу при установке интерфейса AUDIO_IN_IF в состояние Alternate Setting 1, после чего драйвер ожидает событие SOF, во время обработки которого формирует команду AUDIO_CMD_RECORD, по которой заполняет половину буфера тракта записи пакетами из буфера DSP. Далее эти пакеты передаются из циклического буфера тракта записи вовне через конечную точку AUDIO_IN_EP.

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

Особенностью использования конечной точки AUDIO_IN_EP драйвером звукового устройства является необходимость запуска USBD_LL_FlushEP(pdev, AUDIO_IN_EP) для очистки буфера конечной точки после окончания передачи каждого пакета.

Тракт воспроизведения дуплексного звукового устройства USB включается при установке интерфейса AUDIO_OUT_IF в состояние Alternate Setting 1. Команда AUDIO_CMD_PLAY формируется драйвером звукового устройства по событию заполнения каждой половины циклического буфера тракта воспроизведения, после чего эти пакеты передаются в буфер DSP.

Команда AUDIO_CMD_STOP формируется драйвером при установке интерфейса AUDIO_OUT_IF в состояние Alternate Setting 0, после чего DSP включает в тракте воспроизведения режим тишины.

Синхронизация потоков данных доработанным драйвером не производится, поэтому функция USBD_AUDIO_Sync не производит никаких действий и оставлена в составе драйвера только для совместимости.

Проверка работоспособности драйвера дуплексного звукового устройства USB


При генерации драйвера виртуального COM-порта STM32CubeMX удалит из проекта файлы драйвера звукового устройства. Поэтому переносим usbd_audio.c и usbd_audio_if.c в папку Core/Scr, а usbd_audio.h и usbd_audio_if.h в Core/Inc.

Пересобираем проект, перепрошиваем устройство. Подключаем устройство к компьютеру, включаем тракт записи через панель управления звуком. Назначаем тракты воспроизведения и записи дуплексного звукового устройства USB устройствами по умолчанию.

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

Включаем в панели управления звуком для тракта записи нашего устройства прослушивание через звуковую карту компьютера. Убеждаемся в работоспособности драйвера дуплексного звукового устройства USB.

Создаём Communication Device Class


Приступаем к созданию виртуального COM-порта, для чего переходим в раздел Middleware и выбираем IP Commucation Device Class. Задаём максимальное количество интерфейсов равное пяти. Размер буферов задаём равным 64 Bytes.



Интерфейсов пять, т.к. в составе дуплексного звукового устройства их три, а в составе виртуального COM-порта два.

Сохраняем проект. Генерируем код. Смотрим, что получилось в результате.

Разбираем работу устройства


Файлы сгенерированного в STM32CubeMX драйвера виртуального COM-порта расположены в папках Middlewares/ST/Class/CDC и USB_DEVICE.

Функции, с помощью которых драйвер виртуального COM-порта взаимодействует со своим оконечным оборудованием, содержатся в файле usbd_cdc_if.c.

Во время инициализации устройства функция CDC_Init_FS задаёт настройки буферов трактов приёма и передачи.

При получении команд управления драйвер виртуального COM-порта запускает функцию CDC_Control_FS. Список команд управления приводится на стр.19 документа:

[4] Universal Serial Bus Communications Class Subclass Specification for PSTN Devices, Revision 1.2, February 9, 2007

В описании функции следует обратить внимание на структуру переменных типа USBD_CDC_LineCodingTypeDef, объявленного в usbd_cdc.h. При дальнейшем использовании драйвера мы можем с помощью переменной такого типа жёстко задать параметры COM-порта, которые он передаёт вовне по запросу.

Функция CDC_Receive_FS запускается по событию получения данных по виртуальному COM-порту.

Для передачи данных по виртуальному COM-порту используется функция CDC_Transmit_FS.

Проверка работоспособности драйвера виртуального COM-порта


Виртуальный COM-порт начинает работать прямо из коробки. Для контроля работоспособности организуем функцию эха.

Открываем в папке USB_DEVICE\App файл usbd_cdc_if.c и добавляем в функцию CDC_Receive_FS шлейф, как показано ниже:
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len){  /* USER CODE BEGIN 6 */  CDC_Transmit_FS (Buf, *Len); //++++++  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);  USBD_CDC_ReceivePacket(&hUsbDeviceFS);  return (USBD_OK);  /* USER CODE END 6 */}

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

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

От автора


В следующей части публикации мы объединим виртуальный COM-порт и дуплексное звуковое устройство в составное устройство USB и разберём несколько не совсем очевидных нюансов этого объединения.
Источник: habr.com
К списку статей
Опубликовано: 09.03.2021 08:15:06
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Разработка систем связи

Программирование микроконтроллеров

Stm32

Stm32cubemx

Stm32cubeide

Ham radio

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru