Примеры работы с USB Device для STM32F4-Discovery

Поскольку в нашем сообществе совсем мало статей про работу с STM32F4-Discovery, то я решил выложить несколько примеров работы с USB в STM32F4. Все примеры написаны в IAR.

По каким-то причинам ST не выложили документацию на работу с USB в контроллерах STM32F4. Сами библиотеки для работы с USB пришлось взять из примеров для Discovery. Насколько я понял позже, при работе с этими библиотеками можно использовать документацию UM1021 (библиотека USB для STM32F105/7 and STM32F2xx).
Все нижеописанные примеры, как мне кажется, достаточно хорошо показывают некоторые режимы работы USB в STM32F4-Discovery, и при этом к ней не требуется подключать какую-либо внешнюю периферию.

В примерах к Discovery работа в режиме «USB Device» показана в примере Demonstration (он прошивается в Discovery при изготовлении). Пример достаточно навороченный, USB в нем используется для эмуляции мыши в системе.
Разбираться с USB я начал именно с него. Для того, чтобы было проще разобраться в его работе, я выкинул из него часть кода, и оставил только код для работы в режиме «HID Mouse».
При включении производится инициализация периферии платы и USB, после чего весь код выполняется только в прерываниях. В данном случае все просто — в обработчике прерывания SysTick_Handler() опрашивается кнопка на плате, и если она нажата, то вызывается функция USBD_HID_SendReport, которая передает данные о перемещении курсора. Данные всегда одинаковы(константы), так что при нажатии кнопки на Discovery, курсор начинает ползти вверх.

Других примеров для работы в режиме «USB Device» к Discovery не прилагалось, не смотря на то, что в библиотеке USB были файлы для работы и в режиме CDC, и Audio Out.
Поискал в интернете примеры работы с USB, нашел только эти:
mcu.cz/comment-n2848.html
mcu.cz/comment-n2800.html
Правда, описание там на чешском и используется там TrueSTUDIO, так что решил на базе найденного написать свои примеры, правда, код остался практически тот же.

Сначала «USB Custom HID». В примерах такой класс отсутствовал, и я взял его из чешского примера.
Принцип работы такой же, как и в примере от ST для «STM32F10x and STM32L1xx».
Посылая на контроллер репорт из одного байта, можно управлять светодиодом, соответствующему номеру репорта.
Обработка приема данных идет в файле «usbd_hid_core.c» в функции USBD_HID_DataOut.
При нажатии кнопки на Discovery происходит прерывание, на компьютер отправляется репорт из одного байта с описанием состояния кнопки.
Проверить работу контроллера можно при помощи программы от ST, USB HID Demonstrator, которая позволяет принимать и отправлять репорты (скриншот есть на чешском сайте).

Дальше захотелось реализовать режим CDC — эмуляция COM-порта. Разработчики из ST выложили класс для CDC, но примера для работы с ним не было. Все нужные исходники опять же есть у чехов, правда в их коде я нашел ошибки, делающие проект неработоспособным.
Так же у них при нажатии кнопки в виртуальный COM-порт просто передается символ «A», я пошел немного дальше, и прикрутил printf. При работе программы в виртуальный порт каждую секунду передается строка «Hello, World!».
При передаче символов S и A в порт с компьютера, на плате зажигается и гаснет один из светодиодов.
Для работы в данном режиме, на компьютер нужно установить драйвер от ST: Vitual COM Driver

Поскольку в примерах к Discovery был класс для работы в режиме «Audio Device», я решил сделать из Discovery внешнюю звуковую карту — работающую на воспроизведение. В интернете нечего похожего не нашел, однако уже готовый такой пример есть у ST в библиотеке USB для STM32F105/7 and STM32F2xx. Все исходники там мало отличались, вся разница в основном только в используемом драйвере внешнего звукового чипа CS43L22. Драйвер там достаточно навороченный, позволяет передавать звук на чип через I2S и DAC контроллера, данные могут передаваться по прерываниям от I2S и при помощи DMA.
После того как проект был скомпилирован и прошит, возникла проблема — звук воспроизводился, но качество было просто отвратительным. После того, как я подключил осциллограф и запустил на компьютере генератор синусоидальных сигналов, я обнаружил что форма сигнала на выходе аудио-чипа явно искажена — четверть всего времени воспроизведения сигнал отсутствовал. Позже, после отладки и написания другого проекта, предназначенного только для воспроизведения звука, я обнаружил, что подобные искажения появляются, если функцию воспроизведения звука вызывать через равные промежутки времени — например из прерывания таймера, причем период работы таймера может быть значительно больше времени воспроизведения звука. Аудиоданные при этом передавались через DMA в модуль I2S(этот режим используется в примере от ST). Судя по всему, проблема явно связана с какими-то особенностями аудио чипа.
Для того, чтобы получить более приличный звук, я использовал DAC контроллера(аудио чип работает усилителем), звук при этом стал более-менее сносным, но одноканальным(воспроизводится только левый канал). Получить стерео звук можно только в режиме I2S. Я попробовал передавать звук по прерываниям от I2S — и искажения пропали. Правда, при воспроизведении данные от USB могут приходить в момент, когда звук еще воспроизводится, и иногда, насколько я понял, часть звуковых данных попадает в другой канал. Проявляется это как тихие щелчки, слышно их только в том случае, если звук в каналах различается.
Из-за вышеуказанных проблем, мой драйвер отличается от того, что выложен в примерах от ST. В данный момент можно переключать метод воспроизведения — через I2S и через DAC. Это можно сделать, изменив строчку
"__IO uint32_t CurrAudioInterface = AUDIO_INTERFACE_I2S;" в файле аудиодрайвера «stm32f4_discovery_audio_codec.c»
на "__IO uint32_t CurrAudioInterface = AUDIO_INTERFACE_DAC;"

Исходные файлы:
www.dropbox.com/s/pr201jqkweubb2e/my_proj.zip?dl=0
  • +1
  • 09 марта 2012, 01:37
  • citizen

Комментарии (41)

RSS свернуть / развернуть
Прикрепи примеры к статье, а то они через некоторое время протухнут.
0
  • avatar
  • Vga
  • 09 марта 2012, 05:08
Пытался уже, но по какой-то причине не получилось — пытаюсь прикрепить, пишет «Файл загружается», после чего на этом месте появляется прямоугольник с надписью «Null». Сообщений об ошибках не появляется.
0
Попробуй другой браузер.
0
Пробовал Оперу, Хром и IE — везде одинаково.
0
залей на дропбокс. оттуда никуда не денутся
0
При передаче символов S и A в порт с компьютера, на плате зажигается и гаснет один из светодиодов.

А вот эта функция в выложенном проекте не реализована(((
Автор, если можно, выложи проект с реализованной данной функцией.
Заранее благодарен!
0
Обновил файл на дропбоксе.
Действительно, забыл добавить папку «my_usb_cdc». Интересующая вас функционал реализуется расположенной в файле «usbd_cdc_vcp.c» функцией VCP_DataRx. В этом проекте данные на компьютер передаются без использования printf.
0
Спасибо огромное!!!
0
Здраствуйте! Озадачился сделать простейшее hid на этой платке, но сложность проекта сбивает. Может подскажете тупому, где в проекте demonstration задается class, subclass, InterfaceProtocol. Такие строки есть в файле usbd_hid_core и значения им присвоены соответствующие мыши, однако их изменение ни к чему не ведет — устройство остается мышью.
0
  • avatar
  • gip
  • 24 мая 2012, 18:27
Никто не подскажет, почему в функцию VCP_DataRx данные всегда поступают по одному символу, и соответственно их длина(Len) всегда равняется одному.
Как это пофиксить?
0
Большое Вам спасибо! Запустился сразу проект виртуального COM-порта my_usb_cdc_print. Смотрю через программу Compt — шлет Htllo World! каждую секунду. Все отлично. Но не могу заставить зажигаться и гаснуть никакой LED. Посылаю на F4Discavery через эту же Compt коды символов S, s, A, a — никакого эффекта. И в проекте не могу найти это место зажигания. Помогите, пож.!
0
А, простите, в комментариях нашел ответ. Но в тексте, конечно, надо отразить, что в каком проекте.
0
При компиляции не может найти cmsis_iar.h. У вас версия IAR 6.2 со встроенным CMSIS? У меня 5.4 версия. И еще при запуске говорит что используется неизвестный тул — PEMICRO_ID
0
Да, у меня IAR со встроенным CMSIS.
0
Уважаемый Автор, прошу выложить проект примера работы режима CDC для CoIDE.
Заранее багодарен!
0
не могу понять в чем проблема, заливаю проект my_usb_cdc_print все проходит без ошибок. А когда пытаюсь посмотреть передачу «Hello world» через Compt, ничего не происходит
0
  • avatar
  • iDez
  • 10 апреля 2013, 17:23
Проверьте дебаггером выполнение программы. Насколько я помню, данные принимаются при любых настройках порта — поскольку порт виртуальный.
0
Проверил дебагером, видно как на при каждом цикле в APP_Rx_Buffer записывается новая строчка Hello World, однако увидеть это через какой-нибудь терминал так и не удалось.
P.S. с проводом точно все в порядке, видел через него другие сообщения
0
У всех все работает, драйвер стоит? + драйвер может тупить.
0
Автор, а вы USB bulk еще не поднимали?
0
нет
0
… комментарии к статье большей частью о том как хреново крепятся файлы к статье.

По каким-то причинам ST не выложили документацию на работу с USB в контроллерах STM32F4

Лежит все на их сайте, кроме как под носом смотреть не научились.
Искать STM32 USB OTG Host and Device Library V2.0.0…
0
А для полного нуба как IAR понимает этот набор директорий как проект?
И более прямой вопрос что собирать чтобы получить usb звуковую карту?
0
В выложенной папке 7 вложенных папок. Две из них — Libraries и Utilities — общие для всех проектов. Остальные папки, начинающиеся на «my_» — папки отдельных проектов. То есть для запуска любого из проектов достаточно 3 папок — Libraries, Utilities и одной из «my_», папки должны находиться в одном месте.
В каждой папке «my_» есть своя вложенная папка EWARM, в которой лежат различные файлы проекта, в том числе и главный файл Workspase — с расширением ".eww". Этот файл и нужно открыть в IAR, после чего в нем открывается весь проект.
Для того, чтобы открыть проект воспроизведения звука через USB, достаточно открыть в IAR файл «STM32F4-Discovery_audio.eww» (папка my_audio_usb/EWARM), после чего должен открыться проект, который можно собрать и запустить.
Самый простой способ — прошить готовую прошивку «my_audio_usb/EWARM/Demo/Exe/STM32F4-Discovery_audio.hex»
0
Огромное спасибо.
Теперь буду пробовать достать DAC (PCM1795, PCM1792A) и ОУ (OPA627)

И решать грабли с питанием и прочим.

Интересно сильно будет отличаться общение с PCM1795 по i2C от общения с нашей CS43L22
так вроде оба получает данные по Serial порту
и управляются по I2C
0
Пересобрал проект в CooCox IDE (gcc 4.6.2). Заработало :-)) у меня теперь вопрос. Почему не используется DMA для i2s, так сделано специально? При воспроизведении слышно щелчки, которые зависят от установленного уровня громкости (подозреваю, что где-то проскакивают нулевые сэмплы/повторяются одни и те же сэмплы при обработке прерывания)
0
Я в свое время много экспериментировал, и у меня сложилось ощущение, что проблема с аудио-ЦАП. Щелчки возникали, если между пакетами передаваемых данных возникала пауза (даже очень маленькой длительности).
В тексте более подробно расписано, как я пытался с этим бороться. У меня получилось частично избавиться от искажений, использовав прерывания от таймера, который обеспечивает отсутствие задержек между передаваемыми байтами. Однако таймер проблематично синхронизировать с USB, из-за чего возникают тихие щелчки при воспроизведении стерео звука. (При использовании DMA, форма сигнала совсем по страшному искажается).
Библиотека воспроизведения звука для STM32F4-Discovery просто ужасная, с ошибками и странной мешаниной кода. Скорее всего именно из-за этого в STM не стали делать свой пример аудиокарты, хотя класс Audio Device для USB у них реализован.
0
специально проверил, зашив авторским бинарником — та же ерунда. придется копать глубже…
0
То есть, самое главное — не допустить, чтобы кодек остался без данных (применяя DMA и прерывания half transfer и transfer complete).
0
Проект USB Audio переделал под асинхронное воспроизведение с выделенной конечной точкой обратной связи. и заработало с DMA
0
А как насчет поделиться? Лучше в виде статьи, но и просто сорец пойдет.
+2
Насчет статьи — чуть позже. Предыстория проекта STM32F4discovery для пирата. В двух словах — давно интересуюсь FM-вещанием, захотел сделать «шарманку» на цифровых технологиях. Прошивка с исходниками:
drive.google.com/folderview?id=0B-j5bkNbrAIRdEE1OERxc0pDZ00&usp=sharing
+1
Небольшой апдейт. В выложенном ранее исходнике обратная связь не работала. Приношу свои извинения, по прежней ссылке обновил файлы stm32f4_discovery_audio_codec.c (добавил инициализацию TIM2 для измерения частоты SOFов) и usbd_audio_core.c (поправил дескрипторы USB, формирование пакета для конечной точки обратной связи)
0
Прикольно, что если ткнуть «положить в мой драйв», то оно само обновляется. Ты только, главное, не удаляй)
0
я б с удовольствием выложил здесь на сайт, но не умею
0
Для этого нужно топик катать, а не комментарий. К топику можно приаттачить файлы.
+1
Проект USB audio, собранный GCC, не работает. Если кто-то сталкивался с подобным, просьба отписаться. IAR зависимые проекты — печалька. Проверил System Workbench for STM32 последней на данный момент версии
0
Здравствуйте! Пытаюсь запустить проект my_usb_cdc на CooCox, всё компилится, прошивается. Но МК не попадает в обработчик прерывания OTG_FS_IRQHandler, устройство не инициализируется. Обработчик прерывания SysTick_Handler срабатывает. В какую сторону копать? В stm32f4xx_it.h объявлял обработчики usb, не помогло. Разрешал в main все прерывания и для каждой периферии, не помогло. Может в startup-файле собака зарыта? Прошу поделиться опытом и знаниями.

P.s. Создавал отдельно проект в IAR из папки my_usb_cdc, всё работает. В CooCox не заводится…
0
Думаю, надо смотреть в сторону настроек тактирования и настроек stack/heap — их нужно сделать побольше.
0
По тактированию: Когда создаю проекты в CooCox через wizard, то он обычно подсовывает файлы конфигурации (stm32f4xx.h и system_stm32f4xx.c) с HSE = 25 МГц, все значения настройки PLL в system_stm32f4xx.c тоже заточены под 25 МГц. Но сейчас файлы взяты из вашего проекта, а там всё, как и должно быть (8 МГц)… Везде HSE = 8 МГц, тактирование usb настроено на 48 МГц (все PLL правильно прописаны).
По стеку/куче: Сделал всё по инструкции из
forum.easyelectronics.ru/viewtopic.php?f=35&t=12720
www.coocox.org/forum/viewtopic.php?f=2&t=917
Игрался со значениями размера стека и кучи, безрезультатно…

P.s. Смотрел осциллографом, что на линии данных usb (d+). IAR: Как только вставляю usb, сразу появляются пачки импульсов. CooCox: никакой реакции.
0
Ваша наводка на тактирование меня спасла, спасибо!
Подвела меня копипаста и ограниченность знаний.
Пошел по шагам, значение RCC_Clocks.HCLK_Frequency в Coocox оказалось 160 МГц, а в IAR 168 МГц, т.е. система не проинициализировалась.
В main вставил SystemInit() — глупая ошибка.
Видимо, в IAR эта функция вызывается автоматом (прописана в startup). В CooCox приходится вызывать вручную.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.