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
|
1 |
sudo apt install -y gcc-arm-none-eabi stlink-tools minicom |
Перевірка:
|
1 2 3 |
arm-none-eabi-gcc --version # 10.3.1 st-flash --version # v1.7.0 minicom --version # 2.8 |
Проблема яку не очікував: BRLTTY
Підключив CH340 адаптер — і /dev/ttyUSB0 не з’являється. lsusb плату бачить, але файлу немає.
|
1 |
sudo dmesg | tail -20 |
В логах знаходимо винуватця:
|
1 |
usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1 |
BRLTTY — програма для шрифту Брайля. Вона перехоплює CH340 і відключає його одразу після підключення.
⚠ brltty є в базовій установці Ubuntu 22.04. Для розробки він абсолютно непотрібний.
|
1 |
sudo apt remove brltty |
✓ Після видалення перепідключи CH340 — /dev/ttyUSB0 з’явиться одразу.
І традиційно — права доступу:
|
1 2 |
sudo usermod -aG dialout $USER newgrp dialout |
Встановлення залежностей для Buildroot
|
1 2 3 4 5 6 7 |
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
|
1 2 |
git clone https://github.com/LuckfoxTECH/luckfox-pico.git cd luckfox-pico |
SDK важить ~1GB. Встановлюємо cross-compilation toolchain:
|
1 2 3 4 |
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 на початку кожної сесії — вона не зберігається між терміналами. Додай в ~/.bashrc: export BUILDROOT=~/luckfox-pico/sysdrv/source/buildroot/buildroot-2023.02.6
Вибір конфігурації і збірка
|
1 2 |
cd ~/luckfox-pico ./build.sh lunch |
З меню вибираємо для Luckfox Pico Pro (Flash, SPI NAND):
|
1 2 3 4 5 |
[4] RV1106_Luckfox_Pico_Pro_Max [1] SPI_NAND [0] Buildroot ./build.sh all |
Перша збірка — 20-40 хвилин. Образ буде тут: output/image/update.img
Прошивка через upgrade_tool
|
1 |
sudo cp upgrade_tool /usr/local/bin && sudo chmod +x /usr/local/bin/upgrade_tool |
Maskrom режим: затисни BOOT → підключи USB → відпусти BOOT.
|
1 2 |
lsusb | grep -i rock # має показати Fuzhou Rockchip sudo upgrade_tool uf ~/luckfox-pico/output/image/update.img |
⚠ Завжди вказуй повний шлях до образу — щоб не переплутати з офіційним образом з сайту.
Перевірка: це наш образ?
|
1 2 3 |
ssh -o PubkeyAuthentication=no root@172.32.0.93 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 — вибір пакетів
|
1 |
./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). Збірка впала:
|
1 |
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.
Структура пакету:
|
1 2 3 4 5 6 7 8 9 |
package/go-dashboard/ ├── Config.in ← опис для menuconfig ├── go-dashboard.mk ← інструкції збірки ├── S98go-dashboard ← init.d автозапуск ├── S99staticip ← статичний IP └── src/ ├── main.go └── go.mod |
Config.in — важливо: таби не пробіли
|
1 2 3 4 5 6 7 |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
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
|
1 2 3 4 |
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 \ https://github.com/buildroot/buildroot/raw/2023.02.6/package/Config.in
Автозапуск: init.d і підводні камені
init.d скрипти в Buildroot виконуються при старті системи. Число в назві визначає порядок — S98 запускається перед S99.
S98go-dashboard — запуск Go сервера:
|
1 2 3 4 5 6 7 8 9 |
#!/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:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/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) стирає флеш повністю перед прошивкою. Або просто видалити файл вручну на платі перед тестуванням нової версії.
Результат: перевірка після прошивки
|
1 2 3 4 5 6 7 8 9 10 |
ssh -o PubkeyAuthentication=no root@192.168.1.125 curl http://192.168.1.125:8080/api/stats { "hostname": "luckfox", "arch": "arm", "uptime_seconds": 161.62, "go_version": "go1.18.1", "time": "2026-05-02 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.