Последнее время большую популярность приобрёл программно-аппаратный комплекс Arduino, который предназначен для разработки различных интересных электронных конструкций. Конструкции изготовляются путём соединения базовой платы Arduino с дополнительными необходимыми модулями. На базовой плате Arduino находится микроконтроллер, прошивка на который пишется в специальной среде разработки для Arduino с использованием, как правило, готовых библиотек на тот или иной модуль.
Один из модулей – W5500 – предназначен для изготовления электронных конструкций, которые будут связаны с Интернет. При этом чаще всего, подразумевается удалённое управление своей конструкцией. Например, это может быть «умный дом», робот и тому подобное. Самый тривиальный проект (кроме Hello world) – удалённое включение светодиодов через web-браузер (рис. 1). Если вместо светодиодов подключить транзисторные ключи и реле, можно коммутировать более мощные нагрузки. Таким образом, по сути, программа (прошивка) данной конструкции представляет собой web-сервер, обрабатывающий http-запросы удалённого пользователя.
Рис. 1. Управление светодиодами через браузер.
В основе модуля W5500 лежит сам чип W5500 с его обвеской, а также, разъём BLS подключения МК по SPI, разъём RJ-45 для подключения к компьютерной сети, линейный регулятор напряжения питания на 3.3 В (рис. 2).
Рис. 2. Модуль W5500.
Чип W5500 представляет собой полноценный контроллер, в который встроена обработка целого стека сетевых протоколов, начиная от Ethernet и заканчивая TCP (рис. 3). Реализуя конструкцию на базе данного чипа, программисту нет необходимости писать код обработки протокола TCP/IP, достаточно реализовать только протокол прикладного уровня, который будет вложен в TCP. В примере выше (на Arduino) в качестве прикладного протокола используется http.
Рис. 3. Структура чипа W5500.
Не занимаясь Arduino, я решил в деталях изучить документацию на чип W5500 и самостоятельно реализовать программу на базе микроконтроллера Atmega8. Данная программа не будет предусматривать обработчик http. Требуется реализовать простейший (RAW) обмен данными через протокол TCP, используя удалённый терминал. Не совсем точно говорить о протоколе Telnet, как это сказано в названии данной статьи. У него есть свои специфические особенности, основанные на обмене дополнительной информацией о параметрах терминалов. Однако большинство telnet-клиентов поддерживают RAW и не требуют вышесказанного. Таким образом, программа МК Atmega8 не будет предусматривать обработчик протокола прикладного уровня. Она будет заниматься только инициализацией W5500, управлением сокетами, приёмом и передачей данных.
Основное применение данной конструкции – управление устройствами через удалённый терминал. При этом конструкция подключается к управляемому устройству через UART интерфейс (три провода GND, TxD, RxD). Управление через терминал – это классический профессиональный подход в той или иной сфере при отсутствии графического интерфейса. Например, командная строка Windows или Linux, или способ настройки роутера через терминал по протоколу Telnet. Последний пример фактически равноценен идее, о которой идёт речь в данной статье.
При разработке того или иного устройства при необходимости я предусматриваю управление им текстовыми командами через терминал, который подключен по UART интерфейсу. Это может быть подключение к обычному ПК к COM-порту RS-232 через микросхему-переходник MAX232, или к USB (виртуальный COM-порт) через микросхему PL2303. В качестве терминала можно использовать стандартную программу HyperTerminal. С распространением смартфонов на базе Android стало удобно подключение через Bluetooth: к UART интерфейсу устройства подключается модуль Bluetooth (например, HC-06), а к модулю подключается смартфон беспроводным способом. В Интернете множество приложений, реализующих терминал через Bluetooth. Таким образом, можно управлять устройством через терминал с мобильного телефона через Bluetooth в небольшом радиусе действия. Конструкция, о которой идёт речь в данной статье, позволяет реализовать управление через терминал, используя Интернет. В качестве терминала может выступать стандартный HyperTerminal, которой поставляется с Windows XP, или можно запустить из командной строки Windows утилиту «telnet» и работать в ней. Если же речь идёт о смартфоне, то можно выбрать одно из приложений на Android (их также большое множество) (рис. 4).
Рис. 4. Приложения по запросу «TCP terminal» на Google Play.
Чип W5500 имеет 8 независимых сокетов, каждый из которых обладает памятью для приёма и передачи информации по 2 KB. Итого, общая память 16 KB на приём и 16 KB на передачу информации. Эти параметры применяются по умолчанию, но при необходимости на этапе инициализации чипа память по сокетам можно перераспределить. В описываемом здесь приложении будут использоваться параметры памяти по умолчанию, и задействованы все 8 сокетов. Каждому сокету на этапе его инициализации присваивается множество параметров, главные из которых – режим его работы и TCP порт. Режим работы всех восьми сокетов, который нам необходим – режим TCP сервера. Необходимо присвоить каждому сокету различные порты. Я взял восемь подряд идущих портов, начиная, к примеру, от 4000. На этапе инициализации модуля W5500 ему присваиваются зашитые в программу МК Atmega8 сетевые параметры: IP-адрес, маска подсети, IP-адрес шлюза и даже физический MAC-адрес. Сетевые параметры модуля W5500 должны соответствовать настройкам домашней сети, к которой он подключается. При удалённом подключении к нашему описываемому устройству в настройках терминала указывается адрес узла (IP-адрес или доменное имя) и порт. Адрес узла ссылается на устройство W5500, а порт – на сокет в устройстве. Один сокет может работать только с одним подключением. Следовательно, имеется возможность осуществлять восемь независимых одновременных подключений. На рисунке 5 показаны параметры подключения в стандартной программе HyperTerminal к W5500 с IP-адресом 192.168.0.111 к сокету 0 (порт 4000). Для подключения в глобальной сети Интернет (извне) требуется соответствующе настроить домашний роутер.
Рис. 5. Подключение через TCP/IP в HyperTerminal.
Я перепробовал множество различных приложений TCP-терминалов, у каждого есть свои преимущества и недостатки. Прежде всего, по способу упаковки TCP пакета, можно выделить два случая. В первом случае TCP пакет формируется и отправляется серверу сразу при введённом в терминал символе. Таким образом, поле данных каждого пакета занимает 1 байт и содержит введённый пользователем символ. Программа HyperTerminal работает как раз в таком режиме. Во втором случае набор символов (команда) вводится в отдельное текстовое поле, а при нажатии на кнопку «Отправить» формируется всего-навсего один пакет с полем данных, содержимое которого представляет собой введённый пользователем набор символов. Размер поля данных такого пакета в байтах совпадает с количеством введённых символов. Второй случай наиболее предпочтительный и удобный, а также экономичный в трафике. Наша конструкция работает с обоими случаями, передавая на выход (TxD) UART МК Atmega8 все символы, введённые удалённым пользователем с любого сокета.
Что касается организации передачи информации от сервера к клиенту, здесь тоже есть свои особенности. Можно сделать, чтобы однобайтовый TCP пакет программа МК формировала также непосредственно, по поступлению одного байта (символа) на ножку RxD UART МК. Можно сделать формирование TCP пакета из множества поступающих байтов на МК по присутствию специального дополнительно сигнала, который присутствует только во время передачи последовательности от подключенного устройства (сигнал упаковки). Кстати говоря, данный сигнал применяется для коммутации MAX485 на передачу в случае преобразования RS-232 в полудуплексный интерфейс RS-485. Однако, как я убедился, удобнее всего применять таймер, т.е. небольшую задержку, в течение которой будет производиться приём символов и формирование TCP пакета. Именно этот способ я реализовал в описываемой конструкции. Работает это следующим образом. Таймер (время задано примерно 0.3 сек.) запускается при поступлении первого символа и сбрасывается при поступлении каждого очередного символа на UART МК. Если в течение заданного времени символы не поступали, пакет с поступившими символами формируется и отправляется клиенту, а таймер останавливается. В моём конкретном случае происходит массовая рассылка по всем сокетам, к которым подключены клиенты.
Теперь речь пойдёт о конфиденциальности. Описываемый удалённый терминал не защищён от «подслушивания» с помощью анализаторов трафика. Даже сам протокол Telnet не предусматривает парольной авторизации и шифрования. Для этого имеются другие современные протоколы удалённого терминала. А в случае с Telnet, как и в случае RAW (без прикладного протокола) можно реализовать косвенный способ парольной авторизации, который разве что будет неэффективный при намеренном умышленном вмешательстве. Однако такой способ авторизации защитит от безконтрольного «левого» трафика. Он может исходить от шпионских программ, которые, перебирая диапазон IP-адресов известных провайдеров и диапазон портов, могут внезапно подключиться к нашему устройству (если оно «слушает» соединения из Интернета). В своей прошивке я реализовал страницу приветствия клиента, если тот подключился к серверу, т.е. к конструкции на базе модуля W5500.
Страница приветствия содержит информацию об IP-адресе клиента, номера сокета (для контроля) и предложением ввести пароль (рис. 6).
Рис. 6. Страница приветствия сервера W5500.
После подключения внутри программы МК запускается таймер на время (примерно на 18 сек.), в течение которого пользователь должен успеть ввести определённый пароль (одинаковый на всех сокетах). В случае неправильно введённого пароля по истечению заданного времени пользователя информирует соответствующее сообщение, и сервер разрывает соединение (рис. 7).
Рис. 7. Сообщение о некорректном пароле.
В случае корректно введённого пароля пользователю также высвечивается соответствующее сообщение (рис. 8). После этого устанавливается «прозрачный» мост между удалённым терминалом и UART интерфейсом МК, к которому по SPI подключен модуль W5500. Работа такого моста проверялась только на уровне пользовательских команд. Может не гарантироваться полноценный высокоскоростной обмен данными, если в каких-либо случаях в роли клиентского приложения будет выступать не пользовательский терминал, а какая-либо другая программа. А уж тем более, в описываемой конструкции не гарантируется (точнее, не предусмотрен) полнодуплексный обмен данными.
Рис. 8. Сообщение о корректном пароле.
При вводе пароля пользователю на терминал не возвращаются вводимые им символы, а также не работает «Backspace» (откат при неправильно введённом символе). Длинна пароля – 8 символов. Программа МК сканирует первые пришедших от клиента 8 символов вне зависимости от распределения их по TCP пакетам. Но любой пакет не должен превышать 10 байтов. Кстати говоря, функция «Отправить текстовый файл» в программе HyperTerminal работает весьма интересно. Как было проверено с помощью анализатора трафика, при выполнении этой функции формируется два TCP пакета: первый пакет с данными в 1 байт содержит первый символ передаваемого текстового файла, а второй пакет – всё остальное содержимое.
Сервер предусматривает два различных пароля. Один пароль служит для установления моста «TCP-UART» (обычное использование), о чём говорилось выше, а второй пароль – для управления модулем W5500 или другими параметрами конструкции. В случае ввода данного пароля пользователю высвечивается другая страница приветствия, и он попадает в режим управления. Я намеренно предусмотрел, чтобы данный режим был возможен только на одном из свободных сокетов. Если сокет с данным режимом занят, и будет произведена попытка авторизоваться в этот режим на другом сокете, соединение будет немедленно разорвано сервером. Перед разрывом высветится сообщение о номере сокета, который уже работает (занят) в режиме управления (рис. 9).
Режим управления предусматривает определённые мной команды, перечень которых можно увидеть, введя команду «help». Команда должна завершаться символом перевода на новую строку (клавиша Enter). Кроме того, если активен режим управления, сервер W5500 выдаёт в терминал служебные сообщения, например, о подключающихся клиентах на другие сокеты с их IP-адресами или об освободившемся сокете. На рисунке 10 продемонстрировано вышесказанное. Перечень команд пока что не полный, со временем будет пополняться.
Рис. 9. Сообщение о занятом сокете при вводе пароля режима управления.
Рис. 10. Режим управления W5500.
Команда «echo» отключает или включает возврат печатаемого символа на терминал (самоконтроль). Следующие две команды предназначены для чтения и записи адресуемого регистра чипа W5500. Значения регистров по адресам указаны в документации на чип W5500. Эти универсальные команды я ввёл, прежде всего, для отладки. Команда «rl» немедленно «перезагружает» сокет, номер которого указан после. Аналогично, команда «sr» читает статус сокета, выдавая его значение в виде HEX-числа. Команда «ens» выдаёт таблицу состояний каждого сокета: состояние «0» — сокет свободный, ждёт клиента, состояние «1» — сокет в режиме обычного использования, состояние «2» — сокет в режиме управления. Можно ввести гораздо большее число команд. Будет полезно менять параметры, которые вписываются в чип на этапе инициализации при включении устройства (например, сетевые параметры), сохраняя их в энергонезависимую память МК. Также может оказаться полезным ввести специальные команды, которые будут управлять дополнительными свободными пинами МК. Например, «PC0=1», «PC2=0» и т.д. Обязательно нужна команда конфигурации UART интерфейса МК.
Рассмотрим более тонкие детали работы программы МК. Кроме вышеперечисленных таймеров, задействован таймер, благодаря которому через каждые примерно полминуты по всем задействованным сокетам рассылаются т.н. контрольные TCP пакеты «keep-alive». Это нужно для проверки соединения в случае отсутствия пользовательского обмена данными. Если по какой-либо причине со стороны клиента не будет ответа с подтверждением в течение определённого времени, установленного внутри W5500, сработает т.н. таймаут, и сокет будет перезагружен. Соединение может внезапно потеряться, например, по причине разрыва на канальном или физическом уровне: выдернули Ethernet кабель, отключился Интернет или потеряно Wi-Fi соединение и т.д.
Основываясь на документации к чипу W5500 (datasheet) в программном коде реализованы следующие функции. Во-первых – базовые функции записи и чтения регистров W5500 по адресам. Функции верхнего уровня – аппаратный сброс, инициализация чипа, инициализация сокета, открытие сокета, сокет на прослушивание, дисконнет и закрытие сокета, отправка команды «keep_alive», перезагрузка сокета. Последняя функция представляет собой композицию вышеупомянутых функций: закрытие, открытие, прослушивание. Большинство функций возвращают значение статуса сокета после их выполнения. Наконец, самые основные функции – обработка принятой информации (чтение из буфера RX) и обработка отправляемой информации (запись в буфер TX). Рекомендации по реализации этих функций я взял с официального сайта производителя чипа W5500 (ссылка). Функция приёма переписывает принятые данные из буфера RX в собственный буфер (не кольцевой) размером 128 байт. Этого размера вполне достаточно для простых приложений, да и с микроконтроллера Atmega8 много не возьмёшь. В буфер TX W5500 функцией передачи переписываются данные из промежуточного буфера также небольшого размера. А в него в свою очередь попадают данные из кольцевого буфера UART. Последний реализован автоматически в среде разработки CVAVR с помощью вспомогательного приложения CodeWizardAVR на этапе создания проекта.
Модуль W5500 подключен к SPI интерфейсу МК (MOSI, MISO, SCK, SCLK). Кроме того, к определённому выходу МК подключен вывод RST (аппаратный сброс), и к входу внешнего прерывания INT0 подключен соответствующий вывод INT. Последний используется по прямому назначению: При возникновении того или иного события в модуле W5500 он формирует импульс на выводе INT, который обрабатывается контроллером в теле внешнего прерывания. МК узнаёт, на каких сокетах произошло событие, затем переписывает коды событий для каждого сокета в определённый массив. Дальнейшая обработка прерывания происходит внутри основного цикла программы. Всего документировано пять событий: клиент подключился, клиент отключился (точнее, подал запрос на отключение), поступили данные от клиента, сработал таймаут, данные отправлены успешно. В основном цикле обрабатываются все события, кроме последнего. В данную обработку помещён оператор switch-case. Самая большая часть программного кода на языке Си встречается в секции обработки третьего события (приём данных). В нём после функции обработки принятой информации также помещён оператор switch-case, но в данном случае этот «переключатель» связан с переменной, отвечающей за состояние сокета, о котором говорилось выше (значения 0, 1, 2). Первая секция отвечает за процедуру распознавания пароля. Принятые символы переписываются в отдельный парольный буфер. При определённых условиях работают функции сравнения принятой строки со строками-константами, содержащих пароли. В случае того или иного совпадения присваивается соответствующее состояние. Вторая секция самая простая – содержимое собственного буфера принятой информации перенаправляется на UART микроконтроллера. Это режим обычного использования. Третья секция (самая большая) отвечает за обработку команд – режим управления устройством.
Кроме продолжения обработчика прерываний в основном цикле программы помещены обработчики виртуальных таймеров – таймаут для разрыва соединения при неуспешной попытке ввода пароля, периодическая отправка «keep-alive» и отправка клиенту сформированного по таймеру TCP пакета. Ещё в тело основного цикла помещена функция чтения из UART, внутри которой переписываются принятые контроллером символы в собственный (промежуточный) буфер передачи и происходит сброс таймера, отвечающий за формирование TCP пакета.
Все процедуры сокетов помещены в цикл от 0 до 7, итератор которого привязан к номеру сокета. Таким образом, происходит последовательная обработка всех сокетов. Изначально я подразумевал, что, если присвоить каждому из восьми сокетов одинаковый номер порта, то можно обеспечить подключение до восьми пользователей по одному и тому же порту. Однако такая конфигурация не заработала, и данный вопрос пока отложен на будущее.
Разрабатывая печатную плату конструкции, я предусмотрел часы реального времени (RTC) на микросхеме DS1307. На двусторонней печатной плате размещены МК Atmega8, кварц на частоту 11.0592 МГц (частота выбрана для точности работы UART), разъём для модуля W5500, разъёмы портов МК (в том числе SPI для прошивки, UART), RTC с собственным кварцем и отсеком для батарейки CR2032, линейный регулятор на 5 В (7805), разъём питания и прочее. Эскиз печатной платы в программе «Sprint Layout» представлен на рисунке 11. Единственный элемент, который изображён красным цветом, припаивается на обратной стороне, но я его припаял на лицевую сторону.
Рис. 11. Эскиз печатной платы.
Фотографии готовой конструкции представлены на рисунке 12. Часы в данной конструкции будут использоваться для отметки времени при тех или иных событиях сокетов W5500, и данное время будет приписываться пользователю в терминал рядом с сообщением, если пользователь подключен в режиме управления. А также, часы пригодятся на будущее для экспериментов с протоколом настройки времени NTP или для других каких-либо целей.
Рис. 12. Фотографии готовой конструкции.
В заключении стоит отметить, что конструкция собственного изготовления по большей части оправдывает похожие устройства промышленного уровня. Основное достоинство – цена. Изготовить получилось гораздо дешевле, чем цена готового подобного устройства. А такой недостаток, как ограниченный функционал, неизбежен. В данном случае применён упрощённый контроллер Atmega8, так как ставилась соответствующая упрощённая цель.
Рис. 13. Промышленный конвертер TCP/IP – RS-232.
На рисунке 13 в качестве примера изображён промышленный конвертер TCP/IP в RS-232, выполненный на базе чипа W5100, очень похожим на W5500. У него, кроме гибкого интерфейса управления, есть ещё одно преимущество. Кроме работы с TCP/IP терминалом, имеется возможность с помощью специального драйвера, который поставляется с устройством, на клиентской стороне установить виртуальный COM-порт. Через него можно подключиться с помощью обычного терминала, у которого нет режима TCP/IP подключения. Более того, устройство может поддерживать полноценный обмен данными по RS-232 в случае, если вместо терминала через виртуальный COM-порт подключается какая-либо программа. То есть, устройство, изображённое на рисунке 13, является полноценным мостом RS-232 через сетевую инфраструктуру.
Один из модулей – W5500 – предназначен для изготовления электронных конструкций, которые будут связаны с Интернет. При этом чаще всего, подразумевается удалённое управление своей конструкцией. Например, это может быть «умный дом», робот и тому подобное. Самый тривиальный проект (кроме Hello world) – удалённое включение светодиодов через web-браузер (рис. 1). Если вместо светодиодов подключить транзисторные ключи и реле, можно коммутировать более мощные нагрузки. Таким образом, по сути, программа (прошивка) данной конструкции представляет собой web-сервер, обрабатывающий http-запросы удалённого пользователя.
Рис. 1. Управление светодиодами через браузер.
В основе модуля W5500 лежит сам чип W5500 с его обвеской, а также, разъём BLS подключения МК по SPI, разъём RJ-45 для подключения к компьютерной сети, линейный регулятор напряжения питания на 3.3 В (рис. 2).
Рис. 2. Модуль W5500.
Чип W5500 представляет собой полноценный контроллер, в который встроена обработка целого стека сетевых протоколов, начиная от Ethernet и заканчивая TCP (рис. 3). Реализуя конструкцию на базе данного чипа, программисту нет необходимости писать код обработки протокола TCP/IP, достаточно реализовать только протокол прикладного уровня, который будет вложен в TCP. В примере выше (на Arduino) в качестве прикладного протокола используется http.
Рис. 3. Структура чипа W5500.
Не занимаясь Arduino, я решил в деталях изучить документацию на чип W5500 и самостоятельно реализовать программу на базе микроконтроллера Atmega8. Данная программа не будет предусматривать обработчик http. Требуется реализовать простейший (RAW) обмен данными через протокол TCP, используя удалённый терминал. Не совсем точно говорить о протоколе Telnet, как это сказано в названии данной статьи. У него есть свои специфические особенности, основанные на обмене дополнительной информацией о параметрах терминалов. Однако большинство telnet-клиентов поддерживают RAW и не требуют вышесказанного. Таким образом, программа МК Atmega8 не будет предусматривать обработчик протокола прикладного уровня. Она будет заниматься только инициализацией W5500, управлением сокетами, приёмом и передачей данных.
Основное применение данной конструкции – управление устройствами через удалённый терминал. При этом конструкция подключается к управляемому устройству через UART интерфейс (три провода GND, TxD, RxD). Управление через терминал – это классический профессиональный подход в той или иной сфере при отсутствии графического интерфейса. Например, командная строка Windows или Linux, или способ настройки роутера через терминал по протоколу Telnet. Последний пример фактически равноценен идее, о которой идёт речь в данной статье.
При разработке того или иного устройства при необходимости я предусматриваю управление им текстовыми командами через терминал, который подключен по UART интерфейсу. Это может быть подключение к обычному ПК к COM-порту RS-232 через микросхему-переходник MAX232, или к USB (виртуальный COM-порт) через микросхему PL2303. В качестве терминала можно использовать стандартную программу HyperTerminal. С распространением смартфонов на базе Android стало удобно подключение через Bluetooth: к UART интерфейсу устройства подключается модуль Bluetooth (например, HC-06), а к модулю подключается смартфон беспроводным способом. В Интернете множество приложений, реализующих терминал через Bluetooth. Таким образом, можно управлять устройством через терминал с мобильного телефона через Bluetooth в небольшом радиусе действия. Конструкция, о которой идёт речь в данной статье, позволяет реализовать управление через терминал, используя Интернет. В качестве терминала может выступать стандартный HyperTerminal, которой поставляется с Windows XP, или можно запустить из командной строки Windows утилиту «telnet» и работать в ней. Если же речь идёт о смартфоне, то можно выбрать одно из приложений на Android (их также большое множество) (рис. 4).
Рис. 4. Приложения по запросу «TCP terminal» на Google Play.
Чип W5500 имеет 8 независимых сокетов, каждый из которых обладает памятью для приёма и передачи информации по 2 KB. Итого, общая память 16 KB на приём и 16 KB на передачу информации. Эти параметры применяются по умолчанию, но при необходимости на этапе инициализации чипа память по сокетам можно перераспределить. В описываемом здесь приложении будут использоваться параметры памяти по умолчанию, и задействованы все 8 сокетов. Каждому сокету на этапе его инициализации присваивается множество параметров, главные из которых – режим его работы и TCP порт. Режим работы всех восьми сокетов, который нам необходим – режим TCP сервера. Необходимо присвоить каждому сокету различные порты. Я взял восемь подряд идущих портов, начиная, к примеру, от 4000. На этапе инициализации модуля W5500 ему присваиваются зашитые в программу МК Atmega8 сетевые параметры: IP-адрес, маска подсети, IP-адрес шлюза и даже физический MAC-адрес. Сетевые параметры модуля W5500 должны соответствовать настройкам домашней сети, к которой он подключается. При удалённом подключении к нашему описываемому устройству в настройках терминала указывается адрес узла (IP-адрес или доменное имя) и порт. Адрес узла ссылается на устройство W5500, а порт – на сокет в устройстве. Один сокет может работать только с одним подключением. Следовательно, имеется возможность осуществлять восемь независимых одновременных подключений. На рисунке 5 показаны параметры подключения в стандартной программе HyperTerminal к W5500 с IP-адресом 192.168.0.111 к сокету 0 (порт 4000). Для подключения в глобальной сети Интернет (извне) требуется соответствующе настроить домашний роутер.
Рис. 5. Подключение через TCP/IP в HyperTerminal.
Я перепробовал множество различных приложений TCP-терминалов, у каждого есть свои преимущества и недостатки. Прежде всего, по способу упаковки TCP пакета, можно выделить два случая. В первом случае TCP пакет формируется и отправляется серверу сразу при введённом в терминал символе. Таким образом, поле данных каждого пакета занимает 1 байт и содержит введённый пользователем символ. Программа HyperTerminal работает как раз в таком режиме. Во втором случае набор символов (команда) вводится в отдельное текстовое поле, а при нажатии на кнопку «Отправить» формируется всего-навсего один пакет с полем данных, содержимое которого представляет собой введённый пользователем набор символов. Размер поля данных такого пакета в байтах совпадает с количеством введённых символов. Второй случай наиболее предпочтительный и удобный, а также экономичный в трафике. Наша конструкция работает с обоими случаями, передавая на выход (TxD) UART МК Atmega8 все символы, введённые удалённым пользователем с любого сокета.
Что касается организации передачи информации от сервера к клиенту, здесь тоже есть свои особенности. Можно сделать, чтобы однобайтовый TCP пакет программа МК формировала также непосредственно, по поступлению одного байта (символа) на ножку RxD UART МК. Можно сделать формирование TCP пакета из множества поступающих байтов на МК по присутствию специального дополнительно сигнала, который присутствует только во время передачи последовательности от подключенного устройства (сигнал упаковки). Кстати говоря, данный сигнал применяется для коммутации MAX485 на передачу в случае преобразования RS-232 в полудуплексный интерфейс RS-485. Однако, как я убедился, удобнее всего применять таймер, т.е. небольшую задержку, в течение которой будет производиться приём символов и формирование TCP пакета. Именно этот способ я реализовал в описываемой конструкции. Работает это следующим образом. Таймер (время задано примерно 0.3 сек.) запускается при поступлении первого символа и сбрасывается при поступлении каждого очередного символа на UART МК. Если в течение заданного времени символы не поступали, пакет с поступившими символами формируется и отправляется клиенту, а таймер останавливается. В моём конкретном случае происходит массовая рассылка по всем сокетам, к которым подключены клиенты.
Теперь речь пойдёт о конфиденциальности. Описываемый удалённый терминал не защищён от «подслушивания» с помощью анализаторов трафика. Даже сам протокол Telnet не предусматривает парольной авторизации и шифрования. Для этого имеются другие современные протоколы удалённого терминала. А в случае с Telnet, как и в случае RAW (без прикладного протокола) можно реализовать косвенный способ парольной авторизации, который разве что будет неэффективный при намеренном умышленном вмешательстве. Однако такой способ авторизации защитит от безконтрольного «левого» трафика. Он может исходить от шпионских программ, которые, перебирая диапазон IP-адресов известных провайдеров и диапазон портов, могут внезапно подключиться к нашему устройству (если оно «слушает» соединения из Интернета). В своей прошивке я реализовал страницу приветствия клиента, если тот подключился к серверу, т.е. к конструкции на базе модуля W5500.
Страница приветствия содержит информацию об IP-адресе клиента, номера сокета (для контроля) и предложением ввести пароль (рис. 6).
Рис. 6. Страница приветствия сервера W5500.
После подключения внутри программы МК запускается таймер на время (примерно на 18 сек.), в течение которого пользователь должен успеть ввести определённый пароль (одинаковый на всех сокетах). В случае неправильно введённого пароля по истечению заданного времени пользователя информирует соответствующее сообщение, и сервер разрывает соединение (рис. 7).
Рис. 7. Сообщение о некорректном пароле.
В случае корректно введённого пароля пользователю также высвечивается соответствующее сообщение (рис. 8). После этого устанавливается «прозрачный» мост между удалённым терминалом и UART интерфейсом МК, к которому по SPI подключен модуль W5500. Работа такого моста проверялась только на уровне пользовательских команд. Может не гарантироваться полноценный высокоскоростной обмен данными, если в каких-либо случаях в роли клиентского приложения будет выступать не пользовательский терминал, а какая-либо другая программа. А уж тем более, в описываемой конструкции не гарантируется (точнее, не предусмотрен) полнодуплексный обмен данными.
Рис. 8. Сообщение о корректном пароле.
При вводе пароля пользователю на терминал не возвращаются вводимые им символы, а также не работает «Backspace» (откат при неправильно введённом символе). Длинна пароля – 8 символов. Программа МК сканирует первые пришедших от клиента 8 символов вне зависимости от распределения их по TCP пакетам. Но любой пакет не должен превышать 10 байтов. Кстати говоря, функция «Отправить текстовый файл» в программе HyperTerminal работает весьма интересно. Как было проверено с помощью анализатора трафика, при выполнении этой функции формируется два TCP пакета: первый пакет с данными в 1 байт содержит первый символ передаваемого текстового файла, а второй пакет – всё остальное содержимое.
Сервер предусматривает два различных пароля. Один пароль служит для установления моста «TCP-UART» (обычное использование), о чём говорилось выше, а второй пароль – для управления модулем W5500 или другими параметрами конструкции. В случае ввода данного пароля пользователю высвечивается другая страница приветствия, и он попадает в режим управления. Я намеренно предусмотрел, чтобы данный режим был возможен только на одном из свободных сокетов. Если сокет с данным режимом занят, и будет произведена попытка авторизоваться в этот режим на другом сокете, соединение будет немедленно разорвано сервером. Перед разрывом высветится сообщение о номере сокета, который уже работает (занят) в режиме управления (рис. 9).
Режим управления предусматривает определённые мной команды, перечень которых можно увидеть, введя команду «help». Команда должна завершаться символом перевода на новую строку (клавиша Enter). Кроме того, если активен режим управления, сервер W5500 выдаёт в терминал служебные сообщения, например, о подключающихся клиентах на другие сокеты с их IP-адресами или об освободившемся сокете. На рисунке 10 продемонстрировано вышесказанное. Перечень команд пока что не полный, со временем будет пополняться.
Рис. 9. Сообщение о занятом сокете при вводе пароля режима управления.
Рис. 10. Режим управления W5500.
Команда «echo» отключает или включает возврат печатаемого символа на терминал (самоконтроль). Следующие две команды предназначены для чтения и записи адресуемого регистра чипа W5500. Значения регистров по адресам указаны в документации на чип W5500. Эти универсальные команды я ввёл, прежде всего, для отладки. Команда «rl» немедленно «перезагружает» сокет, номер которого указан после. Аналогично, команда «sr» читает статус сокета, выдавая его значение в виде HEX-числа. Команда «ens» выдаёт таблицу состояний каждого сокета: состояние «0» — сокет свободный, ждёт клиента, состояние «1» — сокет в режиме обычного использования, состояние «2» — сокет в режиме управления. Можно ввести гораздо большее число команд. Будет полезно менять параметры, которые вписываются в чип на этапе инициализации при включении устройства (например, сетевые параметры), сохраняя их в энергонезависимую память МК. Также может оказаться полезным ввести специальные команды, которые будут управлять дополнительными свободными пинами МК. Например, «PC0=1», «PC2=0» и т.д. Обязательно нужна команда конфигурации UART интерфейса МК.
Рассмотрим более тонкие детали работы программы МК. Кроме вышеперечисленных таймеров, задействован таймер, благодаря которому через каждые примерно полминуты по всем задействованным сокетам рассылаются т.н. контрольные TCP пакеты «keep-alive». Это нужно для проверки соединения в случае отсутствия пользовательского обмена данными. Если по какой-либо причине со стороны клиента не будет ответа с подтверждением в течение определённого времени, установленного внутри W5500, сработает т.н. таймаут, и сокет будет перезагружен. Соединение может внезапно потеряться, например, по причине разрыва на канальном или физическом уровне: выдернули Ethernet кабель, отключился Интернет или потеряно Wi-Fi соединение и т.д.
Основываясь на документации к чипу W5500 (datasheet) в программном коде реализованы следующие функции. Во-первых – базовые функции записи и чтения регистров W5500 по адресам. Функции верхнего уровня – аппаратный сброс, инициализация чипа, инициализация сокета, открытие сокета, сокет на прослушивание, дисконнет и закрытие сокета, отправка команды «keep_alive», перезагрузка сокета. Последняя функция представляет собой композицию вышеупомянутых функций: закрытие, открытие, прослушивание. Большинство функций возвращают значение статуса сокета после их выполнения. Наконец, самые основные функции – обработка принятой информации (чтение из буфера RX) и обработка отправляемой информации (запись в буфер TX). Рекомендации по реализации этих функций я взял с официального сайта производителя чипа W5500 (ссылка). Функция приёма переписывает принятые данные из буфера RX в собственный буфер (не кольцевой) размером 128 байт. Этого размера вполне достаточно для простых приложений, да и с микроконтроллера Atmega8 много не возьмёшь. В буфер TX W5500 функцией передачи переписываются данные из промежуточного буфера также небольшого размера. А в него в свою очередь попадают данные из кольцевого буфера UART. Последний реализован автоматически в среде разработки CVAVR с помощью вспомогательного приложения CodeWizardAVR на этапе создания проекта.
Модуль W5500 подключен к SPI интерфейсу МК (MOSI, MISO, SCK, SCLK). Кроме того, к определённому выходу МК подключен вывод RST (аппаратный сброс), и к входу внешнего прерывания INT0 подключен соответствующий вывод INT. Последний используется по прямому назначению: При возникновении того или иного события в модуле W5500 он формирует импульс на выводе INT, который обрабатывается контроллером в теле внешнего прерывания. МК узнаёт, на каких сокетах произошло событие, затем переписывает коды событий для каждого сокета в определённый массив. Дальнейшая обработка прерывания происходит внутри основного цикла программы. Всего документировано пять событий: клиент подключился, клиент отключился (точнее, подал запрос на отключение), поступили данные от клиента, сработал таймаут, данные отправлены успешно. В основном цикле обрабатываются все события, кроме последнего. В данную обработку помещён оператор switch-case. Самая большая часть программного кода на языке Си встречается в секции обработки третьего события (приём данных). В нём после функции обработки принятой информации также помещён оператор switch-case, но в данном случае этот «переключатель» связан с переменной, отвечающей за состояние сокета, о котором говорилось выше (значения 0, 1, 2). Первая секция отвечает за процедуру распознавания пароля. Принятые символы переписываются в отдельный парольный буфер. При определённых условиях работают функции сравнения принятой строки со строками-константами, содержащих пароли. В случае того или иного совпадения присваивается соответствующее состояние. Вторая секция самая простая – содержимое собственного буфера принятой информации перенаправляется на UART микроконтроллера. Это режим обычного использования. Третья секция (самая большая) отвечает за обработку команд – режим управления устройством.
Кроме продолжения обработчика прерываний в основном цикле программы помещены обработчики виртуальных таймеров – таймаут для разрыва соединения при неуспешной попытке ввода пароля, периодическая отправка «keep-alive» и отправка клиенту сформированного по таймеру TCP пакета. Ещё в тело основного цикла помещена функция чтения из UART, внутри которой переписываются принятые контроллером символы в собственный (промежуточный) буфер передачи и происходит сброс таймера, отвечающий за формирование TCP пакета.
Все процедуры сокетов помещены в цикл от 0 до 7, итератор которого привязан к номеру сокета. Таким образом, происходит последовательная обработка всех сокетов. Изначально я подразумевал, что, если присвоить каждому из восьми сокетов одинаковый номер порта, то можно обеспечить подключение до восьми пользователей по одному и тому же порту. Однако такая конфигурация не заработала, и данный вопрос пока отложен на будущее.
Разрабатывая печатную плату конструкции, я предусмотрел часы реального времени (RTC) на микросхеме DS1307. На двусторонней печатной плате размещены МК Atmega8, кварц на частоту 11.0592 МГц (частота выбрана для точности работы UART), разъём для модуля W5500, разъёмы портов МК (в том числе SPI для прошивки, UART), RTC с собственным кварцем и отсеком для батарейки CR2032, линейный регулятор на 5 В (7805), разъём питания и прочее. Эскиз печатной платы в программе «Sprint Layout» представлен на рисунке 11. Единственный элемент, который изображён красным цветом, припаивается на обратной стороне, но я его припаял на лицевую сторону.
Рис. 11. Эскиз печатной платы.
Фотографии готовой конструкции представлены на рисунке 12. Часы в данной конструкции будут использоваться для отметки времени при тех или иных событиях сокетов W5500, и данное время будет приписываться пользователю в терминал рядом с сообщением, если пользователь подключен в режиме управления. А также, часы пригодятся на будущее для экспериментов с протоколом настройки времени NTP или для других каких-либо целей.
Рис. 12. Фотографии готовой конструкции.
В заключении стоит отметить, что конструкция собственного изготовления по большей части оправдывает похожие устройства промышленного уровня. Основное достоинство – цена. Изготовить получилось гораздо дешевле, чем цена готового подобного устройства. А такой недостаток, как ограниченный функционал, неизбежен. В данном случае применён упрощённый контроллер Atmega8, так как ставилась соответствующая упрощённая цель.
Рис. 13. Промышленный конвертер TCP/IP – RS-232.
На рисунке 13 в качестве примера изображён промышленный конвертер TCP/IP в RS-232, выполненный на базе чипа W5100, очень похожим на W5500. У него, кроме гибкого интерфейса управления, есть ещё одно преимущество. Кроме работы с TCP/IP терминалом, имеется возможность с помощью специального драйвера, который поставляется с устройством, на клиентской стороне установить виртуальный COM-порт. Через него можно подключиться с помощью обычного терминала, у которого нет режима TCP/IP подключения. Более того, устройство может поддерживать полноценный обмен данными по RS-232 в случае, если вместо терминала через виртуальный COM-порт подключается какая-либо программа. То есть, устройство, изображённое на рисунке 13, является полноценным мостом RS-232 через сетевую инфраструктуру.