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

    Некоторое время назад мне в очередной раз потребовался 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/RI;
    • поддержка 7 и 8-битной длины слова;
    • поддержка контроля четности;
    • 1, 1.5 и 2 стоповых бита;
    • совместимость со стандартными драйверами Linux, macOS и Windows;
    • подписанный INF файл для Windows XP, 7 и 8;
    • поддержка произвольных скоростей (более 2 Мбит/с);
    • сигнал TXA для управления трансиверами RS-485 (DE, /RE);
    • DMA на передачу и прием данных USART;
    • встроенный командный интерпретатор для конфигурации;
    • нет зависимостей от сторонних библиотек кроме CMSIS;
    • проект с открытым исходным кодом, лицензия MIT;

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


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

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


    *******************************
    * Configuration Shell Started *
    *******************************
    
    >uart 1 tx output pp dcd active low pull up
    >

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


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


    Signal Direction UART1 UART2 UART3
    RX IN PA10 PA3 PB11
    TX OUT PA9 PA2 PB10
    RTS OUT N/A PA1 PB14
    CTS IN N/A PA0 PB13
    DSR IN PB7 PB4 PB6
    DTR OUT PA4 PA5 PA6
    DCD IN PB15 PB8 PB9
    RI IN PB3 PB12 PA8
    TXA OUT PB0 PB1 PA7

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


    Сигнал TXA (TX Active) служит для управления микросхемами трансиверов RS-485 (DE, /RE). TXA активен во время передачи данных и переключается в неактивное состояние не более чем за 0.6 мкс после завершения передачи. Это соответствует спецификациям RS-485 на скоростях до 920 кБод c почти двукратным запасом по времени переключения.


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


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


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


    Подробная документация, исходный код и собранная прошивка доступна в репозитории проекта на GitHub.


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


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


    Обновления


    Поддержка RI


    28.11.2020


    Добавил поддержку сигнала RI на всех портах (спасибо plyatov), добавил в статью описание сигнала RI.


    Устранил ошибку, приводящую к возможному повреждению данных на приеме


    01.12.2020


    Код не проверял готовность BULK IN endpoint перед отправкой CDC ZLP-пакетов. При определенных условиях это могло приводить к повреждению принимаемых данных. Очень странно, но эта ошибка в реальной жизни проявлялась существенно реже, чем можно было бы ожидать. Исправлено в версии 2.1.1.


    Поддержка управления трансиверами RS-485


    02.12.2020


    Добавил поддержку управления трансиверами RS-485 в версии 2.2.0, обновил статью, добавил описание сигнала TXA. Спасибо dernuss и остальным тем, кто просил сделать эту фичу.

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 70

      0
      Сразу спрошу — на каждый канал два endpoint? — а то я сейчас думаю, как на 4-1 endpointa натянуть 2 uarta и никак :(.
        +2
        Один CDC требует для своей работы следующие endpoints: BULK IN, BULK OUT, INTERRUPT IN. В STM32F103C8T6 есть 8 двунаправленных endpoints. Один CDC ACM занимает два из них. Если надо ужаться и не жалко потерять возможность отправки notifications, то в качестве INTERRUPT IN endpoint в дескрипторе можно указать несуществующий номер endpoint. Таким образом на STM32F103C8T6 можно реализовать 7 CDC. Если надо ужаться, но при этом не хочется терять возможность отправки notifications, то рекомендую попробовать поделить один INTERRUPT IN endpoint между всеми CDC устройствами. Из стандарта не следует, что это не будет работать, более того, в структуре notification есть поле для номера интерфейса. Но я не тестировал такой вариант с реальными драйверами и ничего не могу сказать о том, как это работает на практике.
          0
          То есть Вы сделали IN OUT совмещенным на одном endpoint и получили 3*2=6 требуемых.
          О несуществующем для notification я уже думал, но что скажет драйвер?
          А вот общий канал управления для всех — это очень интересно, тогда я уложусь 1+1+2*1=4.
            0

            Драйвер ничего не скажет, даже не узнает, что этот endpoint в действительности отсутствует. Драйвер в этот endpoint ничего сам не отправляет, это IN endpoint. Но это все-таки хак с точки зрения периферии микроконтроллера. Вот пример того как это сделано: https://github.com/eddyem/stm32samples/tree/master/F1-nolib/SevenCDCs

              0

              Хост не отправляет, хост спрашивает и не получает от МК ничего (МК не понимает, что от него хотят — конечная точка не существует и не обрабатывается)

                0

                Да, я несколько некорректно выразился. Хотел подчеркнуть, что это IN endpoint. Естественно, в USB инициатором любого обмена выступает хост.

        0

        Rs485 было бы более полезно(ну точнее пин, переключающий phy), по крайней мере для меня.

          0

          Без аппаратной реализации не заработает, а ее на stm без внешних микросхем не сделаешь.

            0
            Rs-485 можно сделать аппаратно на STM32F0, я на 042 делал.
              0

              Почему нельзя? Вроде можно, у ST даже есть App note AN3070 на эту тему. Понятно, что это не так быстро, но все же лучше, чем ничего.

                0

                Да не, это не то, это про то как DE управлять, если используешь DMA. Но микросхема-драйвер (типа ADM485) все равно нужна для физического уровня. Подключить A и B к самой СТМке нельзя, а вот на PSoC скорее всего можно (но надо написать код драйвера RS485)

                  0

                  Да, тогда понятно. Вы правы, без драйвера никак.

                    +1

                    Теоретически можно, но лично мне трудно оценить, на какую скорость хватит быстродействия МК. Если напряжение на линии соответствует питанию МК то там по факту только определять, какая из линий выше по напряжению. Возможно можно встроенный в мк компаратор использовать. Или АЦП. В любом случае нужна аналоговая периферия. На цифре тоже работать будет, но на небольшом расстоянии.
                    Передача проще — 1 и 0 цифровой на A и B.


                    Но опять же, под PSoC это проще сделать, чем кодить на Си и использовать стандартную встроенную периферию.

                      0

                      Софтовая реализация RS-485 могла бы быть отличными упражнением, но для практического применения боюсь будет слишком медленно. Особенно, если надо сделать больше одного порта.

                        0
                        Софтовая реализация RS-485 могла бы быть отличными упражнением

                        Вот да, постоянно тревожит эта тема, надеюсь как-нибудь занятся ей в свободное время. Плюс, можно будет сравнит это с аппаратной реализацией в PSoC и написат статью.


                        но для практического применения боюсь будет слишком медленно

                        Если ограничить дальность столом, то есть использовать только для отладки, должно работать на цифровых входах быстро.


                        Особенно, если надо сделать больше одного порта.

                        Если скорость одинаковая, и тактировать все одним таймером, то расходы на каждый дополнительный порт будут очень низкие. Только память для хранения состояния (прием/передача, номер бита и указатели на буферы)

              +1

              В таких проектах очень важна мотивация. А что может мотивировать лучше, чем создание устройства, которым в первую очередь будешь пользоваться самостоятельно? Мне в повседневной жизни RS-485 совершенно ни зачем не нужен, а вот RS-232 очень даже. Но если вдруг понадобится RS-485, и я не найду подходящего мне устройства, то обязательно займусь.

                +1

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

                  +1

                  Добавил поддержку RS-485, обновил статью.

                    0
                    для работы с RS485 скорость 460 кБод/сек можно выставлять на всех 3х портах?
                      0

                      Я постарался (и продолжаю стараться) сделать обработчик прерывания от USART как можно более коротким, и с хорошей вероятностью все будет работать на 460 кБод на 3-х портах одновременно. Но мне всё-таки нужно больше обратной связи от тех, кто будет это использовать в реальной жизни. Просили сделать RS-485 — я сделал. Теперь я, в свою очередь, прошу протестировать результат :)


                      <зануда моде он>
                      Бод = это бит/с, поэтому бод/с — это не скорость, это ускорение :)
                      </зануда моде офф>

                        0
                        ну да с Бодом ошибся.
                        Протестировать могу не скоро, только в следующем году.
                        Надо сначала платку развести сразу с phy

                        Есть у меня мысль сделать простые платки и микросхемами ft4232/2232 и заодно с stm32f1 с USB-C для RS485 и JTAG. С гальванической изоляцией.
                          +1

                          Довел время сброса TXA до 0.6 мкс применив bit banding. Теперь еще больше шансов, что все заработает на 460 кБод на трех портах одновременно.

                  +2

                  Я человек простой — вижу stm вместо ардумны — ставлю плюс не читая даже код.


                  P.S. когда-нибудь у меня хватит времени спроектировать DIY-NES kit на основе Blue pill.

                    +2

                    Возможно кому то пригодится FT4232 — USB to 4 UART.
                    Главные его преимущества:


                    • не нужно прошивать;
                    • полноценные UART;
                    • скорости повыше, т.к. USB High Speed.
                      +1

                      Вы забыли упомянуть, что FT4232 — это микросхема, а не готовая плата. Да, ее не нужно прошивать, но зато её нужно к чему-то припаять. Максимальная скорость действительно впечатляет — 12Mbaud, согласно datasheet. Но и цена кратно больше: отладочная плата на AliExpress стоит 800 руб. против 120 руб за STM32 Blue Pill. И если можно, расскажите поподробнее про "полноценность". Единственное различие, которое бросилось в глаза — это наличие на FT4232 сигнала RI, но с другой стороны, на FT4232 отсутствует возможность тонкой настройки входов/выходов (полярность, подтяжка, тип выхода).

                        0
                        А я и не заявлял, что это готовая плата.
                        Готовых плат на этом чипе полно на Aliexpress. Хочешь на 2 порта (FT2232H), хочешь на 4 (FT4232H).
                        Я не говорю, что ваш проект чем то плох.
                        Бывают ситуации когда время дороже, чем деньги и тогда проще купить готовый прибор не требующий дополнительных телодвижений для использования.
                          0
                          Почитайте datasheet и увидите, что FT4232H — это не только UART-ы с хорошими буферами FIFO, но и GPIO которые много где применяются (BitBang JTAG, SPI, I2C и т.п.).
                          Так-же есть автоматический контроль потока для RS485, настраиваемая мощность выходов (4-16мА).
                          Я давно использую эту микросхему и доволен её работой и поддержкой в Linux и Win32.
                            0

                            Да FT4232H (FT2232H) — это прекрасная микросхема, кто бы спорил. И datasheet на нее я читал. Просто, как говорится, right sizing, для одних применений лучше она, для каких-то других — вариант на STM32 Blue Pill. Особенно, если последняя уже валяется в ящике стола. Опять же, у FT GPIO, а у STM32 Blue Pill возможность установки выходов в открытый сток… Под каждую задачу — свое решение.

                            +1
                            «Полноценный» — это порт UART со всеми сигналами RXD, TXD, /RTS, /CTS, /DTR, /DSR, /DCD, /RI.
                              0

                              В моем варианте, из всего перечисленного, отсутствует только /RI. Не самый нужный сигнал. "Полноценность" не сильно пострадала. Зато присутствует возможность управления параметрами сигнальных линий. Впрочем, надо будет подумать о реализации и /RI тоже, благо это делается тривиально. Спасибо за подсказку!

                                0

                                Добавил поддержку RI, обновил статью. Спасибо!

                                  0
                                  у FT4232H ещё TXDEN есть сигнал:)
                                    +1

                                    Да, похоже от судьбы не уйдешь и придется все-таки делать поддержку управления конвертерами RS-485. Базово уже сделал, но не выкладывал. Там надо выдержать достаточно жесткие тайминги по управлению DE при переходе от передачи к приему и я сейчас пытаюсь это обеспечить.

                                      0
                                      ))
                                      там вроде просто, у st есть AN3070 на эту тему
                                        0

                                        Спасибо, я уже тоже выше про этот AN написал. Примерно так и буду делать.

                                        0
                                        Если есть возможность использовать ногу RTS (но на ней обычно слишком нужные функции висят), то аппаратно будет работать прекрасно.
                                        А вот если нет — то придется делать софтово (натыкаясь на грабли).
                                          0

                                          У STM32F072 и STM32F103C8T6 разные USART. У первого есть режим в котором сигнал RTS может управлять DE(/RE) RS-485, а у второго — нет. В целом, USART на STM32F072 более продвинутый. Но что поделать, ведь STM32F103C8T6 гораздо более распространен и дешев, поэтому выбор очевиден.


                                          Что касается граблей, то насколько я понял все грабли у вас заключались в том, что 5-ти вольтовый MAX485 то ли работал, то ли нет с 3.3 вольтовыми уровнями (или питанием?). Или я что-то пропустил? Может в комментариях?


                                          В-общем, я пока работаю над софтовым управлением TXA (DE, /RE). Пришлось перепахать всю прошивку, отказаться от прерываний USB в пользу поллинга, задействовать вытесняющие прерывания и много всего по мелочи. Когда-нибудь потом напишу статью об этом.


                                          А пока задержка переключения TXA по окончанию передачи составляет менее 1 мкс. Измерено осциллографом на одном из портов на фоне занятых постоянной передачей двух других. Это позволяет работать с RS-485 на скоростях не менее 460 кБод и на мой взгляд, это очень прилично. Хотя я собираюсь еще немного ужаться.

                                            0

                                            Думаю, стоит пока остановиться. Уже слишком круто)

                                              0

                                              Я не остановился и довел задержку до 0.6 мкс. Вот на этом пока остановлюсь :)

                                            0

                                            Кстати, по поводу ваших "граблей" в статье. Я посмотрел ваш код на GitHub и мне бросилось в глаза, что у вас USART RX настроен как floating. А он должен быть подтянут к Vcc. И тогда все будет хорошо, не будет никакого "мусора" и не надо будет запрещать прием на время передачи.

                                0

                                И ещё вопрос, какой максимальный размер посылки можно передать?

                                  0

                                  Извините, но я не понял ваш вопрос. Максимальный размер какой посылки имеется в виду?

                                    0

                                    Может я что то тож не понимаю, но наверное нельзя сразу отправить несколько мегабайт в Stm32 с какого нибудь устройства по uart одной посылкой? Наверное можно только короткие посылки передавать, например по 1килобайту? Вот у cp2102 есть буфера 640B TX Buffer
                                    576B RX Buffer

                                      0

                                      В этом проекте буфера на приём / передачу равны 1024 байтам. Если ПО успевает вычитывать данные из последовательного порта быстрее, чем они поступают по uart, то все будет хорошо. Если нет, то однажды случится переполнение буфера и часть данных будет потеряна. О таком событии прошивка сообщает хосту. На тестах я передавал многие мегабайты на скорости более 2 Мбит/с с порта на порт, и никаких переполнений не возникало. Но, конечно, если ПО или ОС «задумается», то шанс потерять данные есть. Если нужно гарантированно не терять данные, следует использовать аппаратный контроль потока (RTS/CTS).

                                        0
                                        всё понятно, а есть возможность увеличить буферы например до 2...4к?
                                          0

                                          Если увеличивать только буфера на прием, то до 2 Кбайт точно можно. До 4 Кбайт возможно можно, надо смотреть. Только я не понимаю, зачем? Какую проблему вы хотите таким образом решить?

                                            0
                                            скорее не решить, а избежать. Многие микросхемы, например ft2232, имеют 4к буффера. Кто знает, вдруг это где то надо или используется
                                              0

                                              Максимальная скорость FT2232 по RS232 — 12 Mbaud, это оправдывает наличие больших буферов для того, чтобы не потерять данные в ситуации, когда мы приняли сразу большой пакет, а ПО не успело среагировать. Максимальная скорость, которая у меня получилась на STM32F103C8T6 — около 2 Mbaud, то есть в 6 раз медленнее. При этом, отношение размера буфера к максимальной скорости в моем случае даже выше.


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


                                              Однако, если вы действительно встретитесь с проблемой правильным решением которой будет увеличение размера буферов, я с удовольствием это сделаю.

                                                +1
                                                ок) хорошо что на 485 согласились) буду ждать коммита
                                                  +1

                                                  Сделал экспериментальную версию, обновил статью.

                                              0
                                              В STM32F103 ограничивает скорость USB FullSpeed до 12 Мбит/с и размеры Endpoint 64 байта. У FT используется USB HighSpeed 480МБит/с и размер endpoint 512 байт. Когда в STM32 заполнится FIFO, то должно сработать ограничение — надо подождать, для этого RTS/CTS и нужны.
                                              В целом проект очень интересный, только код без комментариев — это как машинный код, кроме компилятора его никто не понимает. Даже автор через год забудет.
                                                0

                                                У нас с вами разный подход к комментированию кода. Я считаю, что сам код должен быть написан так, чтобы был понятен без комментариев. От этого у меня в коде длинные и осмысленные названия имен переменных, функций и так далее. Комментарии я использую для описания важных и неочевидных вещей, когда это действительно требуется, а также для отделения логических блоков в коде друг от друга. До сих пор я как-то умудрялся разбираться в своих проектах даже 20 летней давности. И другие люди тоже разбирались без проблем. А еще есть blame в Git и commit messages…


                                                А если уж совсем позанудничать...

                                                То я посмотрел код вашего проекта MIDI2USB, давайте для примера возьмем main() из main.c


                                                WDT_Init();            // Disable WDTimer (not used)
                                                PORT_Init();            // Initialize ports (UART, LEDs)
                                                SYSCLK_Init();            // Set system clock to 48MHz
                                                UART0_Init();            // Initialize UART0 @31250, 8-N-1
                                                USBD_Init( &usbInitStruct );            // Initialize USB, clock calibrate
                                                LED_IN  = 1;            // Blink LED
                                                LED_OUT = 1;            // Blink LED
                                                IE_EA   = 1;            // Global enable IRQ

                                                Если у вас функция WDT_Init не инициализирует watchdog, а запрещает его, функция PORT_Init() инициализирует не порт, а порты и так далее, то да, такой код лучше комментировать.


                                                Я уже не говорю о том, какие проблемы бывают при расхождениях в коде и комментариях. И о том, что код вызывающий UART0_Init() не должен и не может знать о том что это на самом деле "// Initialize UART0 @31250, 8-N-1" в случае если он не передает эти параметры явно при вызове функции.


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

                                                  0
                                                  Вы пишите «очень рассчитываю на обратную связь», а сами токсично реагируете и в мой огород кидаете камень «А у вас негров линчуют».
                                                  Я отвечу на критику
                                                  Проект реализован на контроллере EFM8EB20F64 — это современный разогнанный 8051 от SiLabs.
                                                  1) Для инициализации и настройки периферии используется конфигуратор (вроде CubeMX, для тех кто не в теме), это такой норматив, правило в этой среде разработки. И этот конфигуратор генерирует код функций: WDT_Init(); PORT_Init(); SYSCLK_Init(); и т.д. Так принято в SiLabs 8051. В Windows API, например, принято имена давать lpszClassName; Никто не возмущается.
                                                  2) Функции инициализации не имеют аргументов. Более того, в каждом проекте они разные. Поэтому комментарий дать — хорошая практика.
                                                  3) Ядро 8051 живёт более 40 лет и есть много кода для него. Раньше (и иногда сейчас) используются «магические константы» для записи в регистры. Это не красиво и не понятно. Эта проблема частично решается оформлением кода в два столбца с комментариями. Это не я придумал, это традиция. «When in Rome do as romans do».
                                                  4) Оформление дескрипторов у меня выполнено в стиле SiLabs и на версии языка С, который понимает IDE.

                                                  Критиковать ваш код в ответ не буду, но с указателями и типами данных у вас помойка в коде. Ищите сами. Я из темы удаляюсь.
                                                    0

                                                    Есть разница между конструктивной критикой и "бла-бла-бла, в вашем коде не хватает комментариев, поймет только компилятор, а автор все забудет через год". Первое — приветствуется, второе — неприемлемо. А комментарии в стиле: "но с указателями и типами данных у вас помойка в коде. Ищите сами." — это вообще ни о чем. Однако, если бы вы написали что-то в стиле: "вот тут сделано неправильно потому-то и потому-то", то я сказал бы вам огромное спасибо. Если бы вы написали "в таких условиях возникает вот такая ошибка, повторять так", я бы вообще прыгал до потолка от радости. Конечно, если бы это было действительно неправильно и у меня не было бы причины сделать именно так.


                                                    1. Валить все на конфигуратор не стоит, CubeMX и не такую еще дичь генерит, но это не значит что его использование является обязательным. А в WinAPI как раз очень разумная, не близкая мне лично, но разумная политика названия переменных;
                                                    2. Правильно, но не в том месте в котором она вызывается. Кончится это тем, что один программист поправит функцию инициализации, а вот про все места из которых она вызывается даже не подумает. А другой программист потом будет очень рад, потратив пару часов на осознание того факта что в комментарии написано одно, а функция делает другое.
                                                    3. Традиция, так традиция. Но мне-то какое дело до ваших традиций?
                                                    4. Опять же, тот факт, что у вас что-то оформлено в стиле SiLabs никак не делает ваши дескрипторы более читаемыми. Хотя да, я понимаю, есть еще возможные ограничения компилятора.

                                                    А камень в ваш огород я не кидал, я просто указал на конкретные проблемы вашего стиля кода и комментирования, со ссылками на конкретные места в вашем коде, объяснил к чему это потенциально приводит.


                                                    И я правда не считаю ценными советы по оформлению кода от человека с таким качеством кода как у вас. Покажите пример, а если нет — тогда действительно, вы все сделали правильно удалившись из темы.

                                                  0

                                                  Я 1 мбайт в секунду максимум выжимал полезных данных. Проц тот же что и у сабжа

                                                    0

                                                    По USB? А что еще с этими данными происходило? Чем еще прошивка занималась, расскажите, пожалуйста. Это интересно!

                                                      0

                                                      Да по usb. Я использовал режим bulk.
                                                      Просто кидал с хоста данные, в Stm32 расшифровывал и передавал назад. Очень просто. Типа электронного ключа кто то меня попросил сделать

                                                        0

                                                        Ага, понял, спасибо!

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

                                          Спасибо! Я не стал выделять конфигурацию в один порт для того, чтобы не терять в производительности. Хотя, здесь есть пространство для дебатов. Дело в том, что в stm32f103c8t6 размер USB packet buffer memory равен 512 байтам. 112 из них заняты buffer description table (для 7 endpoints), сами endpoints занимают еще 384 байта. При этом, уже даже тут пришлось несколько ужаться, и размеры BULK IN/OUT endpoints для порта 1 сделать равными 32 байтам против 64 байт у остальных портов. Это несколько ограничивает производительность первого порта. Таким образом, у нас осталось всего 16 байт, которые все и уйдут на дескриптор 8-го endpoint. Надо откуда-то взять еще хотя бы 16 байт. В принципе, можно уменьшить два из трех INTERRUPT IN endpoints до 8 байт и передавать уведомления о состоянии порта за два «захода». Но мне не захотелось так делать вот почему: конфигурационный порт нужен далеко не всем и используется относительно редко. Я не захотел выделять для него на постоянной основе ресурсы, которые могут помочь увеличить производительность при нормальной работе.


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


                                          С другой стороны, пока я все это писал, я понял, что у меня есть аж 16 свободных байт, а текущий размер control EP0 – 8 байт. Будет лучше инвестировать эти свободные байты туда.

                                          0
                                          Спасибо! Интересный проект. Сам пользуюсь для этой цели преобразователем U-620 от ST Lab. 8 полноценных портов RS-232 на одном USB, и с внешним блоком питания.
                                            0

                                            Спасибо, не знал про U-620. Мощная штука! Но мне не подходит: мне в первую очередь требуются TTL уровни.

                                            0

                                            Очень понравилось на плиске с usb девайсом играться — 16 конечных точек в двух направлениях, хайспид и никаких дурацких ограничений. Но это, как говорится, если usb — важная часть проекта, например, аудио многоканальное.

                                              0
                                              А можно так с CDC + MSC да так чтоб под cmsis?
                                              Оффтоп
                                              Поставил бы плюс, но нечем
                                                0

                                                Я вряд ли буду это делать. У меня в планах выкинуть один из последовательных портов и попробовать добавить туда простенькую аудиокарту: один вход с использованием ADC, один выход с использованием таймера в режиме ШИМ. И тогда получится интерфейс для радиолюбительских трансиверов, для работы во всяких цифровых модах типа FT8. Но пока сложно сказать, когда я это сделаю.

                                                  0
                                                  Я хочу сделать восстановлялку данных с SD
                                                +1
                                                Здорово вышло!
                                                А может возможно пробросить напрямую, как хаб USB, к китайской звуковой? Итого 2 порта и проброшенный USB для звуковой карты, как раз для трансивера. Не уверен, что ШИМ и ADC встроенные будут работать как надо.

                                                Собрал, адаптировал резистор 10k -> 1.5. Работает, правда при нажатии «отключить» (использую CoolTerm) виснет, пока не выдернешь USB или сброс не нажмешь. В своих поделках я дергал отдельной ногой контроллера подтянутой на D+, чтобы USB понял рестарт.
                                                  0

                                                  Мне интересно именно ADC и ШИМ попробовать. Может и не заработают. Посмотрим. По поводу зависания — интересно, попробую повторить. А на какой ОС вы работаете?

                                                    0

                                                    Повторил под Win.

                                                    0

                                                    Исправлено в версии 2.3.3, пожалуйста, обновитесь.

                                                  Only users with full accounts can post comments. Log in, please.