STM32 з нуля без HAL: Buildroot, Luckfox і перший крок у embedded Linux. Частина 5
STM32 вивчено, що далі?
GPIO, UART, I2C, SPI, Timer все є, все працює, свій HAL написаний. Але якщо подивитись на вакансії embedded розробника там завжди є рядок: «досвід з Linux, Buildroot, Device Tree». І ось тут наш крутезний bare-metal HAL нікому не цікавий.
Місяць перший закрито:
- ARM для Ардуїнщиків, які прагнуть чогось більшого. Вступ
- STM32 з нуля без HAL: GPIO, регістри і переривання. Частина 1
- STM32 з нуля без HAL: UART від bit-bang до HAL. Частина 2
- STM32 без магії: переривання. Частина 3
- AVR vs STM32: як перейти і чому варто. Частина 4
Починаю другий місяць своєї епопеї і цей місяць це перехід в інший світ. STM32 більше не головний герой. Тепер він просто периферія. Мозком стає Luckfox Pico Pro — маленька плата з ARM Cortex-A7, 128MB RAM і повноцінним Linux всередині. Коштує ~$15.
Що будемо робити: зберемо власний Linux образ з нуля через Buildroot, навчимось додавати власні пакети (BR2_PACKAGE), розберемось з автозапуском через init.d. А в наступних частинах — U-Boot і перший міст STM32 ↔ Linux через UART.
◆ ЧАСТИНА 1: Середовище і збірка образу
Чиста машина — чистий старт
Всі дії виконуються на Ubuntu 22.04. Спеціально беру чисту машину — щоб читач міг повторити з нуля без «а у мене вже щось стояло».
Встановлення STM32 toolchain
sudo apt install -y gcc-arm-none-eabi stlink-tools minicom
Перевірка:
arm-none-eabi-gcc --version # 10.3.1 st-flash --version # v1.7.0 minicom --version # 2.8
Проблема яку не очікував: BRLTTY
Підключив CH340 адаптер — і /dev/ttyUSB0 не з’являється. lsusb плату бачить, але файлу немає.
sudo dmesg | tail -20
В логах знаходимо винуватця:
usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
BRLTTY — програма для шрифту Брайля. Вона перехоплює CH340 і відключає його одразу після підключення.
⚠ brltty є в базовій установці Ubuntu 22.04. Для розробки він абсолютно непотрібний.
sudo apt remove brltty
✓ Після видалення перепідключи CH340 — /dev/ttyUSB0 з’явиться одразу.
І традиційно — права доступу:
sudo usermod -aG dialout $USER newgrp dialout
Встановлення залежностей для Buildroot
sudo apt install -y git build-essential wget curl \ libncurses-dev libssl-dev python3 python3-pip \ bc cpio rsync unzip file bison flex \ device-tree-compiler golang-go \ gcc-multilib g++-multilib module-assistant expect \ gawk texinfo fakeroot cmake gperf autoconf \ libncurses5-dev pkg-config python-is-python3
⚠ golang-go потрібен на хості для збірки Go пакетів в Buildroot. Без нього збірка впаде з ’go: command not found’.
Клонування Luckfox SDK
git clone
github.com/...kfoxTECH/luckfox-pico.git
cd luckfox-pico
SDK важить ~1GB. Встановлюємо cross-compilation toolchain:
cd tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/ source env_install_toolchain.sh arm-rockchip830-linux-uclibcgnueabihf-gcc --version # arm-rockchip830-linux-uclibcgnueabihf-gcc (crosstool-NG 1.24.0) 8.3.0
⚠ Скрипт може видати ’sed: cannot read ~/.bash_profile’. Не помилка — toolchain налаштовується.
Налаштування робочої змінної BUILDROOT
Більшість команд з Buildroot потребують довгого шляху до директорії. Щоб не вводити його кожного разу — встановлюємо змінну:
export BUILDROOT=~/luckfox-pico/sysdrv/source/buildroot/buildroot-2023.02.6
Але ця змінна зникає при кожному закритті терміналу. Додаємо в ~/.bashrc щоб встановлювалась автоматично:
echo 'export BUILDROOT=~/luckfox-pico/sysdrv/source/buildroot/buildroot-2023.02.6' >> ~/.bashrc source ~/.bashrc
Перевірка:
echo $BUILDROOT # /home/alex/luckfox-pico/sysdrv/source/buildroot/buildroot-2023.02.6 ls $BUILDROOT/package/ | head -5
⚠ Якщо $BUILDROOT порожній — команди типу ’cat $BUILDROOT/package/Config.in’ виконаються з помилкою ’No such file’. Завжди перевіряй echo $BUILDROOT на початку сесії.
Вибір конфігурації і збірка
cd ~/luckfox-pico ./build.sh lunch
З меню вибираємо для Luckfox Pico Pro (Flash, SPI NAND):
[4] RV1106_Luckfox_Pico_Pro_Max [1] SPI_NAND [0] Buildroot ./build.sh all
Перша збірка —
Прошивка через upgrade_tool
sudo cp upgrade_tool /usr/local/bin && sudo chmod +x /usr/local/bin/upgrade_tool
Maskrom режим: затисни BOOT → підключи USB → відпусти BOOT.
lsusb | grep -i rock # має показати Fuzhou Rockchip sudo upgrade_tool uf ~/luckfox-pico/output/image/update.img
⚠ Завжди вказуй повний шлях до образу — щоб не переплутати з офіційним образом з сайту.
Перевірка: це наш образ?
ssh -o PubkeyAuthentication=no [email protected] uname -a # Linux luckfox 5.10.160 #1 Wed Apr 8 16:52:35 EEST 2026 armv7l GNU/Linux
Дата збірки сьогоднішня. Значить це мій образ.
Пакети, BR2_PACKAGE і автозапуск
Developer Image: toolbox для embedded розробки
Базовий образ мінімальний. Для розробки потрібно більше. Buildroot дозволяє додати будь-який пакет через menuconfig.

menuconfig — вибір пакетів
./build.sh buildrootconfig

В меню Target packages додаємо:
- Networking: nmap, tcpdump, iperf3
- Debugging: strace, lsof, gdbserver
- System tools: htop
- Interpreter languages: python3
- Text editors: nano


Фейл з mc: uclibc vs glibc
Спробував додати Midnight Commander (mc). Збірка впала:
tty-ncurses.c: undefined reference to 'mvin_wchnstr'
Luckfox використовує uclibc — легша бібліотека без повної підтримки wide characters. mc потребує саме їх. В embedded Linux не все з Ubuntu можна просто скомпілювати.
⚠ uclibc vs glibc — перший урок реального embedded. Buildroot SDK визначає що можна використовувати.
BR2_PACKAGE: власний Go сервер
Стандартні пакети — це галочки в menuconfig. Для власного коду є BR2_PACKAGE — механізм інтеграції в систему збірки Buildroot.
Структура пакету:
package/go-dashboard/ ├── Config.in ← опис для menuconfig ├── go-dashboard.mk ← інструкції збірки ├── S98go-dashboard ← init.d автозапуск ├── S99staticip ← статичний IP └── src/ ├── main.go └── go.mod
Config.in — важливо: таби не пробіли
config BR2_PACKAGE_GO_DASHBOARD bool "go-dashboard" help HTTP dashboard для Luckfox. JSON API на порті 8080.
⚠ Buildroot Config.in вимагає таби. Пробіли — пакет невидимий в menuconfig пошуку. Перевір: cat -A Config.in → має бути ^I на початку рядків.
go-dashboard.mk
GO_DASHBOARD_VERSION = 1.0.0 GO_DASHBOARD_SITE = $(TOPDIR)/package/go-dashboard/src GO_DASHBOARD_SITE_METHOD = local define GO_DASHBOARD_BUILD_CMDS cd $(@D) && \ GOOS=linux GOARCH=arm GOARM=7 \ CGO_ENABLED=0 \ go build -o go-dashboard main.go endef define GO_DASHBOARD_INSTALL_TARGET_CMDS $(INSTALL) -D -m 0755 $(@D)/go-dashboard $(TARGET_DIR)/usr/bin/go-dashboard endef define GO_DASHBOARD_INSTALL_INIT_SYSV $(INSTALL) -D -m 0755 $(GO_DASHBOARD_PKGDIR)/S98go-dashboard \ $(TARGET_DIR)/etc/init.d/S98go-dashboard $(INSTALL) -D -m 0755 $(GO_DASHBOARD_PKGDIR)/S99staticip \ $(TARGET_DIR)/etc/init.d/S99staticip endef $(eval $(generic-package))
⚠ $(TOPDIR) — правильний шлях для цього SDK. $(BR2_EXTERNAL_LUCKFOX_PATH) не працює.
Підключення до Buildroot
grep -n "vim/Config.in" $BUILDROOT/package/Config.in # → 2748 sed -i '2748a\\tsource "package/go-dashboard/Config.in"' \ $BUILDROOT/package/Config.in
⚠ Якщо зламав Config.in: wget -O $BUILDROOT/package/Config.in \ github.com/...23.02.6/package/Config.in
Автозапуск: init.d і підводні камені
init.d скрипти в Buildroot виконуються при старті системи. Число в назві визначає порядок — S98 запускається перед S99.
S98go-dashboard — запуск Go сервера:
#!/bin/sh case "$1" in start) nohup /usr/bin/go-dashboard > /var/log/go-dashboard.log 2>&1 & ;; stop) killall go-dashboard 2>/dev/null ;; esac
⚠ start-stop-daemon — не використовуй для Go процесів на Buildroot Luckfox. Вішає систему при boot. Тільки nohup ... & працює надійно.
S99staticip — статичний IP після DHCP:
#!/bin/sh case $1 in start) sleep 5 ifconfig eth0 192.168.1.125 netmask 255.255.255.0 route del default 2>/dev/null route add default gw 192.168.1.1 ;; stop) ;; esac
⚠ sleep 5 — чекаємо поки udhcpc завершить роботу. /etc/network/interfaces не допомагає — udhcpc стартує незалежно і перебиває статичний IP. S99staticip з sleep 5 — єдиний надійний спосіб на Buildroot Luckfox.
ubifs: чому старі файли залишаються після прошивки
Виявив цікаву особливість: після прошивки нового образу старі файли в /etc/init.d/ залишались навіть якщо їх не було в новому образі.
Причина: ubifs (UBI File System) на SPI NAND не перезаписує файли які не змінились. upgrade_tool оновлює партиції інкрементально. Файл вже є у флеші — і залишається там навіть якщо в новому образі його немає.
⚠ Рішення: upgrade_tool ef (erase and flash) стирає флеш повністю перед прошивкою. Або просто видалити файл вручну на платі перед тестуванням нової версії.
Результат: перевірка після прошивки
ssh -o PubkeyAuthentication=no [email protected] curl
192.168.1.125:8080/api/stats
{
"hostname": "luckfox",
"arch": "arm",
"uptime_seconds": 161.62,
"go_version": "go1.18.1",
"time": "2026-04-28 16:33:18"
}
✓ Час правильний — NTP синхронізувався через Ethernet. Через USB RNDIS NTP не працює стабільно.
RNDIS vs Ethernet: важливий висновок
USB RNDIS з’єднання (172.32.x.x) — нестабільне для SSH сесій. Термінал підвисає через ~20 секунд без активності. Ctrl+C/Z не допомагають.
Ethernet через роутер (192.168.1.x) — стабільне. Підключай плату кабелем до роутера для нормальної роботи.
⚠ RNDIS підходить тільки для першого підключення і прошивки. Для розробки завжди використовуй Ethernet.
Підсумок
За два тижні пройшли шлях від чистої Ubuntu до власного Linux образу з Go HTTP сервером і автозапуском:
- Встановили STM32 і Buildroot оточення на чистій машині
- Вирішили проблему BRLTTY — типову для Ubuntu 22.04
- Зібрали образ для Luckfox Pico Pro з нуля через build.sh all
- Прошили через upgrade_tool в Maskrom режимі
- Зібрали Developer Image: htop, nmap, python3, strace, tcpdump, iperf3
- Познайомились з uclibc — не все з Ubuntu компілюється в embedded
- Написали BR2_PACKAGE і зібрали Go сервер як частину образу
- Налаштували автозапуск через init.d і статичний IP
- Розібрались з ubifs — чому старі файли залишаються після прошивки
Далі планую: U-Boot і boot sequence — розберемось як система завантажується від першої інструкції до нашого шела. І головне — з’єднаємо STM32 і Luckfox через UART.
17 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів... зберемо власний Linux образ з нуля через Buildroot, навчимось додавати власні пакети (BR2_PACKAGE), розберемось з автозапуском через init.d. ...
Це все, що потрібно було — одна команда «git clone git.buildroot.net/buildroot»
Потім зберіть все безпосередньо в buildroot. До речі, buildroot не потребує залежностей: він самодостатній — він сам може зібрати toolchain і все, що йому потрібно. Також Ви можете обирати безпосередньо в buildroot uclibc або glibc, яке Linux ядро, які пакети.
Дякую за доповнення, щоб читачі бачили ширшу картину. Для vanilla заліза достатньо. Але оскільки RV1106 має закриті бінарники DDR init і патчі ядра яких немає в upstream Buildroot. Перевірено особисто без вендорського SDK плата просто не стартує.
Зрозуміло. Але навіщо взагалі розглядати такі плати, якщо ринок переповнений відкритими архітектурами?
Я мав на увазі, що якщо збираєтеся вивчати вбудовані системи, було б корисніше обрати щось ванільне
1 «мій крокодил, як хочу так і міряю»
2 тому що це саме дешевше
3 тому що це було би дуже просто і Romano Paolo написав би: «ШІ би ліпше накарлякало б»
4 «ми не шукаєм легких шляхів»
Супер, відчувається гостре сатиричне перо майстра 🔥🔥🔥💯
Досі не можу пробачити корпоратам, що вони зіпсували прекрасні віндовс інструменти і свої компілятори в угоду gcc і пердолінга в терміналі. Ембед і так важкий, а тут ще зверху напихують додаткову когнітивну нагрузку з лінуксячою інфраструктурою, яка нікому не потрібна.
Думав віндовс то в ігри грати і офіси всякі, ну ще C# . За надцять років розробки віндовс зустрічав тільки 1С
MigWin/CygWin чи Arduino IDE? Notepad++?
Присрате POSIX поверх вінди це була до речі перша ластівка деградації. Бо чомусь хайтек можуть написати компілятор для своїх МК, який не потребує гнутого слопа і взагалі посікса, як явища. А потім комусь прийшло в голову, що писати компілятори не обов’язково, можна просто взяти самий херовий в саіті gcc і продавать його лохам за гроші, ще й через прослойку. Але зараз і хайтек замість розробки нормального тулінга перейшов на gcc і llvm
Людство вже давно на yocto перейшло, який білдрут
Друже ви мабуть довго думали і зважили усі за та проти. Років надцять тому Харкнув би у відповідь, щось схоже по духу та не сьогодні. Я очікував таких розумників в коментарях, бо це було очікувано.
Buildroot і Yocto — це різні інструменти для різних задач. Yocto дає максимальну гнучкість і масштабується на продакшн з десятками пакетів, CI/CD, і командною розробкою. Buildroot дає мінімальну систему швидко і з меншим порогом входу — ідеально для навчання, прототипів і маленьких SoC типу RV1106 де Luckfox SDK побудований саме на Buildroot.
До речі, Rockchip, Allwinner, багато китайських SoC вендорів — їхні офіційні SDK йдуть з Buildroot, не з Yocto. Тому для самих маленьких поясню — це не «відсталість», а зважений і прагматичний вибір під задачу.
У серії буде і складніше — kernel modules, драйвери. Buildroot тут як фундамент, а не як останнє слово
Далеко не все людство перейшло, всякі Ілони Маски зокрема: github.com/...eslamotors/buildroot/tags
при «клятому совку» вживали «все прогресивне людство»
Велика повага за те, що описуєте з чистої системами, нотатками про ймовірні проблеми, як перевірити що все ок. І особливо за враховування нової сесії в терміналі і скидання env змінної) Впевнений комусь зекономить час.
Бо статті цінні не лише за success path, але й поширення інформації про набиті шишки.
Дякую, бо якщо чесно побачивши сповіщення про новий коментар напружився. Подумки — ну знов комусь не вгодив, бо в те не так і то не це. Завдяки таким поодиноким коментарям, як ваші і існує ця серія. Не було б то давно покинув би це графоманство
Свідки Кейла/ІАРа відпали на 4 ступені польота
Супер, як завжди ємко 😂😂😂🔥❤️