Подключение по uart в linux

Обновлено: 03.07.2024

Не так давно в нашем сервисе All-Hardware произошло знаковое событие. Если раньше порт UART был подключён только к терминалу внутри браузера, то теперь можно установить в Windows специальный драйвер, через который этот порт будет проброшен в вашу локальную систему. Теперь работа с удалённой платой даёт что-то большее, чем написание «Hello World». Вы можете запустить на своей локальной машине программы, которые работают с COM-портом, и обмениваться с удалённой платой по сложным протоколам. Из того, что уже реализовано на практике, – измерение тока потребления платой STM32G474RE DPOW1 Discovery.

Лично я в эпопее по внедрению данной функциональности участия не принимал, так как в то время одомашнивал оборотней (осваивал работу с синтезируемым ядром RISC-V — SweRVolf), но расспросил участников, какие технологии они применяли. В этой статье я покажу физические принципы, лежащие в основе проброса. Практический выхлоп будет состоять в том, что вы сможете пробрасывать порт, не устанавливая никаких драйверов, но реализуя особую (а не универсальную) логику в своей программе. Ну, и вы поймёте, как можно пробросить порт не только для нашего сервиса, а вообще из ОС Linux.




1. Введение

Сначала стоит напомнить, что такое сервис All-Hardware. Подробно про него можно почитать в моих предыдущих статьях (раз и два). Есть также статья моего коллеги. А если кратко, то это такой сайт, через который можно поработать с отладочными платами на базе микроконтроллеров. Сейчас там есть STM32 и NXP. При этом вы пишете и компилируете код на своей машине, а затем просто подключаетесь отладчиком к нашему серверу. Все современные средства отладки позволяют работать не только локально, но и удалённо, и сервис эту возможность использует. Ну, а для обратной связи на сервере имеется видеокамера, которая снимает состояние платы (её светодиоды и экран).

Но реальная работа с платами обычно подразумевает что-то большее, чем пошаговую отладку и просмотр экрана. Платы должны что-то делать. И для этого у них имеются порты. С древнейших времён в нашем сервисе был терминал, через который можно было общаться с UART. Однако интерактивная работа – это хорошо, но работа собственных программ – лучше. И при внедрении платы STM32G474RE DPOW1 Discovery производитель решил, что на локальных машинах пользователей просто необходимо запускать готовую программу, которая в обычной жизни общается с платой через COM-порт Windows. Ребята написали драйвер уровня ядра, благодаря которому на локальных машинах появляется обычный COM-порт. Но физически он пробрасывается на наш сервер. Какие при этом используются технологии – мы сейчас и рассмотрим. Свой драйвер мы не сделаем. Но при разработке своей программы под Windows нет особой разницы, общаться с COM-портом или вызывать иные функции. А вот вызывать функции, которые будут реализовывать проброс на любой Линуксовый сервер, а не только наш – мы научимся.

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

2. Теория со стороны Linux

2.1 Полезная утилита socat

Центральным элементом для проброса портов является забавная утилита socat. Она позволяет пробрасывать данные из одного источника в другой. Список возможных источников – просто широчайший. Установите эту программу:
sudo apt-get install socat

и затем – подайте:
socat –h

Под катом – простыня, описывающая все возможности пробросов…

Впечатляет? Сейчас мы попробуем при помощи этой утилиты пробросить порт UART в терминал. Я подключил к системе наш интеллектуальный контроллер реле, который был описан в этой статье. В ней же был описан способ, как определить имя получившегося устройства.


Собственно, конкретно у меня в системе сейчас имеется всего один последовательный порт, но если бы их было несколько, я бы догадался, с каким из них работать, по ID (голубая часть идентификатора). Для простоты, я буду использовать короткое имя (оранжевая часть идентификатора). В общем, имя – /dev/ttyACM0.

Вбиваю вот такое заклинание:


И тишина. Но зная, что наш контроллер интеллектуального реле реагирует на символ «знак вопроса», я нажимаю его и вижу ответ «abc»:


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

Наверняка, кто-то уже хочет задать вопрос, как это я так лихо настроился на работу с портом, не указав его скорость? Ну, просто контроллер интеллектуально реле – это USB-устройство с интерфейсом CDC. Данные из канала USB сразу попадают в память, а в физический интерфейс UART они никогда не поступают. Именно поэтому я эту поделку и взял для проверки. Минимум возможных мест для сбоя! Но вопрос про скорость – верный. Чтобы её задать, перед запуском socat следовало подать команду вида:


То есть, совсем честный запуск терминала должен был выглядеть так (на самом деле, можно обойтись и без sudo, как – скоро расскажу):


Для проверки я подключу к системе настоящий переходник USB-UART и задам скорость не 115200, а какую-нибудь не самую типовую. Скажем, 38400. Это надо, чтобы исключить случайное совпадение, вдруг мы запросили стандартную скорость, а она уже была выставлена. Сначала я хотел задать совсем нестандартную, но система не дала мне это сделать. В Windows таких проблем не возникало, хочу 12345 – задаю 12345. Линукс так не позволил.

После установки скорости я пошлю свой любимый символ «U» (его код 0x55, то есть, чередующиеся нули и единицы) и измерю фактическую скорость при помощи курсорных измерений осциллографа.



Скорость установлена верно (c поправкой на погрешность переходника). Замечательно. Мы смогли пробросить терминал ОС в последовательный порт. Теперь надо подключиться к системе и начать работать с этим терминалом. Но желательно сделать это с максимальным уровнем автоматизации. Давайте рассмотрим, как это сделали наши разработчики.

2.2 Специально настроенный пользователь

При работе сторонних пользователей с нашим сервером не стоит давать им вводить команды в терминал. И дело даже не в безопасности (хотя, и в ней тоже). Дело в том, что пользователь зашёл на сервис All-Hardware, чтобы поработать с микроконтроллерами, а не для того, чтобы поработать с Линуксом. Своё отношение к работе с ним я уже многократно высказывал. Лично мне эта работа не нравится. 50 на 50, что приходящие на сервис пользователи будут такого же мнения. Скрываем работу с ОС, и вопрос «нравится или нет» исчезает сам собой. Поэтому мы создадим пользователя, при подключении которого к системе, автоматически будет проброшен порт. И пользователь, работая через SSH-терминал, сразу будет общаться именно с этим портом. Никакой подготовительной работы от него не потребуется.

Итак, начинаю цитировать методичку. Создаём аккаунт пользователя с именем, скажем, uart01:

В скрипте бесполезно использовать команду sudo – некому вводить пароль. Чтобы созданному пользователю разрешали запускать программы socat, stty и прочие, работающие с портами, без прав администратора, добавляем его в группу dialout, для чего подаём команду:


Что мы видим, когда подключаемся к удалённой машине по SSH? А давайте проверим на практике:


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


Ну что ж. Методичку я с умным видом процитировал. Давайте хоть сам проверю, сработает ли эта последовательность.


Да-с. Фальстарт… Но мы знаем, что не хватает прав – добавляй sudo. Пробуем ещё раз, применяя это знание:


Было предупреждение, что нет того самого autoexec.bat, но мы его сейчас добавим. В остальном –всё чистенько. Как выяснилось в дальнейшем, чего в методичке не хватает, так это пароля для пользователя. Немного погуглив, я выяснил, что его можно назначить так:


2.3 Пишем autoexec.bat

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

Даже основная работа занимает пол экрана. Там прописан цикл, на случай, если у переходника UART->USB будет отключено питание, ведь чаще всего мы пользуемся портом UART из состава JTAG-адаптера. Обесточили плату – обесточился и адаптер, физически распаянный на ней. Тогда утилита socat вылетит с ошибкой, но бесконечный цикл не даст вылететь сессии, а восстановит соединение.

Дальше большой участок занимает установка скорости UART в зависимости от заранее заданных параметров.

Но для понимания принципа всё это нам не только бесполезно, но ещё и крайне вредно. Мы утонем в куче строк, и рискуем не приметить слона. Поэтому для статьи я сделаю совершенно спартанский вариант скрипта. Он будет состоять из тех двух строк, которые мы вводили выше вручную. Первая задаёт скорость порта (я вбил константу 115200), вторая – делает проброс (опять же, я вбил имя пробрасываемого порта намертво). Ну, и перед ними – чисто технологическая строка.

3. Практическая проверка со стороны Linux

3.1 Сбойный прогон

Хорошо, пользователь добавлен, файл autoexec.bat – создан. Давайте попробуем подключиться к системе по SSH от имени этого пользователя:


Ошибка авторизации. Почему? Начальник, знающий Linux в совершенстве, объяснил мне, что ответ на этот вопрос можно найти в файле
/var/log/auth.log


Начальник посоветовал мне написать:


И надобавлял прав запуска там (вновь установленные флаги отмечены звёздочкой).


3.2 Успешный прогон


Ошибок нет… Нажимаю «знак вопроса».


Работает! Есть проброс!

Ну всё. Через обычный терминал мы уже можем достучаться. На самом деле, это, конечно, лучше, чем терминал в браузере, но не сильно. Поэтому приступаем к работе из собственной Windows-программы. Ведь цель проброса порта – именно реализовывать сложный обмен своей программы с удалённым контроллером.

4.2 Как добыть и подключить библиотеку


В открывшемся окне выбираем вкладку «Обзор» и вбиваем в поиск слово SSH. У меня нужная библиотека оказалась первой в списке.


У меня проект в решении один, но, когда меня обучали, мне разработчик рассказывал, что он затем выбирал вкладку «Установлено» и отмечал, в какие проекты эту библиотеку добавить. Но это я пересказываю на уровне «слышал звон, да не знаю, где он». Просто вдруг у вас будут проблемы – вы будете знать, как их решать. А для случая первичной установки при одном проекте в решении – всё. У нас всё получилось. Вот она сама добавилась в зависимости моего проекта:


Я добавлю на форму три элемента – кнопку «Открыть соединение», строку для отсылки в UART и текст, принятый из UART.

В программе должна быть переменная-член:

4.3 Подключаемся к серверу

В сервисе All-Hardware мы подключаемся к серверу с использованием SSL-сертификата. Но для демонстрации можно использовать и метод попроще, с использованием имени пользователя и пароля. Тогда вся функциональность умещается в две строки плюс немного технологической мишуры:

4.4 Создание потока данных

Для того чтобы передавать данные, надо обязательно создать поток (не тот поток, который Thread, а который Stream). Для этого вызываем функцию CreateShellStream(). Удивительно, но ей надо передать массу сведений о консольном окне (число строк, число столбцов, размер окна в точках), хотя никакого физического терминала создано не будет. Просто так надо. Ну, и последний параметр функции – размер буфера. Итого, функция открытия соединения разрастается на одну строку и теперь выглядит так:


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

4.5 Передача на сервер

4.6 Приём с сервера

Для чтения есть блокирующая и асинхронная функции. Давайте я в примере сделаю приём через асинхронную функцию по таймеру.

4.7 Проверяем

Для проверки открываем соединение, после чего шлём строку из трёх знаков вопроса. Убеждаемся, что пришли три ответа (а каждый ответ у интеллектуального реле выглядит, как строка из символов abc). Значит, система работает.


5. Работа со стороны Windows на прочих языках

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

6. Заключение

Мы рассмотрели механизмы, позволяющие пробросить порты UART из ОС Linux в ОС Windows. Именно на таком методе реализован проброс портов и в сервисе All-Hardware, но для полной унификации ещё разработан драйвер виртуального порта. Поэтому все программы, которые работают с COM-портом, смогут работать и с проброшенным портом, как будто он установлен на локальной Windows-машине.

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

А лично автор при подготовке данной статьи почерпнул вещь, никак не связанную с её темой. В скриптах есть запись вида:
anyUtility 2>log.txt

Оказывается, это всё работает даже в Windows (не само перенаправление, а именно перенаправление с двойкой). Теперь автор умеет сохранять перечень ошибок, выдаваемых GNU компилятором, в файл. Перенаправлять поток надо именно так. Как учит народная мудрость: «Век живи – век учись».

UART CP2103

Мы уже писали, что низковольтный последовательный порт UART может заметно облегчить процесс диагностики современной электронной техники. В этом материале расскажем, как его правильно подключить к компьютеру с операционной системой Windows.

Рассмотрим самый популярный UART, собранный на микросхеме CP2103.

В системе нет драйвера

Чтобы убедиться, что Windows обнаружила наш модуль UART, откроем панель управления, а в ней диспетчер устройств.

диспетчер задач

Теперь видно, что система обнаружила модуль UART на микросхеме CP2103, но драйвера к нему не нашла, так как около значка устройства стоит восклицательный знак. Далее нужно по этой ссылке сохранить драйвер устройства.

загрузка драйвера

Сохраненный файл нужно распаковать в предварительно созданную папку на компьютере.

установка драйвера

Если операционная система 32-х разрядная - необходимо запустить файл CP210xVCPInstaller_x86, а если 64-х разрядная - CP210xVCPInstaller_x64.

продолжение установки

завершение установки

Принимаем условия соглашения и нажимаем "далее".

проверка установки

Нажимаем "готово" и возвращаемся в диспетчер устройств.

проверка установки

Здесь видно, что наш модуль правильно определился и переехал в раздел "Порты (COM и LPT)". Нужно запомнить номер COM-порта, который система присвоила модулю UART.

Поскольку, начиная с Windows7 Microsoft перестала поставлять программу "Гипертерминал", найдем ей достойную замену. Можно скачать бесплатную терминальную программу PyTTY с официального сайта.

сайт PuTTY

На сайте предлагается выбрать файл с нужной разрядностью Windows для загрузки.

загрузка PuTTY

Затем нужно согласиться с тем, что мы собираемся открыть исполняемый файл.

подтверждение

Но на этом Windows не успокаивается, она не знакома с производителем файла, поэтому нажимаем кнопку "запустить".

еще одно

После установки в разделе "Программы" появляется пункт PuTTY. Для дальнейшей работы его необходимо запустить.

запуск PuTTY

В форме программы нужно выбрать "Connection type - Serial", затем в поле "Serial line" ввести номер COM-порта, который мы запомнили из диспетчера устройств и установить скорость соединения. Для приставок DVB-T2 выбираем 115200, для другого оборудования скорости могут быть другими.

Затем нужно проверить работоспособность модуля UART. Нажимаем кнопку "Open" и попадаем в терминал. Далее замыкаем контакты RX и TX модуля между собой и набираем символы на клавиатуре. При замкнутых между собой выводах RX и TX на экране терминала должен печататься текст, набираемый на клавиатуре, при разомкнутых - не должен печататься.

Проверка работы UART

Теперь можно подключать наш диагностический модуль к испытуемому устройству. Помните, что сигналы приема и передачи нужно "крестить" - то есть RX модуля UART соединять с TX устройства, а TX - с RX устройства.

Подключение UART к приставке

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

Программатор CH341a

Использовать в качестве UART можно и программатор на микросхеме CH341a. Для этого необходимо удалить перемычку PROG / UART и установить драйвер последовательного режима работы. Процедура установки драйвера и запуска PuTTY аналогична представленной выше.

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

программатор на CH341A

Существует несколько программ, работающих с ним под операционную систему Windows. Под Linux с этим несколько сложнее, поскольку универсальных программ, реализующих работу программатора CH341A со всеми типами микросхем крайне мало. Однако существует набор консольных утилит под различные чипы. Все ниже сказанное относится к Linux Debian, Ubuntu, Mint, MX. Для других семейств Linux команды установки пакетов будут несколько другими.

После скачивания распаковываем архив ch341eeprom-master в пользовательскую папку /home/имя_пользователя. Запускаем терминал. Переходим в папку с исходным кодом, устанавливаем библиотеку libusb 1.0 и компилируем исходный код:

sudo apt-get install libusb-1.0-0-dev

gcc -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0

После этого нужно перезагрузить компьютер, чтобы новые правила вступили в силу. Далее можно подключить программатор с установленной микросхемой 24Cxx, и для считывания микросхемы в файл набрать в терминале:

где: 24c02 - тип микросхемы (24С01 . 24С512)
test.bin - имя файла, куда загрузится считанная прошивка

Для стирания микросхемы:

Для записи из файла в микросхему:

Для работы с SPI-Flash серий 25ххх можно установить программу Flashrom. Для этого можно использовать такую команду:

Для считывания содержимого микросхемы в файл можно использовать такую команду:

где test.bin - имя файла, куда загрузится считанная прошивка.

Flashrom самостоятельно определит тип микросхемы и производителя, считает из нее данные и сохранит их в файл test.bin.

Для стирания микросхемы:

Для записи прошивки в микросхему:

где test.bin - имя файла, из которого запишется прошивка в микросхему. Flashrom постоянно модифицируется, список поддерживаемых микросхем и программаторов растет.

Для 32-х битной версии Linux можно собрать программу, скопировав каталог src в домашнюю папку и запустив команду make.

Для считывания микросхем 24Cxx или 93Cxx необходимо использовать команду:

где: 93c46 - тип микросхемы (24С01 . 24С1024 или 93с06 . 93с96)
test.bin - имя файла, куда загрузится считанная прошивка

Для записи микросхем 24Cxx или 93Cxx необходимо использовать команду:

где: 93c46 - тип микросхемы (24С01 . 24С1024 или 93с06 . 93с96)
test.bin - имя файла, куда загрузится считанная прошивка

где: 93c46 - тип микросхемы (24С01 . 24С1024 или 93с06 . 93с96)

Для микросхем серии 25xxx команды те же, за исключением префикса -E и типа микросхемы. Их писать не нужно, поскольку тип микросхемы определяется автоматически.

Микросхемы 93С06 . 93С96 программируются с использованием адаптера, устанавливаемого вместо микросхемы 25xxx.


программатор 24Cxx

Для установки программы на Linux Debian, Ubuntu, Mint, MX нужно скачать ее из архива, распаковать его и запустить файл ./install.sh. После установки программа попадет в главном меню в раздел "Прочее". Исходный код программатора выложен на github.

Приобрести программатор можно по этой ссылке.

К этому программатору можно приобрести также панельку для микросхем в корпусе SOP8 (размер 150mil для микросхем серий 24Cxx и 93Cxx, 208mil для 25Qxx) или набор панелек под пайку, клипсу для программирования прямо на плате. Напоминаем, что для ее использования необходимо перерезать дорожку питания программируемой микросхемы, иначе программатор можно повредить. Также пригодится набор макетных проводников для подключения программатора к различным платам, набор микросхем серии 93Схх и 24Схх и набор микросхем 25Q32FVVSIQ.

В предыдущем посте было показано как запустить UART на отладочной плате Launchpad для MSP430. Теперь рассмотрим как общаться с платой при помощи средств командной строки Linux. Используется плата с прошивкой из предыдущего поста. Для подробностей - см. под кат


Как известно, все устройства последовательных портов представлены файлами устройств в каталоге /dev.Через эти файлы и происходит общение ОС Linux с внешним устройством на последовательном порту. Чтобы передать что-то на внешнее устройство нужно записать данные в файл устройства, а чтобы считать информацию из устройства --- прочитать данные из файла устройства. Это можно делать при помощи команд cat и echo так же как для обычных файлов на диске. Или внутри программы на С при помощи вызовов ioctl(), read() и write() или библиотеки termios.

Физическим последовательным портам RS232, к которым подключались диалапные модемы на старых компьютерах, соответствуют файлы устройств /dev/ttyS*, начиная с /dev/ttyS0. Виртуальным последовательным портам, которые создаются различными конвертерами USB<->UART соответствуют файлы устройств /dev/ttyUSB* и /dev/ttyACM*. Ядро Linux автоматически разпознаёт подключенное устройство, загружает для него драйвер и создаёт файл устройства. Вручную устанавливать драйвер, как в ОС Windows не требуется. Например, если подключить к USB преобразователь USB<->UART FT232, то создаётся файл устройства /dev/ttyUSB0, с которым можно работать также как и с обычным последовательным портом. На плате Launcpad находится микросхема TUSB3410, которая тоже представляет собой конвертер USB<->UART. Если подключить её к USB, то создаётся файл устройства /dev/ttyACM0. Чтобы общаться с платой нужно что-либо писать/читать с этого файла.

Чтобы пользователь мог читать или писать в файл устройства последовательного порта, его нужно добавить в группу dialout. Иначе работать с последовательным портом сможет только администратор root.

Простейшим приложением с графическим интерфейсом, которое работает с последовательным портом, является CuteCOM. Он обычно уже есть в вашем дистрибутиве Linux. Его можно установить из репозиториев. При помощи CuteCOM мы работали с платой в предыдущем посте. Выглядит CuteCOM вот так:


Работать с ним крайне просто. Указываем нужное устройство, если его нет в списке, то его можно впечатать вручную. Затем указываем скорость и параметры и нажимаем OpenDevice. В окне видим данные, которые пришли от устройства. В поле ввода в нижней части можем печать строку символов, которые предаются на устройство. Чтобы передать данный нажимаем Enter и смотрим ответ устройства в окне.

Теперь рассмотрим как работать с COM-портом из командной строки. Для этого служат три команды: stty, cat и echo.

Команда stty устанавливает параметры и скорость COM-порта. Её формат:

stty <СКОРОСТЬ> -F <УСТРОЙСТВО> <ПАРАМЕТРЫ>

Чтобы установить параметры для платы Launchpad для соединения на скорости 9600 нужно выполнить:

$ stty 9600 -F /dev/ttyACM0 raw -echo

Параметр raw устанавливает, что данные в компьютер передаются байт за байтом так же как приходят в порт без преобразований. Аппаратное управление потоком отключено. Подробнее о том, что включает и выключает raw - см. man stty. Если не включить raw, то скорее всего ничего работать не будет.

Теперь в той же консоли нужно набрать

$ cat /dev/ttyACM0

И можно смотреть данные, которые приходят от платы. Выход - нажать Ctrl+C.

Теперь нажимаем на плате RESET и видим, что в консоди напечатался текст.

Чтобы передать в плату данные, в другой консоли нужно использовать команду echo и перенаправление вывода в файл устройства. Наберём в другой консоли:

В итоге должно получиться так:


Чтобы увидеть 16-ричные коды данных, приходящих от устройства, нужно использовать команду hexdump:

$ cat /dev/ttyACM0|hexdump -C

Получится вот так:


Чтобы иметь вывод данных от устройство на экран и в текстовый файл нужно использовать tee:

Читайте также: