Обновить

SoftSerial: Программный UART на STM32

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели13K
Всего голосов 18: ↑18 и ↓0+28
Комментарии46

Комментарии 46

ЗакрепленныеЗакреплённые комментарии

Ещё вспомнилось, был такой микроконтроллер, Тезей. Ангстрем делал. По сути, это было небольшое развитие встраиваемого ядра управления, теми же смарт-картами. Но вот решили сделать микроконтроллер, но UART туда не вставили, не было его изначально. И - только программный... :-)

На Intel 8051 9-битовый режим был довольно популярен, поскольку там можно было настроить приёмную часть UART, чтобы принимались только посылки с единицей в 9-м бите, и использовать такие посылки в качестве маркера начала информационного пакета (и туда же класть адресный байт — если пакет адресован другому узлу, после анализа адресного байта последующие данные могут игнорироваться аппаратно, если же пакет нужно принять, можно разрешить приём посылок с данными до конца пакета). Но вот при необходимости обеспечить связь с такими устройствами с использованием более обычных реализаций UART иногда приходилось как раз заниматься плясками вокруг бита чётности.

Исходные коды прошивки программного UART

Куда-то пропали. 404, говорит.

Это не совсем честная проверка:

При соединении двух разных устройств скорости могут отличаться до 3%. (поэтому встроенный в STM RC-генератор производитель и пытается калибровать до 1,5%)

В случае появления семпла 0 переходим в состояние rec и остаемся в rec пока не примет (1+8+1+2=12 бит).

Поэтому логичнее было бы после появления сэмпла 0 взять 1+8+1+0,5 битовых интервалов. То есть, перейти в IDLE уже на середине первого стоп-бита. Тогда и второй стоп становится ненужным.

Ещё из оптимизаций: через DMA читать не весь GPIO->IDR, а только нужный байт. Дока на STM32F4 это позволяет, вроде. И тогда ядро может обрабатывать сразу по 4 сэмпла. По крайней мере это разгрузит ядро в IDLE.

А после появления 0 становится известно, какие именно сэмплы находятся на середине битовых интервалов, остальные сэмплы можно не обрабатывать. Тут загрузка ядра и так выходит меньше, чем в IDLE.

В FPGA я приём немного по-другому делал: сначала побитный CDR, потом уже обработка кадра. Так логика выходила проще. В мк это не так удобно - слишком много мелкой работы.

 Зачем в UART интерфейс заложили 7-битный режим?

От 5 до 9, насколько я помню. А 7 так вообще классика, кодирование символов в терминалах 7-ю битами было. А 5 - так вообще от кода Бодо.

В программе TeraTerm можно выбрать только 7 или 8 бит.

Ну вот, например, настройки порта UART микроконтроллера RP2040, он же Raspberry Pico. От 5 до 8 бит. 9-й - бит чётности, но ничего не мешает его использовать как дополнительный информационный.

9-й - бит чётности, но ничего не мешает его использовать как дополнительный информационный.

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

Но пишут, что таки есть реализации с честными 9 информационными битами.

На Intel 8051 9-битовый режим был довольно популярен, поскольку там можно было настроить приёмную часть UART, чтобы принимались только посылки с единицей в 9-м бите, и использовать такие посылки в качестве маркера начала информационного пакета (и туда же класть адресный байт — если пакет адресован другому узлу, после анализа адресного байта последующие данные могут игнорироваться аппаратно, если же пакет нужно принять, можно разрешить приём посылок с данными до конца пакета). Но вот при необходимости обеспечить связь с такими устройствами с использованием более обычных реализаций UART иногда приходилось как раз заниматься плясками вокруг бита чётности.

На Intel 8051 9-битовый режим был довольно популярен, поскольку там можно было настроить приёмную часть UART, чтобы принимались только посылки с единицей в 9-м бите, и использовать такие посылки в качестве маркера начала информационного пакета

STM32 тоже умеют генерить 9битнй payload для UART.

Большинство устройств, управляемых по последовательному порту, имеет ограниченный набор вариантов настройки. Вот авторы программы и решили не заморачиваться. Но в реальности встречается всякое, особенно если достаточно старое. И пятибитных кодировок символов хватает.

можно наверное найти какую-нибудь ещё более корявую терминалку, которая даже 7 бит не умеет, но зачем?

TeraTerm, пожалуй, лучшая терминалка в своем роде. По крайней мере TeraTerm лучше PuTTY.

А как же Terminal by Bray?

В ней нет раскраски логов кодами цветов.

Для бинарных протоколов - нормально.
Для текстовых - нет.

он захлёбывался от непрерывного потока данных даже на 115200

Да. Я это помню. Terminal уходит в туман и Windows предлагает остановить процесс.

К слову Terminal by Bray - это мой самый первый терминал, которым мне пришлось пользоваться.
Далее был SerialKingdoom, HTerm, RealTerm, Putty, Hercules и наконец TeraTerm, лучше которого ничего больше пока не найти.

putty это ssh, и вообще plink для туннелей в первую очередь.

с железками через последовательный порт у меня общаются в основном различные скрипты, руками подключаться приходится только для проверки работоспособности, проверить что с данными настройками порта железка отзывается на условный *IDN? (некоторым древним железякам надо ещё RTS/DTR обязательно подёргать чтоб ожили), так что минималистичный termite более чем устраивает

закладывать в железку всякие \033[38;2;255;82;197;48;2;155;106;0mHello чтобы оно только в определённых терминалах отображалось - имхо какая-то дичь.

Ещё вспомнилось, был такой микроконтроллер, Тезей. Ангстрем делал. По сути, это было небольшое развитие встраиваемого ядра управления, теми же смарт-картами. Но вот решили сделать микроконтроллер, но UART туда не вставили, не было его изначально. И - только программный... :-)

Ещё вспомнилось, был такой микроконтроллер, Тезей. Ангстрем делал. По сути, это было небольшое развитие встраиваемого ядра управления, теми же смарт-картами. Но вот решили сделать микроконтроллер, но UART туда не вставили, не было его изначально. И - только программный... :-)

Тесей это ведь КР1878ВЕ1? Там даже DMA нет (

 

Очень похоже на то.

Тезей. Ангстрем делал. По сути, это было небольшое развитие встраиваемого ядра управления, теми же смарт-картами.

Вот интересно как Тесей (КР1878ВЕ1 ) в корпусе DIP-18 мог поместиться в смарт карту?

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

Он и не помещался, для смарткарт были свои контроллеры, но с той же архитектурой ядра

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

Так Микрон и Ангстрем - разные заводы.

Ещё вспомнилось, был такой микроконтроллер, Тезей. Ангстрем делал. 

Как Вы вообще узнали про такой экзотический микроконтроллер?

Думаю, для этого достаточно заниматься микроконтроллерами достаточно давно

Помню, на DSP TI C55x делал программный uart.

Не, DMA там не нужен был мне, там был конечный автомат в обработчике прерывания.

Прерывания от аппаратного таймера и GPIO. Так?

Помню, на DSP TI C55x делал программный uart.

Почему? На OMAP5910 же есть аж три аппаратных UARTа.

Потому что у меня был не OMAP.

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

А скорость - хз, 15 лет назад дело было.

Помню, на DSP TI C55x делал программный uart.

Какой максимальной битовой скорости Вам тогда удалось достигнуть?

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

програмный приём относительно сложный, а для отладки зачастую достаточно только отправки, я делал это ещё на пик12

  для отладки зачастую достаточно только отправки, я делал это ещё на пик12

Никак не могу с Вами согласиться.

Представьте прошивку 320 kByte, которая собрана из 80...120-ти программных компонентов. Если каждый программный компонент будет лить в UART логи, то вы банально не успеете ничего прочитать и понять. У вас на экране будет Ниагарский водопад из белых логов.

При этом всякая долгая печать в UART ещё и занимает системную шину, DMA каналы, отвлекает ядро своими прерываниями и бизнес логика (функционал) на микроконтроллере поэтому исполняется медленнее.

Эта проблема полностью решается, когда у вас есть возможность отправить строку в пошивку. Эдакую команду. То есть присутствует полудуплексная CLI. С CLI вы можете включать или откл. логи для каждого конкретного программного компонента.

Более того, с CLI вы можете для каждого отдельного программного компонента в прошивке включать и отключать уровни логирования: INFO, NOTICE, WARNING, DEBUG, PARANIOD в зависимости от глубины которую вы готовы сейчас анализировать.


У меня про это есть отдельная методчика:
Отладка программ уровнями логирования (или медицинская карта вашей программы)

https://habr.com/ru/articles/1016480/

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

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

програмный приём относительно сложный

Дак это во всем так.. Поймать летящий мяч сложнее, чем его кинуть.

, я делал это ещё на пик12

Какой максимальной битовой скорости Вам тогда удалось достигнуть?

при 20М кварце ногодрыгом в цикле и nop-ами для выравнивания 455кбит.

Однобитная очередь, отключение прерываний... И как это всё ворочается в итоге при плотном потоке данных на отправку и приём, например на 115200 бод? DMA это хорошо, но системные шины он по-прежнему занимает.

Есть ли какие-то замеры использования процессорного времени, реальные испытания?

Ну вот можете взять и проверить это сами.

Исходные коды прошивки программного UART

Куда-то пропали. 404, говорит.

Это не совсем честная проверка:

При соединении двух разных устройств скорости могут отличаться до 3%. (поэтому встроенный в STM RC-генератор производитель и пытается калибровать до 1,5%)

В случае появления семпла 0 переходим в состояние rec и остаемся в rec пока не примет (1+8+1+2=12 бит).

Поэтому логичнее было бы после появления сэмпла 0 взять 1+8+1+0,5 битовых интервалов. То есть, перейти в IDLE уже на середине первого стоп-бита. Тогда и второй стоп становится ненужным.

Ещё из оптимизаций: через DMA читать не весь GPIO->IDR, а только нужный байт. Дока на STM32F4 это позволяет, вроде. И тогда ядро может обрабатывать сразу по 4 сэмпла. По крайней мере это разгрузит ядро в IDLE.

А после появления 0 становится известно, какие именно сэмплы находятся на середине битовых интервалов, остальные сэмплы можно не обрабатывать. Тут загрузка ядра и так выходит меньше, чем в IDLE.

В FPGA я приём немного по-другому делал: сначала побитный CDR, потом уже обработка кадра. Так логика выходила проще. В мк это не так удобно - слишком много мелкой работы.

Куда-то пропали. 404, говорит.

https://github.com/aabzel/trunk/tree/main/source/projects/jl_32f4xx_sw_uart_gcc_m

Репозиторий
https://github.com/aabzel/trunk

Папка
source/projects

Сборка называется
jl_32f4xx_sw_uart_gcc_m

Вы делали программный UART на микроконтроллере?

Вокруг этого построена вся экосистема Ардуино, потому как оригинальной uno использовалаl atmega8 и единственный уарт был занят как раз console/upload. Были варианты типа Arduino mega, с кучей уартов. Использовались успешно для первых квадракоптеоов. Но сейчас для большей совместимости и кроссплатформенности Ардуино максимально использует программную реализацию. Из коробки.

Но другой вопрос, зачем нужен отладочный уарт, если есть RTT? А я так понимаю он у вас есть

Кстати, в zephyr+nrf52 можно почти из коробки вывести отладку/cli в NordicUart BLE service

Но другой вопрос, зачем нужен отладочный уарт, если есть RTT? А я так понимаю он у вас есть

Из-за отсутствия прав администратора на рабочем PC блокируется возможность подключаться к локальным сокетам. Поэтому Segger RTT отпадает.

Вокруг этого построена вся экосистема Ардуино, потому как оригинальной uno использовалаl atmega8 и единственный уарт был занят как раз console/upload. Были варианты типа Arduino mega, с кучей уартов. Использовались успешно для первых квадракоптеоов. Но сейчас для большей совместимости и кроссплатформенности Ардуино максимально использует программную реализацию. Из коробки.

Стоп. Но ведь в AVR микроконтроллерах нет DMA.
Как тогда там сделали программный UART?

Они что вызывают прерывания таймера на каждый бит что ли?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации