Данный туториал будет полезен программистам, которые перешли с avr или stm32 на одноплатные компьютеры под управлением Ubuntu. Какой конкретно использовать дистрибутив Linux - решать вам, но Ubuntu - самый дружелюбный дистрибутив.

Введение

Итак, ещё вчера вы программировали на микроконтроллере UART, GPIO и ничего не предвещало беды, но заказчик захотел ещё и 20" дисплей с тачскрином... И вот вы уже рассматриваете варианты одноплатных компьютеров (SBC). Их очень много. Поделюсь своим горьким опытом. Я искал по-дешевле и мой выбор остановился на Orange Pi.

Сначала модель PC PLUS. Для неё есть сборка Armbian со свежей ОС, в отличие от сайта производителя, где вам предложат Ubuntu 16. Но вот незадача, с Armbian OrangePi PC PLUS не выключается. OrangePi PC PLUS в конце пишет system halted, потому что за выключение отвечает со-процессор AR100 с закрытыми исходными кодами, которые не вошли в состав Armbian. Можно взять Ubuntu образ с сайта производителя. Там несколько образов, перепробовал все, только один реально выключает одноплатник. Что за отношение к пользователю у xunlong, что они выкладывают прошивки, где их детище невозможно выключить?! Также на PC PLUS возникли непреодолимые трудности с подключением экрана 4:3.

Далее я попробовал OrangePi 4G. Я конечно хочу иметь контроль над системой, поэтому android мне не подходит. Однако из-под Ubuntu на OrangePi 4G не работает ничего, кроме CPU. Никаких драйверов... Под Android работает всё, кроме HDMI, xunlong умудрились сделать HDMI, который несовместим с большинством мониторов (узнать будет ли совместим ваш монитор с OrangePi 4g заранее невозможно).

Далее я взял OrangePi 4B. В глаза бросается, что в консоли он сам себя именует Orange Pi 4. Но на этикетке на самом SBC написано 4B (на pcb маркировка v1.4). При установке на него Armbian любой версии под нагрузкой SBC сразу перезагружается. Я думал это брак, но Ubuntu 18 с сайта производителя работает стабильно под многочасовой нагрузкой (блок питания куплен у того же xunlong). Зато при старте эта же самая Ubuntu 18 с сайта производителя десяток секунд висит с сообщением CONFIG-ERROR) dhd_conf_set_intiovar : txbf setting failed -23 и я даже не могу предположить куда копать...

Также общий вывод про SBC. Если там GPU MALI, не покупайте. Постоянно публикуется информация что вот этот открытый драйвер наконец научился работать с MALI, но всё это вероятно закончится каким-нибудь DRI2: failed to authenticate или очень большой головной болью с кросскомпиляцией.

Мне лично кажется самым перспективным SBC сегодня STM32MP157C-DK2 Потому что действительно открытый, не MALI, и процессоры можно купить даже в розницу.

Начало работы

А далее я продолжу рассказ на примере OrangePi 4B. Скачанную с сайта производителя Ubuntu 18 на удивление успешно удалось обновить до Ubuntu 20.04 стандартным способом. Наверное это благодаря поддержки RK3399 в ядре?

Перед написанием кода обновим компилятор. Здесь нужно пояснить:

  • gcc - это компилятор Си

  • g++ - это компилятор Си++

  • gcc --version или g++ --version показывает версию компилятора

  • g++ - это компилятор по умолчанию, но при этом у вас в системе могут быть g++-9 и g++-10, следите за тем, что в вашей системе скрывает симлинк g++

Если gcc и g++ ссылаются не на ту версию, то надо переназначить симлинк подобным образом:

sudo ln -s g++-10 /usr/bin/g++

Теперь g++ будет подразумевать именно 10 версию. Для gcc допишите сами. Внимательный читатель уже сделал вывод об общем устройстве Linux: всегда можно запустить то, что есть в каталоге /usr/bin, хотя бы в виде симлинков. Все остальное нужно запускать, обращая внимание на тот каталог, в которым вы сейчас находитесь. Для поиска себя очень удобна консольная команда ls.

Если вчера мы писали на Си, то в ближайший его родственник в мире SBC - это Си++. На нём можно писать полнофункциональные приложения, задействуя все возможности SBC. А так как хочется всего готовенького, то я рекомендую Qt. В двух словах Qt - это свалка, а на свалке, как известно, есть всё: GUI, com port, ethernet, 3D, рисовалка графиков, парсер xml и многое другое...

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

Итак, для создания кода на Qt у нас есть два путя. Собирать код на мощном персональном компьютере и деплоить его на SBC или же собирать код на самом SBC. У меня, с одной стороны, не получилось настроить кросскомпиляцию, с другой стороны мой ноутбук по мощности сравним с OrangePi 4B.

Qt - поистине кроссплатформенный фреймворк. Это означает, что при работе с Qt сталкиваешься с вещами, о которых не задумываешься при работе во многих других продуктами. IDE Qt Creator и Qt легко скачиваются с официального сайта, но только под x86_64 (у меня AArch64) и Qt там собран динамически. Собран динамически означает, что Qt не выдаёт после сборки один исполняемый файл, а проект состоит из многих кусочков. А чтобы после сборки получать единый исполняемый файл, нужно собрать Qt статически, получить qmake и уже с этим qmake обрабатывать пользовательские проекты.

Сборка Qt

О сборке Qt 5.15 можно говорить бесконечно. Однако я ограничусь примером минималистичной сборки. Итак, мне нужен GUI, com port, рисовалка графиков. При этом я хочу не только писать на C++20, но и чтобы стандартные библиотеки тоже были соответствующей версии. Вот что бывает, когда стандартные библиотеки (привет std) не той версии.

Сборка программы в Ubuntu обычно подразумевает выполнение правила out-of-source build. Не рекомендую пытаться проводить манипуляции вне родительского каталога! Также не рекомендую использовать файловые системы, отличные от ext4, использовать для сборки виртуальные хранилища. Итак, имеем базовый каталог QtFromGit, перейдем в него в консоли. Далее будем следовать инструкции Разместим каталог build для сборки (в нём будет собираться мусор от компилятора) и каталог build_artifacts для результата сборки, где и будет лежать вожделенный qmake, если сборка пройдёт успешно. Скачаем в QtFromGit Qt:

git clone git://code.qt.io/qt/qt5 qt5 && cd qt5 && git checkout 5.15 && cd qt5

perl init-repository --module-subset=default,qtcharts,qtserialport,-qtactiveqt,-qtcanvas3d,-qtdocgallery,-qtfeedback,-qtserialbus,-qtconnectivity,-qtdeclarative,-qtquickcontrols2,-qtsvg,-qtquickcontrols,-qtwebengine,-qtwayland,-qtandroidextras,-qtdoc,-qtgraphicaleffects,-qtqa,-qttranslations,-qtvirtualkeyboard,-qtquicktimeline,-qtquick3d,-qtrepotools,-qttools,-qtshadertools,-qtimageformats,-qtnetworkauth,-qtwebsockets,-qt5compat,-qt3d,-qtsensors,-qtquicktimeline,-qtmultimedia,-qtdatavis3d,-qtscript,-qtgamepad,-qtlottie,-qtmacextras,-qtremoteobjects,-qtlocation,-qtspeech,-qtwebchannel,-qtwebglplugin,-qtwebview,-qtwinextras,-qtpurchasing,-testsuites,-qtxmlpatterns

Вариант А. Для использования с X11:

cd ../build && ../qt5/configure -release -static -opensource -make libs -nomake examples -nomake tests -confirm-license -no-pch -no-xcb -no-xcb-xlib -no-gtk -skip webengine -skip qtwayland -skip qtdoc -skip qtgraphicaleffects -skip qtqa -skip qttranslations -skip qtvirtualkeyboard -skip qtquicktimeline -skip qtquick3d -skip qt3d -skip qtrepotools -skip qttools -skip qtimageformats -skip qtnetworkauth -skip qtwebsockets -skip qtactiveqt -skip qtmacextras -skip winextras -skip qtmultimedia -skip qtgamepad -skip qtserialbus -skip qtspeech -skip qtsensors -skip qtcharts -skip qtlocation -opengl es2 -qpa eglfs -no-ssl -c++std c++2a -prefix ../build_artifacts

Вариант Б. Для режима киоска:

export QT_QPA_EGLFS_INTEGRATION=eglfs_kms

export QT_DEBUG_PLUGINS=1

cd ../build && ../qt5/configure -release -static -opensource -make libs -nomake examples -nomake tests -confirm-license -no-pch -no-xcb -no-xcb-xlib -no-gtk -skip webengine -skip qtwayland -skip qtdoc -skip qtgraphicaleffects -skip qtqa -skip qttranslations -skip qtvirtualkeyboard -skip qtquicktimeline -skip qtquick3d -skip qt3d -skip qtrepotools -skip qttools -skip qtimageformats -skip qtnetworkauth -skip qtwebsockets -skip qtactiveqt -skip qtmacextras -skip winextras -skip qtmultimedia -skip qtgamepad -skip qtserialbus -skip qtspeech -skip qtsensors -skip qtcharts -skip qtlocation -kms -opengl es2 -qpa eglfs -no-ssl -c++std c++2a -prefix ../build_artifacts

После выбора варианта соберем и установим Qt

make -j8

make install

В процессе сборки контролируйте расход ОЗУ! Это можно делать с помощью htop. При превышении разумного предела используйте файл подкачки!

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

sudo ln -s полныйпуть/QtFromGit/buildartifacts/bin/qmake /usr/bin//qmake

Далее соберем qtcharts. В каталоге QtFromGit создайте каталог build_qtcharts. Перейдите в него с помощью cd build_qtcharts.

qmake ../qt5/qtcharts/qtcharts.pro INCLUDEPATH+=../qt5/qtcharts/include/QtCharts CONFIG+=release

make -j8

make install

Таким образом мы установили Qt на Orange Pi 4B. Для использования com port не забудьте добавить пользователя в группу dialout и перезагрузиться. В случае проблем со сборкой, можете вызвать make clean, но работает это очень долго, так что проще удалить все файлы в папке build. В случае проблем с конфигурированием (например, Qt не увидел каких-то модулей, которые вы доустановили после конфигурирования), рекомендуется сделать очистку и переконфигурировать. Очистка:

git submodule foreach --recursive "git clean -dfx" && git clean -dfx

Про память

В моём случае расход памяти следующий. Размер папки qt5 (исходные коды Qt) 325 МБ. Размер папки build (мусор от компилятора) 143 МБ. Папку с исходным кодом и мусором сборки можно удалить после успешной установки Qt. Размер папки build_artifacts, содержащей статически собранный Qt, составил 150 МБ. Но цифры могут быть и несколько десятков ГБ, если конфигурировать Qt с большим количеством модулей. Также важен расход оперативной памяти. В моём случае было достаточно 4 ГБ ОЗУ и 1,8 ГБ файла подкачки. Из моего опыта этого будет достаточно для сборки Release, но если захотите сборку с флагом -developer-build (чтобы иметь много версий Qt на одной машине), то будьте готовы предоставить более 12 ГБ совокупного объёма ОЗУ+файл подкачки.

Если вас заинтересовала данная тема, поддержите в комментариях! Планирую вторую часть посвятить миганию светодиодом.