Автор | Сообщение |
---|---|
admin | |
Волна интереса к микроэлектронным устройствам и их взаимодействию между собой для промышленных и бытовых нужд привела к развитию большого количества конструкторов для разработки на базе достаточно мощных SoC (систем на чипе), достаточно миниатюрных относительно микроконтроллерных решений, но уже содержащих в себе полноценную операционную систему. Разработка приложений для таких конструкторов практически не отличается от обычной серверной разработки, за исключением того, что ограничение по ресурсам все равно надо держать в уме. По мере роста производительности и возможностей все больше оборотов набирает практика использования интерпретируемых языков высокого уровня, таких как Lua, Python, JS для разработки приложений. Некоторые языки постепенно проникают и в “младших братьев”, микроконтроллеры, правда, в очень ограниченном варианте. Причин тому несколько:
Увы, за все удобства приходится платить. В данном случае цена за удобства — самые ценные ресурсы, производительность и размер кода (во многих случаях приходится носить с собой довольно объемную среду исполнения). Поэтому полевое применение языков высокого уровня в SoC и SoM — штука неоднозначная и, местами, компромиссная. Мы используем для разработки язык Erlang, применяя его как по прямому назначению (создание серверных приложений и control plane), так и весьма непривычно — web-приложения. Поэтому идея использовать инфраструктуру этого языка для создания IoT-решений возникла задолго до появления плат, на которых среда выполнения Erlang-а могла бы работать без проблем. Причин использовать Erlang было множество, самые весомые:
Первой рабочей платой, на которой мы попробовали Erlang, была Carambola 2 литовских разработчиков 8devices, собранной на популярном чипе AR9331. Первая версия этой платы, увы, имела недостаточный объем flash-памяти, чтобы поместить среду выполнения. А вот вторая версия уже вполне себе позволяла вместить как ERTS, так и небольшое приложение. Установка производилась классическим для такого рода устройств методом — сборкой образа OpenWRT, содержащего Erlang, с последующей прошивкой его в flash-память устройства. Первый запуск среды, увы, привел к разочарованию — все повисло. Причины этого я уже рассказывал на конференции InoThings 2018, но, увы, как потом оказалось, ввел коллег в заблуждение, ошибочно назвав источник такого поведения. Вкратце перескажу. При работе с файлами виртуальная машина ERTS использует тип off_t, размер которого в дистрибутиве вычисляется при автоконфигурировании сборки (если она идет на целевой платформе) или же подставляется из среды кросс-компиляции, как то и случилось в случае OpenWRT. Непонятно почему, но в настройках для процессоров MIPS и производных в файле конфигурации сборки стоит вдвое больший размер, чем есть по факту. Проблемы бы не возникало, если бы код виртуальной машины использовал не директивы препроцессора типа
Исправляющий патч и пакет с предпоследней версией ERTS для OpenWRT можно скачать с GitHub. Помимо этого проблем пока не наблюдалось, все работало как и ожидается. Второй аппаратной платформой, на которой мы попробовали Erlang, стал конструктор LinkIt Smart 7688 от компаний Mediatek и SeeedStudio, специально созданный для быстрого прототипирования и изучения основ. Эта плата просто апофеоз разврата в плане ресурсов — подросшая в полтора раза частота MIPS-ядра, больше оперативной памяти (для ERTS это важно, GC не дремлет) и больше flash-памяти, а также наличие MicroSD-карты и возможности использования со-процессора Atmel Atmega 32U4 в версии Duo для работы с периферией. В общем, платформа очень даже подходила для продолжения банкета, а наличие дополнительных подключаемых устройств, соединяющихся без пайки, позволяет быстро и условно красиво собрать на коленке стенд для испытаний. В комплекте с платформой идет ПО с собственным web-интерфейсом, а также с Python и NodeJS-библиотеками для разработки. Экосистема для сборки не изменилась — это, по-прежнему, OpenWRT. Если по каким-то причинам вы посчитаете лишним все это многообразие, то на вышеупомянутом репозитории есть пакеты, содержащие минимальный набор обязательных компонентов. После сборки образ flash-памяти записывается на устройство и после перезагрузки можно смело пользоваться REPL-ом. Для построения приложений на Erlang-е для IoT необходимо решить один архитектурный вопрос. Язык проектировался и разрабатывался с прицелом на то, что будет служить control plane, т.е. управляющим слоем, в то время как работать с железом предполагалось посредством FFI. Для этого предусмотрены три типа взаимодействия:
Дилемма заключается в следующем — мы можем вынести в FFI только транспортные вещи (т.е. поддержку GPIO, I2C, SPI, PWM, UART и т.д.), а взаимодействие непосредственно с датчиками и прочими устройствами реализовать на Erlang-е, или же, наоборот, вынести драйвера устройств целиком в код внешних модулей, оставив приложению получение сырых данных и их обработку, в этом случае, возможно, имеет смысл воспользоваться уже написанным кодом. Мы решили использовать первый вариант. Причин тому несколько:
Поэтому довольно быстро была найдена библиотека ErlangALE, которая содержала в себе уже реализованную поддержку GPIO, I2C и SPI через интерфейсы ядра, а о них, в свою очередь, уже позаботились разработчики аппаратной платформы. Библиотека для работы с UART у нас уже была проверенная, плюс довеском подключили erlexec — приложение, позволяющее создавать и управлять процессами ОС. Все перечисленные приложения использовали порты (отдельно запускаемые бинарные процессы) для работы с оборудованием и ОС, что требовало поддержки кросс-компиляции для языков С и С++, для чего был написан достаточно вычурный shell-скрипт, конфигурирующий среду сборки на применение нужных компиляторов. Для тестирования принятых решений мы собрали простое устройство из LinkIt Smart 7866, двух I2C устройств (датчика температуры и давления BMP280 и OLED-дисплея 128 на 64 точки) и USB GPS-модуля, отдающего данные по UART. GPIO был проверен на светодиоде на плате, он работает, а SPI-дисплей подключать показалось ненужным на данном этапе усложнением. Получилось достаточно компактное и простое приложение, исходный код можно посмотреть на Github-е. Я не буду углубляться в фрагменты кода, а постараюсь обзорно описать, как работает приложение. Драйвера всех устройств выполнены в виде gen_server-процессов, это удобно, потому что позволяет складывать в состояние дополнительные параметры и, иногда, состояние устройства. Последнее можно видеть на примере uart_gps — данные с UART-а приходят асинхронно, разбираются парсером NMEA0183 и результаты записываются в состояние процесса, откуда достаются по запросу. Основной цикл приложения описан в модуле gps_temp_display — ежесекундно процесс вычитывает данные GPS и запрашивает состояние температуры и давления у BMP280 и выдает их на OLED-дисплей. Ради интереса можно посмотреть на драйвера дисплея и датчика BMP280 — все получилось достаточно лаконично, 150-170 строк на модуль. В общем и целом на вышеуказанную задачу (написание кода драйверов, объединение все в одно приложение, сборка и тестирование) ушло порядка четырех вечеров по два часа в среднем, т.е. строго говоря — пара рабочих дней. Как мне лично кажется, это хороший показатель, чтобы попробовать применить Erlang в более сложных и серьезных встраиваемых приложениях, не требующих строгих ограничений реального времени. Источник: https://habr.com/post/417245/ |
|
Сообщения: 463 |