Embox принимал участие в IT фестивале TechTrain. Мы как и в первый раз привезли железки и вживую показали наши достижения. О некоторых мы уже писали на хабре, но мало ли кто не поверил :). Были показаны VoIP телефон, Qt и OpenCV, все на базе STM32F7-Discovery. Кроме стенда мы сделали три доклада. Идеи первого про открытый проект я уже описывал на хабре. В данной статье хочу рассказать идеи еще одного нашего доклада, который назывался “Запускаем “десктопное” ПО на микроконтроллерах”. Ну и пользуясь случаем, немного расскажу про свои ощущения о фестивале.
TechTrain
Вначале позволю себе немного рассказать о самом фестивале. Кому не интересно можно сразу перемотать на раздел “Запускаем “Десктопное” ПО на микроконтроллере”
Первое что бросалось в глаза на фестивале — очень много народу. Мы устали стоять на стенде, выступать, проводить квест, общаться. С другой стороны, это было очень весело и интересно, а главное мы получили массу положительных эмоций, например, нам несколько человек сказали, что у нас хороший блог на хабре :). Участники фестиваля были из самых разных сфер деятельности, причем были даже не из IT, ведь лозунг фестиваля “большой фестиваль для разработчиков, инженеров и им сочувствующих.”. Было много детей, один мальчик под конец фестиваля утащил со стенда машинку робота и с ним игрался. Ни мальчик ни робот не пострадали.
Чтобы было более понятна широта аудитории, проиллюстрирую ее по другому. На фестивале проводили множество активностей, одна из них квест. Участникам квеста нужно было подходить на стенды, выполнять придуманные задания и получать печать. За это кто-то даже получил целый квадрокоптер. Но сейчас не об этом. Мы тоже были одним из мест где можно было получить печать. У нас были подготовлены задания, в том числе и вопросы. Вопросы были простыми, касались СПО и встроенных систем. Но контингент был настолько разный, что одни обижались на простоту вопроса, а другие входили в ступор. Последним мы естественно помогали, рассказывали (или предлагали погуглить) про такие вещи как: “кто является создателями языка Си”, “чем знаменит Линус Торвальдс”, “чем отличается микропроцессор от микроконтроллера” или “что такое кросс-компилятор”. В итоге без печати никто не ушел. Кстати, было немного странно, но подозрительно многие легко расшифровывали “GNU — GNU is not Unix”. Наверное к Столлману подготовились. :)
Второе вытекает из первого. Были развлечения для очень широкой аудитории. Например, Хабр привез песочницу. Правда это была не местная песочница, где можно получить инвайт за статью, но в ней можно было на славу поваляться. Про инвайты в песочнице я не догадался спросить, может и давали как в настоящей песочнице. Был клуб старых компов, на них можно было поиграть, что многие и делали. Были игровые автоматы из Музея советских игровых автоматов. Сбербанк, предлагал зону релаксации, в ней также можно было поиграть уже в play station. Были традиционные да IT кикеры и множество других развлекух. К сожалению, нам нужно было работать поэтому говорю только про то что было видно с нашего стенда.
Третьим и наверное главным было то, что организаторам удалось собрать представителей фактически всех it направлений от веб разработки и распределенных систем до embedded. От разработчиков и других технарей, до human resources и просто интересующихся it, например геймеров (ведь можно было зарубиться с самим Ромеро) или DIY энтузиастов. Были QA из COMAQA были тим-лиды из Burning Lead. Были сообщества разных городов (Ростов, Тверь, Краснодар). В итоге получились доклады и стенды очень разные по тематике. Для примера наш стенд находился между сообществом тим лидов Burning Lead и стендом “Санкт-Петербургского клуба IT-директоров”.
В результате к нашему стенду подходили люди с сильно различающимся бекграундом, были и веб разработчики и DotNet-чики, были JS и плюсовики. Кто-то вспоминал, что он что то делал на AVR еще в универе, кто то рассказывал, что он развлекается с RaPi или Arduino. Поразительно много было DotNet-чиков, многие интересовались нет ли у нас .NET Micro Framework. Мы даже сильно задумались не затащить ли нам еще и его. Ожидаемо было много вопросов про Rust. Короче, на мой взгляд, организаторам удалось достаточно хорошо воплотить в жизнь идею фестиваля “Узнай, чем живут другие!”. Ведь как и на любом фестивале, тут главное других посмотреть и себя показать :).
Да фоток здесь не приводим. Немного фоток, в том числе и с живым мальчиком Володей, можно посмотреть у нас в группе. Ну и естественно в группе techtrain куча качественных фоток, обещали еще выложить.
Запускаем Десктопное ПО на микроконтроллере
Мой доклад являлся своего рода подведением итогов по результатам нескольких наших работ о запуске десктопного ПО (Qt, OpenCV, pjsip). Доклад ориентирован на широкую публику. Для хабра я постараюсь сократить многие детали, а для необходимых вещей дам ссылку или ключевые слова для поиска.
Для начала я приведу своего рода агенду. По сути дела будет 3 части. Во-первых, я объясню трудности переноса десктопного ПО на микроконтроллеры, попутно объясню разницу между микроконтроллером и микропроцессором. Еще я отвечу на ключевой вопрос
Чем отличаются микроконтроллеры от микропроцессоров
Так звучал один из наших вопросов на квесте и может быть под влиянием этого появилась статья на Типичном программисте, рассказывающая чем они отличаются. Со всем в статье согласен, но попробуем объяснить своими словами и сделаем несколько другие акценты.
Что такое микроконтроллер (Micro Controller Unit, MCU)? Если взглянуть в википедию, то можно понять, что микроконтроллер это система на кристалле, то есть в одном чипе располагается и процессор и периферия.
Термин система на кристалле (System-on-a-Chip, SoC ) является более широким понятием чем микроконтроллер. Это такая интегрированная в один чип электронная схема, которая содержит микропроцессор (CPU) и периферию. В любом мобильнике есть чип, в котором кроме нескольких процессорных ядер, есть куча периферии. Даже x86 процессоры сейчас включают в себя функции мостов и даже gpu. Но я хочу заострить внимание не на четкой классификации, а на особенностях. Все знают, что системы на кристалле:
- Меньше потребляют
- Дешевле стоят
- Менее производительные
Не все знают, что они еще и более надежны за счет уменьшения числа контактов и могут иметь больший температурный диапазон.
Микроконтроллер имеет еще большую интеграцию и включает в себя еще и память (ОЗУ и ПЗУ), которую тоже относят к периферии. Соответственно, свойства сохраняются, еще меньше потребляют, еще дешевле стоят, еще менее производительные, еще надежнее.
Об “еще менее производительные” хочу поговорить подробнее. Дело в том, что с одной стороны это правда, взять любой современный CPU или SoC общего назначения и увидим существенно большую производительность в так называемых DMIPS. Но если задуматься, зачем такая производительность? Для примера приведу игры Quake и Doom (создатель которых Джон Ромеро был на фестивале), они прекрасно работали на Pentium MMX. Но производительность систем на базе этого CPU уже перекрывают топовые микроконтроллеры. Я имею в виду STM32F7 или даже STM32H7. То есть на базе этих MCU вполне можно выполнять приложения уровня Doom и Quake, что согласитесь вполне не плохо.
Поговорим еще об одной особенности MCU — внутренняя память. Она, как я уже сказал, находится прямо на кристалле, и соответственно, очень быстрая. Но ее, естественно, мало. Но насколько мало? Микроконтроллер STM32F769 содержит 2 mb flash (ПЗУ) и 512 + 16 + 4 кб SRAM (ОЗУ). Кроме того например на плате STM32F769i-disco есть еще внешняя память (128-Mbit SDRAM и 512-Mbit Quad-SPI Flash memory), которая адресуется напрямую. Я даже не говорю о возможности подключить sd-карточку или usb. Ну а если вспомнить известную фразу “640 кб должно хватить каждому”, то возникает резонный вопрос — почему же современное десктопное ПО такое прожорливое? Например, калькулятор в windows 10 в режиме простоя потребляет аж 16 Мб памяти.
Перейдем к следующей особенности MCU, наличию ПЗУ. На самом деле, системы с CPU тоже содержат ПЗУ из нее начинается выполнение, и стартует BIOS, но остальное ПО загружается в оперативную память и из нее исполняется. В embedded системах принято выполнять код напрямую, то что называется eXecute-In-Place (XIP), Linux, кстати, тоже поддерживает этот режим, но основным все же является загрузка всего в основную память и уже тогда выполнение. Возможность выполнения напрямую из ПЗУ важна по двум причинам: первая — гарвардская архитектура разделение на шину команд и шину данных позволяет увеличить скорость выполнения программ; вторая — ну естественно, тратится меньше памяти, ведь как минимум сегмент кода не нужно никуда дополнительно копировать.
Еще одной ключевой особенностью MCU является отсутствие такого модуля как MMU, то есть, у микроконтроллеров нет аппаратной поддержки управления виртуальной памятью. В MCU и то не во всех есть MPU, а код выполняется в одном адресном пространстве, поэтому трудно организовать полноценный fork(). Но сам fork() как мы писали в статье «fork() vs. vfork()» довольно тяжелый системный вызов, причем по функциональности он, во многих случаях, может быть заменен на vfork() или posix_spawn().
Подводя итог, чем же отличаются микроконтроллеры от микропроцессоров, можно сказать следующее:
С точки зрения аппаратной части:
- Микроконтроллеры имеют всю необходимую периферию в том числе и память
- Микроконтроллеры имеют существенно меньше памяти
- Микроконтроллеры не имеют аппаратного блока управления памятью MMU
- Микроконтроллеры имеют более низкую тактовую частоту и могут иметь другую процессорную архитектуры (подархитектуру)
С точки зрения потребительских свойств:
- Микроконтроллеры меньше потребляют энергии, могут работать от батарейки
- Микроконтроллеры дешевле
- Микроконтроллеры надежнее
- Микроконтроллеры менее производительные
Зачем запускать десктопное ПО на микроконтроллере
Итак, MCU менее производительные и изначально предназначались ( и предназначаются) для задач управления. Так зачем же запускать на них ПО предназначенное для другого класса систем? Ну пусть даже их мощности уже хватает для подобных задач, но ведь эти задачи можно решать и традиционным для микроконтроллеров образом. То есть использовать различные маленькие RTOS или писать код с нуля, то что называется bare-metal. Существует очевидный ответ, изначально задачи управления были очень простыми, сейчас требования к функциональности сильно растут. Даже от какой нибудь захудалой лампочке ожидают управление через интернет, я уже не говорю о чайнике, они наверное скоро будут подбирать состав чая по настроению владельца и подогревать оптимальное количество воды до оптимальной температуры в целях улучшения экологической обстановки. :)
Поэтому ничего удивительного, что постоянно идут попытки использовать уже разработанное ПО в микроконтроллерах. Например, одной из первых и широко известных попыток запускать Linux на маленьких платформах является ucLinux, сейчас это режим NOMMU в основном Linux. Идея была запускать Linux на аппаратных платформах без MMU, а ведь мы выяснили что это одно из ключевых отличий CPU от MCU.
Коротко преимущества использования готового ПО:
- Сокращение расходов на разработку
- Сокращение времени выхода на рынок
- Сокращение ошибок в коде. Готовое ПО более надежнее.
Как мы это делаем в Embox
Тут сами понимаете, можно рассказывать очень долго, но я постараюсь опять же тезисно и доступно обозначить основные моменты.
Первое. Embox использует систему сборки Mybuild с собственным языком описания модулей и системы, мы писали о ней в статье «Mybuild — система сборки для модульных приложений». Данная система сборки позволяет не включать в образ ничего лишнего, точнее включать только то что требуется. Можно действительно очень тонко задавать характеристики системы, например для запуска PJSIP на STM32F7 мы ограничили количество ethernet пакетов 16 просто написав строчку в конфигурационном файле для системы
include embox.net.skbuff(amount_skb=16)
Mybuild анализирует зависимости и генерирует различные артефакты, в том числе заголовочные файлы, линкер скрипты и Makefile -ы. Все это позволяет существенно уменьшить количество требуемой памяти и вообще не включать те части которые не используются.
Второе. Очевидно, что Embox должен поддерживать POSIX и он поддерживается. Причем у нас реализована собственная стандартная библиотека, ведь она тоже должна перестраиваться в зависимости от конфигурации системы.
Третье. Статическая линковка. Для того чтобы избежать проблем с единым адресным пространством, уменьшить размер образа и включать только требуемые части мы используем статическую линковку. На разных стадиях собираются разные части системы, но окончательно все (ядро, все подсистемы, библиотеки и приложения) линкуется в единый образ. В нем есть вся информация обо всех символах в образе. И хотя на первый взгляд мы имеем много приложений со стандартными точками входа int main(..), но в результирующем образе, это будут разные символы, которые будут доступны в системе из командной строки.
Четвертое. Нам пришлось реализовать рантайм для C++, поскольку многие популярные приложения и библиотеки используют плюсы.
Пятое. Мы в систему сборки добавили возможность использовать
./configure; make; make install
Предварительно скачав откуда-то исходники и наложив необходимые патчи.
Заключение
На сегодняшний день функциональные требования к системам, которые раньше делались на микроконтроллерах, сильно выросли. От систем управления ожидают сопоставимой с универсальными системами функциональности. Характеристики микроконтроллеров тоже сильно выросли, что позволяет запускать на них ПО с соответствующей функциональностью. Исторически ПО для микроконтроллеров в целях оптимизации писалось под конкретную задачу, но с увеличением функциональных требований необходимо применять подходы из мира универсальных систем, которые позволяют сильно увеличить надежность ПО, а именно, переиспользование модулей, распределенная разработка. Универсальное ПО хоть и не учитывает особенности встроенных систем, но имеет существенно больший и хорошо отлаженный функционал. Поэтому применение десктопного ПО на микроконтроллерах дает выигрыш. Ведь с одной стороны, можно использовать более дешевую, надежную и менее потребляющую аппаратную платформу, а с другой стороны, существенно снижаются затраты на разработку подобных систем.