Полноценный трехпортовый USB-Serial адаптер на STM32 Blue Pill (STM32F103C8T6)

?v=1

Некоторое время назад мне в очередной раз потребовался USB-Serial адаптер. И не просто адаптер c RX/TX, а чтобы еще присутствовали управляющие сигналы. И не один UART, а несколько. И еще желательно, в виде одного композитного устройства, чтобы все это хозяйство не занимало больше одного USB-порта. Так и началась эта история…

Готовые устройства из тех, что можно приобрести в магазине, меня не вдохновили. Либо дорого и сложно найти в продаже, либо не подходят по одному или нескольким критериям выше. Композитных USB-Serial адаптеров в дешевом сегменте я и вовсе не смог найти. Зато на столе обнаружилась отладочная плата STM32 Blue Pill на микроконтроллере STM32F103C8T6. Сверившись с документацией, я убедился, что этот микроконтроллер содержит в себе все, что мне нужно для полного счастья. А именно: интерфейс USB 2.0 full-speed, три USART, семиканальный DMA контроллер и достаточное количество линий GPIO для реализации всех интересующих меня управляющих сигналов.

Осталось только раздобыть соответствующую прошивку, которая превратит безжизненный кусок железа в нужное и полезное устройство. И тут меня поджидало большое разочарование: оказывается, не смотря на бешеную популярность этого микроконтроллера и отладочной платы, никто до сих пор так и не сделал ничего подобного. Вернее, попытка была, но это скорее экспериментально-образовательный proof-of-concept, а не законченный продукт. Чего только стоит блокирующая передача данных по UART: один порт передает, остальные ждут. Нет, этот микроконтроллер определенно заслуживает большего! Пришлось засучить рукава и написать прошивку самому.


Что у меня получилось

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

Что реализовано:


  • три независимых последовательных порта;
  • поддержка аппаратного контроля потока (RTS/CTS) на двух из трех портов;
  • поддержка управляющих сигналов DSR/DTR/DCD;
  • поддержка 7 и 8-битной длины слова;
  • поддержка контроля четности;
  • 1, 1.5 и 2 стоповых бита;
  • совместимость со стандартными драйверами Linux, macOS и Windows;
  • подписанный INF файл для Windows XP, 7 и 8;
  • поддержка произвольных скоростей (более 2 Мбит/с);
  • DMA на передачу и прием данных USART;
  • встроенный командный интерпретатор для конфигурации;
  • нет зависимостей от сторонних библиотек кроме CMSIS;
  • проект с открытым исходным кодом, лицензия MIT;

Командный интерпретатор позволяет настраивать следующие параметры:


  • тип выхода: двухтактный, открытый сток;
  • тип подтяжки входных линий: вверх, вниз, плавающая;
  • инверсия для управляющих сигналов: активный высокий/низкий;

Командный интерпретатор активируется на первом CDC порту при подключении пина PB5 к земле, поддерживает часть управляющих последовательностей ANSI (стрелочки, backspace), и принимает вполне дружелюбные на вид команды:

*******************************
* Configuration Shell Started *
*******************************

>uart 1 tx output pp dcd active low pull up
>

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

Распиновка вышла следующей:

Пины выделенные жирным шрифтом являются толерантными к 5 вольтам.

К сожалению, реализовать RTS/CTS на UART1 не вышло из-за того, что соответсвующие пины заняты сигналами USB. Можно было вывести RTS на какой-нибудь другой пин, поскольку RTS управляется программно, в зависимости от степени заполнения кольцевых буферов на прием, но порт c RTS и без CTS мне показался странной штукой и я решил, что так делать не надо.

Проект написан на языке C, и подразумевает использование arm-none-eabi-gcc для сборки. Я использовал специфичный для GCC синтаксис атрибутов и расширения языка С. Совместимость проекта с проприетарными компиляторами меня не интересует, но если кто-то считает это важным, то я готов принять соответствующий пул-реквест.

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

Подробная документация, исходный код и собранная прошивка доступна в репозитории проекта на GitHub: https://github.com/r2axz/bluepill-serial-monster


Дальнейшие планы

Нет предела совершенству и этот проект — не исключение. В каких-то местах код можно было написать чище, понятнее и эффективнее. Я обязательно этим в какой-то момент займусь. Кроме того, я очень рассчитываю на обратную связь от пользователей для поиска и устранения возможных багов.

© Habrahabr.ru