- PVSM.RU - https://www.pvsm.ru -

В этой статье мы автоматизируем процесс сборки и установки Linux-системы на микроконтроллер STM32MP157-DK2 [1]. ОС будет обладать минимальной функциональностью, но зато мы соберём из исходников собственную систему. А поможет нам в этом Buildroot [2] — система сборки Linux-дистрибутивов.
Сначала вспомним, что Linux-система состоит из достаточно большого количества разных компонентов. Так как мы здесь говорим про embedded-платформы, выделим следующие компоненты:
Собрать все эти компоненты воедино мы можем двумя способами:
Некоторые из этих дистрибутивов поддерживают архитектуру ARMv7. Основное преимущество этого решения в том, что оно простое: эти бинарные дистрибутивы знакомы большинству пользователей Linux-систем, они имеют красивую и простую в использовании систему управления пакетами, все пакеты предварительно скомпилированы, поэтому нашей цели можно достичь очень быстро. Однако собранные таким образом системы обычно сложно кастомизировать (компоненты уже созданы, поэтому вы не можете легко изменить их конфигурацию в соответствии с вашими потребностями) и сложно оптимизировать (с точки зрения объёма занимаемой памяти или времени загрузки).
Они позволяют собрать Linux-систему непосредственно из исходного кода. А это означает, что систему будет легко оптимизировать и кастомизировать под свои нужды. Конечно же, этот способ намного сложнее, а на компиляцию кода придётся потратить немало процессорного времени.
Мы выбираем второй способ. В этой статье используем Buildroot, потому что с этой системой сборки достаточно просто разобраться и она подходит для embedded-платформ.
Buildroot — это набор make-файлов и скриптов, которые автоматизируют загрузку исходного кода различных компонентов, их извлечение, настройку, сборку и установку. В конечном итоге он генерирует образ системы, готовый к прошивке и обычно содержащий загрузчик, файл-образ ядра Linux и корневую файловую систему.
Важно отметить, что Buildroot не поставляется с исходными кодами Linux, с U-Boot или с другими компонентами. Он всего лишь содержит набор скриптов и инструкций, описывающих, какой исходный код загружать и какие настройки использовать при сборке.
Начнём с установки самой системы Buildroot, а потом перейдём к её настройке:
git clone git://git.buildroot.net/buildroot
cd buildroot
Обычно настройка Buildroot делается с помощью команды make menuconfig, которая позволяет указать необходимые опции для вашей системы. Но мы вместо этого используем свою конфигурацию, которую мы создали заранее — специально для STM32MP157-DK2. Она находится в моём репозитории [5].
git remote add tpetazzoni https://github.com/tpetazzoni/buildroot.git
git fetch tpetazzoni
git checkout -b stm32mp157-dk2 tpetazzoni/2019.02/stm32mp157-dk
А теперь дадим Buildroot’у команду использовать нашу конфигурацию.
make stm32mp157_dk_defconfig
Мы могли бы сразу приступить к сборке, так как эта конфигурация работает нормально. Но здесь я хочу показать, как можно изменить конфигурацию и ускорить сборку. Мы изменим всего один параметр. Для этого запустим утилиту menuconfig (она встроена в Buildroot). Если кто-то из вас уже настраивал ядро Linux, этот инструмент должен быть вам интуитивно понятен, поскольку это просто утилита для настройки.
make menuconfig
Если команда не сможет работать из-за отсутствия библиотеки ncurses, установите пакет libncurses-dev или ncurses-devel (точное название пакета будет зависеть от версии Linux ОС, на которой вы запускаете Buildroot). Библиотека ncurses предназначена для управления вводом-выводом на терминал.
Успешно выполнив menuconfig, перейдём в подменю Toolchain. По умолчанию в Toolchain Type выбрана опция . Нужно изменить её на , нажав ENTER.
Дело в том, что по умолчанию Buildroot использует собственный кросс-компилятор. Выбрав опцию , мы можем использовать более шустрый кросс-компилятор, специально заточенный под архитектуру ARMv7.

Выходим из menuconfig и сохраняем изменения. Теперь пришло время поработать с командой make. Я люблю всё логировать, поэтому она будет выглядеть вот так:
make 2>&1 | tee build.log
На этом этапе система сборки Buildroot проверит наличие всех необходимых пакетов. Если чего-то не обнаружит, то выполнение команды прервётся. Если это произойдёт, на сайте Buildroot посмотрите раздел System requirements > Mandatory packages [6] и установите все необходимые зависимости. После этого можно запускать команду заново.
На моей машине команда make работала 10 минут. После сборки появится набор каталогов и файлов (самое интересное лежит в output/images):
Запишем sdcard.img на карту microSD:
sudo dd if=output/images/sdcard.img of=/dev/mmcblk0 bs=1M conv=fdatasync status=progress
Не забудьте проверить, что в вашей системе карта microSD определяется как /dev/mmcblk0 (и на всякий случай предупреждаю: после того, вы запишете туда образ, вся информация на этой карточке будет затёрта)!
Подключите карту к микроконтроллеру.
Соедините USB-кабелем ваш компьютер и micro-USB разъём с надписью ST-LINK CN11 на плате. Ваша машина должна распознать устройство с именем /dev/ttyACM0, через которое вы сможете получить доступ к последовательному порту платы. Установите на свой компьютер и запустите программу для общения с последовательным портом. Лично мне очень нравится picocom [7]:
picocom -b 115200 /dev/ttyACM0
Он подходит для embedded-систем, так как занимает минимальный объём памяти (менее 20 КБ) и имеет подробную документацию.
Наконец, включите плату, воткнув кабель USB-C в разъём PWR_IN CN6. Затем на последовательный порт начнут приходить сообщения. Нам важно, что в конце появится приглашение залогиниться в системе Buildroot. Можно войти в систему с пользователем root, пароль вводить не нужно.

Рассмотрим основные этапы процесса загрузки, изучая сообщения, которые приходят на последовательный порт:
U-Boot SPL 2018.11-stm32mp-r2.1 (Apr 24 2019 — 10:37:17 +0200)
Это сообщение от загрузчика первой стадии: код, содержащимся в файле u-boot-spl.stm32 скомпилирован как часть загрузчика U-Boot. Его непосредственно загружает STM32MP157. Загрузчик первой стадии должен быть достаточно маленьким, чтобы поместиться во внутреннюю память STM32MP157.
U-Boot 2018.11-stm32mp-r2.1 (Apr 24 2019 — 10:37:17 +0200)
Это сообщение от загрузчика второй стадии, который был выгружен из внутренней памяти устройства во внешнюю память загрузчиком первой стадии. Загрузчик второй стадии — это файл u-boot.img, который также является частью загрузчика U-Boot.
Retrieving file: /boot/zImage
Retrieving file: /boot/stm32mp157c-dk2.dtb
Эти сообщения печатает загрузчик второй стадии: мы видим, что он загрузил образ ядра Linux (файл zImage) и блоб дерева устройств (файл stm32mp157c-dk2.dtb), описывающий нашу аппаратную платформу. Хорошо, U-Boot загрузил оба файла в память: теперь он готов к запуску ядра Linux.
Starting kernel ...
Это последнее сообщение U-Boot, после этого управление передаётся ядру.
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.19.26 (thomas@windsurf) (gcc version 8.2.1 20180802 (GNU Toolchain for the A-profile Architecture 8.2-2018.11 (arm-rel-8.26))) #1 SMP PREEMPT Wed Apr 24 10:38:00 CEST 2019
И сразу появляются первые сообщения ядра Linux, показывающие версию Linux и дату/время сборки. Далее идут другие, не слишком интересные сообщения… Нам нужно дождаться вот этого:
[ 3.248315] VFS: Mounted root (ext4 filesystem) readonly on device 179:4.
Это сообщение указывает на то, что ядро смонтировало корневую файловую систему. После этого ядро запустит первый пользовательский процесс. Поэтому следующие сообщения будут связаны с инициализацией пользовательских служб:
Starting syslogd: OK
[...]
Welcome to Buildroot
buildroot login:
И вот, наконец, появляется то самое сообщение от Buildroot с просьбой залогиниться.
После входа в систему вы получите доступ к командной оболочке Linux. Введя команду ps, можно посмотреть список процессов, команда ls/ покажет содержимое корневой файловой системы и так далее.
Также можно немного поиграться с платой — например, включить и выключить один из светодиодов:
echo 255 > /sys/class/leds/heartbeat/brightness
echo 0 > /sys/class/leds/heartbeat/brightness
В начале статьи мы говорили про настройку и оптимизацию конфигурации Buildroot. По идее, для этого нужно сначала изучить основы конфигурирования в этой системе. Поэтому вернёмся в прошлое к команде make menuconfig.
В меню Target options выбрана архитектура ARM Little Endian, а в Target Architecture Variant указан Cortex-A7. На этом процессоре как раз построен наш микроконтроллер.
В меню Build options используем все значения по умолчанию.
Как я писал выше, в меню Toolchain вместо кросс-компилятора по умолчанию был выбран пункт <External toolchain>.
В меню System configuration мы произвели следующие изменения:
В меню Kernel мы выбрали версию Linux и путь для конфигурации ядра:
В меню Target packages оставили значения по умолчанию: активен только пакет BusyBox. BusyBox [9] — очень популярный инструмент для embedded-платформ: это легковесная альтернатива Linux shell и другим инструментам командной строки (cp, mv, ls, vi, wget, tar). Для нашей системы нам хватит одного BusyBox!
В меню Filesystem images активировали ext2/3/4root filesystem и выбрали ext4. Эта файловая система отлично подходит для SD-карт.
Теперь в меню Bootloaders активируем U-Boot, для которого выполняем следующий набор действий:
Вся эта конфигурация сохраняется в простом текстовом файле configs/stm32mp157_dk_defconfig, который мы загружали изначально при запуске make stm32mp157_dk_defconfig.
Надеюсь, после изучения основ конфигурирования стало понятнее, как происходит сборка (для простоты я опустил несколько промежуточных шагов):
Теперь давайте посмотрим на файл board/stmicroelectronics/stm32mp157-dk/genimage.cfg, который советует утилите genimage, как нужно правильно генерировать образ для SD-карты:
image sdcard.img {
hdimage {
gpt = «true»
}
partition fsbl1 {
image = «u-boot-spl.stm32»
}
partition fsbl2 {
image = «u-boot-spl.stm32»
}
partition uboot {
image = «u-boot.img»
}
partition rootfs {
image = «rootfs.ext4»
partition-type = 0x83
bootable = «yes»
size = 256M
}
}
Какие конкретно указания даны в этом скрипте:
Последний раздел помечен как загрузочный (bootable). Это важно, потому что конфигурация U-Boot для аппаратной платформы STM32MP157 по умолчанию следует концепции U-Boot Generic Distro Concept [12]. При загрузке U-Boot будет искать раздел, помеченный как загрузочный, а затем внутри файловой системы, содержащейся в этом разделе, искать файл /boot/extlinux/extlinux.conf, чтобы узнать, как загрузить систему.
Файл extlinux.conf находится внутри оверлей-каталога нашей файловой системы (board/stmicroelectronics/stm32mp157-dk/overlay/boot/extlinux/extlinux.conf), в корневой файловой системе он будет определяться как /boot/extlinux/extlinux.conf и U-Boot легко найдёт его.
Вот что внутри этого файла:
label stm32mp15-buildroot
kernel /boot/zImage
devicetree /boot/stm32mp157c-dk2.dtb
append root=/dev/mmcblk0p4 rootwait
Таким образом мы говорим U-Boot, чтобы он загружал образ ядра из /boot/zImage, дерево устройств — из /boot/stm32mp157c-dk2.dtb. А строка root=/dev/mmcblk0p4 rootwait должна быть передана ядру Linux во время загрузки. Именно в этом выражении (root=/dev/mmcblk0p4) хранится информация о том, где находится корневая файловая система.
Итак, сформулируем этапы загрузки собранной Linux-системы на нашей аппаратной платформе — с учётом новых подробностей:
P.S. Вы можете найти исходный код для Buildroot, использованный в этой статье, вот здесь [13].
Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!
Автор: S_ILya
Источник [16]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/364974
Ссылки в тексте:
[1] STM32MP157-DK2: https://www.st.com/en/evaluation-tools/stm32mp157c-dk2.html
[2] Buildroot: http://www.buildroot.org
[3] Yocto: https://www.yoctoproject.org/
[4] OpenEmbedded: https://www.openembedded.org/
[5] репозитории: https://github.com/tpetazzoni/buildroot/
[6] System requirements > Mandatory packages: https://buildroot.org/downloads/manual/manual.html#requirement-mandatory
[7] picocom: https://github.com/npat-efault/picocom
[8] https://github.com/STMicroelectronics/linux/: https://github.com/STMicroelectronics/linux/
[9] BusyBox: https://busybox.net/
[10] https://github.com/STMicroelectronics/u-boot.git: https://github.com/STMicroelectronics/u-boot.git
[11] GPT partition table: https://en.wikipedia.org/wiki/GUID_Partition_Table
[12] U-Boot Generic Distro Concept: http://git.denx.de/?p=u-boot.git;a=blob;f=doc/README.distro
[13] вот здесь: https://github.com/tpetazzoni/buildroot/tree/2019.02/stm32mp157-dk-blog-1
[14] Маклауд: https://macloud.ru/?partner=4189mjxpzx
[15] Image: https://macloud.ru/?partner=4189mjxpzx&utm_source=habr&utm_medium=perevod&utm_campaign=grigri
[16] Источник: https://habr.com/ru/post/561248/?utm_source=habrahabr&utm_medium=rss&utm_campaign=561248
Нажмите здесь для печати.