STM32 з нуля без HAL: Buildroot, Luckfox і перший крок у embedded Linux. Частина 5

STM32 вивчено, що далі?

GPIO, UART, I2C, SPI, Timer все є, все працює, свій HAL написаний. Але якщо подивитись на вакансії embedded розробника там завжди є рядок: «досвід з Linux, Buildroot, Device Tree». І ось тут наш крутезний bare-metal HAL нікому не цікавий.

Місяць перший закрито:

Починаю другий місяць своєї епопеї і цей місяць це перехід в інший світ. 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

Перша збірка — 20-40 хвилин. Образ буде тут: output/image/update.img

Прошивка через 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.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось15
До обраногоВ обраному6
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

... зберемо власний 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 «ми не шукаєм легких шляхів»

Супер, відчувається гостре сатиричне перо майстра 🔥🔥🔥💯

Але якщо подивитись на вакансії embedded розробника там завжди є рядок: «досвід з Linux, Buildroot, Device Tree».

Досі не можу пробачити корпоратам, що вони зіпсували прекрасні віндовс інструменти і свої компілятори в угоду 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 ступені польота

Супер, як завжди ємко 😂😂😂🔥❤️

Підписатись на коментарі