![](https://habrastorage.org/webt/16/w8/gv/16w8gvq10zcv-qnxtqhvuhngpkc.jpeg)
Сборка
Первым делом начинаем со сборки. Это проще всего делать на эмуляторе QEMU, т.к. там все точно влезает по памяти, и поэтому легко проверить всех ли компонентов хватает для сборки приложения. Проверив, что все animatedtiles успешно собралось, я легко перенес его в конфигурацию для нужной мне платы.
Первый запуск на плате
Размер экрана у STM32F746G-Discovery 480x272, при запуске приложение нарисовалось только в верхнюю часть экрана. Нам естественно захотелось выяснить в чем дело. Конечно можно уйти в отладку прямо на плате, но есть более простое решение. запустить приложение на Линукс с теми же самыми размерами 480x272 с виртуальным фреймбуфером QVFB.
Запускаем на Линукс
Для запуска на Linux нам потребуется три части QVFB, библиотека Qt, и само приложение.
QVFB это обычное приложение, которое предоставит нам виртуальный экран для работы Qt. Собираем его как написано в официальной документации.
Запускаем с нужным размером экрана:
./qvfb -width 480 -height 272 -nocursor
Далее, собираем библиотеку Qt как embedded, т.е. С указанием опции -embedded. Я еще отключил разные модули для ускорения сборки, в итоге конфигурация выглядела вот так:
./configure -opensource -confirm-license -debug -embedded -qt-gfx-qvfb -qvfb -no-javascript-jit -no-script -no-scripttools -no-qt3support -no-webkit -nomake demos -nomake examples
Далее собираем приложение animatedtiles (qmake + make). И запускаем скомпилированное приложение, указав ему наш QVFB:
./examples/animation/animatedtiles/animatedtiles -qws -display QVFb:0
После запуска я увидел, что на Линуксе также рисуется только в часть экрана. Я немного доработал animatedtiles, добавив опцию “-fullscreen”, при указании которой приложение стартует в полноэкранном режиме.
Запуск на Embox
Модифицированный исходный код приложения будем использовать в Embox. Пересобираем и запускаем. Приложение не запустилось, при этом появились сообщения о нехватке памяти в Qt. Смотрим в конфигурацию Embox и находим что размер кучи установлен 2Мб и его явно не хватает. Опять же, можно попробовать выяснить этот момент с прямо на плате, но давайте сделаем это с удобствами в Линукс.
Для этого запускаем приложение следующим образом:
$ valgrind --tool=massif --massif-out-file=animatedtiles.massif ./examples/animation/animatedtiles/animatedtiles -qws -fullscreen
$ ms_print animatedtiles.massif > animatedtiles.out
В файле animatedtiles.out видим максимальное значение заполненности кучи порядка 2.7 Мб. Отлично, теперь можно не гадать, а вернуться в Embox и поставить размер кучи 3Мб.
Animatedtiles запустилось.
Запуск на STM32F769I-Discovery.
Давайте попробуем еще усложнить задачу, и запустим тот же пример на подобном микроконтроллере, но только с большим разрешением экрана — STM32F769I-Discovery (800x480). То есть теперь под фреймбуфер потребуется в 1.7 раз больше памяти (напомню, что у STM32F746G экран 480x272), но это компенсируется в два раза большим размером SDRAM (16 Мб против 8Мб доступной памяти SDRAM у STM32F746G).
Для оценки размера кучи, как и выше, сначала запускаем Qvfb и наше приложение на Линуксе:
$ ./qvfb -width 800 -height 480 -nocursor &
$ valgrind --tool=massif --massif-out-file=animatedtiles.massif ./examples/animation/animatedtiles/animatedtiles -qws -fullscreen
$ ms_print animatedtiles.massif > animatedtiles.out
Смотрим расход памяти в куче — около 6 МБ (почти в два раза больше, чем на STM32F746G).
Осталось выставить нужный размер кучи в mods.conf и пересобрать. Приложение запустилось сразу и без проблем, что и продемонстрировано этом коротком видео
Традиционно можно воспроизвести результаты самостоятельно. Как это сделать описано у нас на wiki.
Данная статья впервые была нами опубликована на английском языке на embedded.com.
EddyEm
Qt — невменяемая жиробасина с кучей оверхеда. Она даже на десктопе не нужна, т.к. есть более легковесные и вменяемые библиотеки для виджетов. А уж на микроконтроллере этой дряни точно не место!
Про C++ вместо C вообще молчу…
abondarev Автор
Ну некоторые с вами не согласятся. Особенно на счет C++.
На счет виджетов, в принципе согласен, если нужны только виджеты, есть более легкие альтернативы, например LVGL, тоже поддержанный в Embox. Но Qt это очень крутой фреймворк, и используют его не только ради виджетов. И например, если уже есть код на Qt то его переписывание может оказаться сложной задачей. В статье же показана возможность, разработать и отладить ПО на линуксе, а затем запустить на целевой платформе.
devprodest
Голубчик, про плюсы это вы зря. Если грамотно использовать, то на много интереснее и удобнее выходит.
abondarev Автор
Да, согласен. Но нужно грамотно использовать :)
И не нужно забывать что некоторые вещи недоступны bare-metal
Gromin
Немного интересуюсь этой темой. Подскажите, пожалуйста, где именно в QT куча оверхеда? И какие можно взять альтернативы (с соизмеримыми возможностями, конечно)?
Тут, я так понимаю, за основу взят очень старый Qt 4.8. С 5 версии они серьезно переработали потроха и, к тому же, у них есть специальная версия Qt для MCU. Увы, платная, но успешно применяемая.
А можете чуть подробнее помолчать? Чем именно C++ не подходит для контроллеров? Только, пожалуйста, не надо про «больший размер бинарников» и «использование динамической памяти».
Первое — чушь, доказательства даже на Хабре были. Например: habr.com/ru/post/347980
Второе — это про STL, а не про C++. Есть реализации STL для контроллеров, а вообще STL использовать и не обязательно. И без нее у «плюсов» остается еще куча плюсов.
fse
Не склонен катить бочку на QT, т.к. считаю, что более удачных, открытых и кроссплатформенных фреймворков нет. По крайней мере не знаю таких, если не брать в стороне стоящую яву.
Но с критикой невозможно не согласиться, она имеет место быть.
Первое что пришло в голову — это сети. Нагруженный обмен данными может проигрывать около 20% относительно сокетной реализации (некроссплатформенной). Если обмен делаете в QT малыми датаграммами, то потери выше. Если взять тонкую обвязку над сокетами, типа mongoos-a, то потери пренебрежимо малы.
Как бы это и понятно. Странно было бы считать, что за удобство не платишь. В оправдание QT можно лишь сказать, что если из-за QT провалил обмен на максимум 20%, то из-за среднестатистического программиста провалишь ещё минимум на 20%.
А дело не в плюсах. Дело в устоявшемся плюсовом код-стайле. В среднем, число вызовов, число копирований на стеке и число выделений/реаллокаций памяти в плюсах выше, чем в си. Хотите снизить число вызовов — юзайте вместо обилия геттеров (которые далеко не все инлайнятся) меньший набор функций + жертвуйте конструкторами. Хотите минимизировать число выделений? Юзайте статические массивы вместо контейнеров… В конце пути вас ждёт си.
Вообще, это всё не досужие разговорчики. Я встречал стандарты прямо запрещающие использование динамической аллокации памяти в лайф-критикал приложениях. Причин несколько и они, думаю, ясны.
Безусловно. Но моё личное мнение — повышаются требования к квалификации программиста. Я уверен, что смог бы писать на плюсах код под MCU, который не уступает си, НО! Стиль такого кода — сильно не в тренде, а чтобы его почувствовал на низком уровне специалист нужна квалификация. Предполагаю, что именно поэтому, к примеру, ядро linux, freertos и всевозможные HAL-слои пишутся исключительно на си, стиль кода которого сам по себе не допускает излишеств.
Надеюсь, смог донести мысли.