STM32 з нуля без HAL: Device Tree, три UART і Python на борту. Частина 7

💡 Усі статті, обговорення, новини про Python — в одному місці. Приєднуйтесь до Python спільноти!

Серія «STM32 з нуля без HAL» • Місяць 3 • Тижні 1-2

Luckfox Pico Pro як мозок, STM32 як м’язи — перша справжня embedded Linux архітектура

Про що ця стаття

Привіт! Ми продовжуємо серію про STM32 без HAL. В минулих статтях ми розібрали Buildroot, зібрали свій Linux-образ, навчились додавати пакети і розібрали U-Boot. Тепер час для наступного кроку — Device Tree.

Років 10 тому я робив домашню автоматизацію на Arduino Pro Mini з W5500 Ethernet шилдом. Паяв модулі, підключав RJ45, писав скетчі. Щоб мати Ethernet на мікроконтролері — потрібен був окремий чіп, окрема плата, окремий стек бібліотек (може колись ще розповім про це).

А тепер Luckfox Pico Pro за $15 має вбудований Ethernet, повноцінний Linux з Python, SSH, веб-сервером, і ще NPU для нейромереж зверху. На мою думку, еволюція — це шлях від пайки Ethernet модуля до вбудованого мережевого стеку embedded розробки. І ця серія статей — спроба цю еволюцію пройти і задокументувати.

Розум. Код. Характер. З таким девізом ми йдемо далі.

Device Tree — це те, без чого не працює жоден embedded Linux пристрій на ARM. Але коли я вперше відкрив DTS файл, то побачив купу рядків з hex-адресами і подумав: «мда, з розбігу не заскочити», але ж на STM32 я писав ті ж самі hex-адреси руками.

В цій статті ми:

• Розберемо DTS файл Luckfox Pico Pro рядок за рядком
• Порівняємо кожну DTS властивість з тим, що ми робили на STM32 bare-metal
• Змінимо один рядок в DTS — і отримаємо новий serial порт
• Підключимо STM32 до Luckfox через UART
• Напишемо Python скрипт, який керує STM32 з Linux
• І трохи зазирнемо в NPU — що це за звір на борту нашої плати

Частина 1. Device Tree — що це і навіщо

Проблема: Linux не знає що на платі

На STM32 ми писали прямо в регістри:

#define USART1_BASE 0x40013800
#define USART1_CR1 (*(volatile uint32_t *)(USART1_BASE + 0x0C))
RCC_APB2ENR |= (1 << 14); // тактування USART1

Ми знали адресу кожного регістра, бо працювали з одним конкретним чіпом. Але Linux — універсальне ядро. Воно працює на тисячах різних плат. Звідки йому знати, що на нашому Luckfox UART2 сидить за адресою 0xff4c0000, а не 0×40013800 як на STM32?

Відповідь проста — це Device Tree, файл, який описує все залізо на платі: які є контролери, за якими адресами, які переривання використовують, які піни зайняті. Ядро читає цей файл при завантаженні і знає з чим працювати.

Структура файлів: як матрьошка

Відкриваємо DTS нашої плати і бачимо три include:

// rv1106g-luckfox-pico-pro-max.dts
#include "rv1106.dtsi" // SoC: всі UART, SPI, I2C
#include "rv1106-evb.dtsi" // базова EVB конфігурація
#include "rv1106-luckfox-pico-pro-max-ipc.dtsi" // специфіка Luckfox

Це як в нашому HAL: rv1106.dtsi — це hal.h де описані всі можливості чіпа, а DTS плати — це main.c де ми обираємо що використовувати.

Root node: хто ми такі

/ {
model = "Luckfox Pico Pro Max";
compatible = "rockchip,rv1103g-38x38-ipc-v10", "rockchip,rv1106g3";
};

model — людська назва плати. compatible — список від конкретного до загального. Ядро спочатку шукає драйвер для rv1103g-38×38-ipc-v10, не знайшло — пробує rv1106g3. Як fallback.

UART2 в DTS vs USART1 на STM32

Ось опис UART2 в базовому rv1106.dtsi:

uart2: serial@ff4c0000 {
    compatible = "rockchip,rv1106-uart", "snps,dw-apb-uart";
    reg = <0xff4c0000 0x100>;
    interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
    clock-frequency = <24000000>;
    clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
    pinctrl-0 = <&uart2m1_xfer>;
    status = "disabled";
};

Тепер порівняємо з тим, що ми робили на STM32 в нашому hal_uart.c:

reg = <0xff4c0000 0×100> — базова адреса і розмір блоку регістрів. На STM32 ми писали #define USART1_BASE 0×40013800. Та сама ідея, тільки в DTS ядро зробить ioremap() замість прямого доступу.

interrupts = <GIC_SPI 27 ...> — UART2 використовує переривання 27 на GIC. На STM32 ми знали що USART1 = IRQ37 і писали NVIC_ISER1 |= (1 << 5). Тут замість NVIC — GIC (бо Cortex-A7 замість Cortex-M3), але ідея та сама.

clock-frequency = <24000000> — вхідна частота 24MHz. У нас на STM32 було 8000000UL / baud для розрахунку BRR. Тут ядро зробить аналогічний розрахунок, тільки з 24MHz.

clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2> — два клоки від CRU. Як ми робили RCC_APB2ENR |= (1 << 14) для ввімкнення тактування USART1. Ядро зробить це автоматично через clock framework.

pinctrl-0 = <&uart2m1_xfer> — мультиплексор пінів. Як ми ставили PA9 в alternate function (0xB) для TX. Тут ядро зробить це через pinctrl підсистему.

status = «disabled» — за замовчуванням вимкнений. В базовому DTSI ВСІ контролери disabled. Плата вмикає тільки те що реально підключено. Як на STM32 — периферія є в чіпі, але без тактування не працює.

Бачите 0xff4c0000? Ця ж адреса з’являється в bootargs ядра: earlycon=uart8250,mmio32,0xff4c0000. DTS описує адресу, bootargs використовує її для ранньої консолі.

Pinctrl: як DTS описує фізичні піни

uart2m1_xfer: uart2m1-xfer {
   rockchip,pins =
      <1 RK_PB3 2 &pcfg_pull_up>, // UART2 RX
      <1 RK_PB2 2 &pcfg_pull_up>; // UART2 TX
};

Формат: <bank pin function pull_config>. Bank 1, Port B pin 2, alternate function 2 це UART2 TX, підтяжка вгору. Порівняйте з нашим STM32 кодом:

// STM32: PA9 = TX = Alternate Function Push-Pull
gpio_init(PIN_PA9, 0xB);

Та ж ідея — ми ставили PA9 в alternate function для UART TX. Тут DTS каже: «GPIO1_B2 — це alternate function 2, що означає UART2 TX». Тільки на STM32 ми знали це з даташиту і прописували вручну, а тут ядро читає DTS і робить все автоматично.

M0, M1, M2 — просто варіанти пінів

M1 в назві — це варіант розводки пінів (mux variant). RV1106 дозволяє вивести один і той же UART на різні фізичні піни. На STM32F103 аналог — AFIO_MAPR remap (наприклад USART1 можна перекинути з PA9/PA10 на PB6/PB7).

Але є важливий нюанс: ви не можете довільно призначити будь-який пін на будь-яку функцію. Варіанти M0/M1/M2 — це фіксовані комбінації, зашиті в кремнії чіпа. Можна обрати тільки з того, що виробник передбачив.

Ми це з’ясували на практиці. На нашій платі конектор SIM800L потрапляє на піни 11-12. Пін 11 — це UART0_TX_M1 (є TX). А пін 12 — SPI0_CS0_M0 (це вже зовсім інша периферія, не RX). Виникло питання: а може є варіант M0 або M2 де UART0_RX потрапить на потрібний пін?

Перевіряємо всі варіанти в pinctrl:

$ grep -A8 "uart0m" rv1106-pinctrl.dtsi

uart0m0_xfer: TX = GPIO0_A1, RX = GPIO0_A0 // не на гребінці
uart0m1_xfer: TX = GPIO2_B1, RX = GPIO2_B0 // TX на піні 11,
// але RX не виведений!
uart0m2_xfer: TX = GPIO4_A1, RX = GPIO4_A0 // не на гребінці

Жоден варіант не призначає UART0_RX на пін 12. TX є, а RX фізично не доступний поруч. Software UART (bit-bang RX) на Linux — це не варіант: планувальник може в будь-який момент забрати CPU на інший процес, і ми втратимо біти. На bare-metal STM32 можна крутитись в tight loop і ловити кожен біт з мікросекундною точністю, але Linux — не RTOS.

Висновок: коли обираєте плату або проектуєте свою PCB для Luckfox — спочатку перевірте pinctrl в DTS. Варіанти M0/M1/M2 фіксовані, і якщо потрібний пін не виведений на гребінку — ніякий DTS overlay не допоможе.

Для SIM800L рішення просте — підключаємо через інший конектор (U3 → UART1), де TX і RX поруч. А конектор SIM800L використовуємо для чогось що потребує тільки TX.

Консоль: FIQ Debugger

Цікава знахідка: ми шукали де вмикається UART2 для консолі і не знайшли звичайного status = «okay». Виявилось, Rockchip використовує FIQ Debugger:

fiq-debugger {
    compatible = "rockchip,fiq-debugger";
    status = "okay";
};

FIQ (Fast Interrupt Request) — переривання з вищим пріоритетом ніж звичайний IRQ. Rockchip перехоплює UART2 через FIQ, щоб консоль працювала навіть коли ядро зависло. Тому консоль — це ttyFIQ0, а не ttyS2.

Це означає що UART2 зайнятий. Для зв’язку зі STM32 потрібно використовувати інший UART — і ось тут починається найцікавіше.

Частина 2. Лише один рядок в DTS

Знаходимо вільні UART

В DTS нашої плати бачимо:

&uart3 { status = "disabled"; };
&uart4 { status = "disabled"; };

Обидва вимкнені. Дивимось на pinout Luckfox — UART3 виведений на піни 19-20 (конектор U4 на нашій платі), UART4 — на піни 6-7 (гребінка U11). Ідеально.

Що робимо? Змінюємо один рядок:

/* UART3_M1 */
&uart3 {
   status = "okay";
};

Pinctrl вже прописаний в базовому rv1106.dtsi (pinctrl-0 = <&uart3m1_xfer>), тому більше нічого додавати не треба.

Збираємо і прошиваємо

# Збираємо ядро (включає компіляцію DTS)
cd ~/luckfox-pico
./build.sh kernel

# Копіюємо boot.img на плату
scp -o PubkeyAuthentication=no output/image/boot.img \
[email protected]:/tmp/

# Прошиваємо тільки boot розділ (mtd3) і перезавантажуємо
ssh -o PubkeyAuthentication=no [email protected] \
"flashcp /tmp/boot.img /dev/mtd3 && reboot"

Чому flashcp і mtd3? На Luckfox flash пам’ять поділена на MTD розділи. MTD (Memory Technology Devices) — це підсистема Linux для роботи з flash напряму. Boot розділ (ядро + DTB) сидить на mtd3. flashcp стирає блок і записує нове ядро. Це як st-flash write firmware.bin 0×08000000 на STM32 — та ж ідея, тільки через Linux підсистему.

Повна розмітка MTD на Luckfox:

mtd0 = env (256K) ← U-Boot змінні
mtd1 = idblock (256K) ← Rockchip ID block
mtd2 = uboot (512K) ← U-Boot
mtd3 = boot (4M) ← ядро + DTB ☆ ми прошиваємо сюди
mtd4 = oem (30M) ← OEM дані
mtd5 = userdata (10M) ← дані
mtd6 = rootfs (210M) ← файлова система (UBIFS)

Перевіряємо результат

Після ребуту — один SSH запит і бачимо:

$ cat /proc/device-tree/serial@ff4d0000/status
okay

$ ls /dev/ttyS*
/dev/ttyS3

Один рядок в DTS — і з’явився /dev/ttyS3. Ядро побачило status = «okay», завантажило драйвер snps,dw-apb-uart, зробило ioremap(0xff4d0000), налаштувало pinctrl, і створило пристрій. Все те, що ми робили на STM32 руками в десятки рядків коду, тут одна декларативна властивість.

Вмикаємо всі три UART

Раз вже розібрались — вмикаємо одразу три UART для максимальної гнучкості:

/* UART1_M1 */
&uart1 { status = "okay"; };

/* UART3_M1 */
&uart3 { status = "okay"; };

/* UART4_M1 */
&uart4 { status = "okay"; };

Перезбираємо, прошиваємо, і тепер:

$ ls /dev/ttyS*
/dev/ttyS1 /dev/ttyS3 /dev/ttyS4

Три serial порти для периферії. Підключай три STM32, або STM32 + SIM800L + щось ще.

Частина 3. Плата Pi Pico Sim800 — як макетка для Luckfox

У мене є кастомна плата Pi Pico Sim800 v3.1 — розроблена під Raspberry Pi Pico для IoT проекту з SIM800L і реле (про цей проект — окрема стаття на DOU). Luckfox Pico Pro має такий же форм-фактор і гребінку 2×20, тому вставляється замість Pi Pico.

Але є нюанс — піни мають різні функції. На Pi Pico пін 19 — це GP14 (I2C SDA), а на Luckfox — це UART3_TX. Тому для зручності я зробив повний маппінг цих двох плат може комусь теж буде корисно.

Raspberry Pi Pi Pico

LuckFox pico

Що реально розпаяно на платі

Плата — це по суті breakout board з конекторами. Єдине, що розпаяно постійно — зсувний регістр SN74HC595N на пінах 4, 5, 9 (DATA, LATCH, CLOCK), з якого виведено 8 пінів, які задумані під керувнням реле. Решта — це знімні конектори для модулів: SIM800L, BMP180, PIR.

Маппінг конекторів

Ключова таблиця — які конектори плати відповідають яким UART на Luckfox:

U4 (BMP180 #1), піни 19-20 → UART3 — основний для STM32

U3 (BMP180 #2), піни 21-22 → UART1 — другий STM32 або SIM800L

U11 (гребінка), піни 6-7 → UART4 — додаткова периферія

Піни 1-2 → UART2 (FIQ debugger) — зайнятий консоллю

Крім UART, на гребінці U11 є повний SPI0 (піни 14-17) — для дисплеїв, flash, тощо.

SIM800L конектор — половинка UART

Конектор SIM800L (піни 11-12) потрапляє на UART0_TX і SPI0_CS0 на Luckfox. TX є, а RX на сусідньому піні немає. Software UART на Linux, як на Ардуїно робити ризиковано бо планувальник може забрати CPU і буде втрачено біти. Тому у моєму випадку для SIM800L краще використати інший конектор — наприклад U3 (UART1).

Зсувний регістр — GPIO bit-bangSN74HC595N підключений до пінів 4, 5, 9. На Luckfox ці піни не збігаються з SPI контролером, тому апаратний SPI не вийде. Але GPIO bit-bang працює чудово — для 8 реле швидкості вистачить з головою.

Думаю це чудова тема для окремої статті — як керувати зсувним регістром з Linux через sysfs.

Частина 4. Підключаємо STM32 — перший міст

Коли паяєш дорожки на платі і перевіряєш пін за піном, потрібна максимальна концентрація. Ніяких паразитних сигналів, тільки чистий UART.

Фізичне підключення

Luckfox U4 pin 19 (UART3_TX) → STM32 PA10 (USART1_RX)
Luckfox U4 pin 20 (UART3_RX) ← STM32 PA9 (USART1_TX)
GND ↔ GND

Обидві плати 3.3V — конвертер рівнів не потрібен. Ті самі три дроти, що раніше йшли до CH340 USB-TTL адаптера, тепер йдуть прямо в Luckfox.

STM32 сторона — нічого не міняємо

На Blue Pill працює той самий код з нашого HAL — uart_init(9600), uart_gets(), uart_puts(). STM32 не знає і не повинен знати, що на іншому кінці замість minicom тепер Linux. Для нього це просто UART.

// main.c на STM32 — без змін з попередніх статей
hal_init();
uart_init(9600);
gpio_init(PIN_PC13, OUTPUT);

while (1) {
    uart_gets(buf, 16);
    if (buf[0] == 'o' && buf[1] == 'n') {
        gpio_write(PIN_PC13, LOW);
        uart_puts("LED on\r\n");
    }
}

Linux сторона — перший тест

З Luckfox по SSH:

# Налаштувати raw режим
stty -F /dev/ttyS3 9600 raw -echo

# Відправити команду і побачити відповідь
echo -ne "on\r" > /dev/ttyS3
cat /dev/ttyS3

LED на Blue Pill загорівся, в терміналі з’явилось «LED on». Luckfox керує STM32. Мозок командує м’язами.

Частина 5. Python контролер — робимо по-людськи

echo в /dev/ttyS3 працює, але це не серйозно. Пишемо нормальний Python скрипт:

#!/usr/bin/env python3
import serial, sys, time

def send_command(ser, cmd):
    ser.write((cmd + "\r").encode())
    time.sleep(0.1)
    response = ""
    while ser.in_waiting:
        response += ser.read(ser.in_waiting).decode(errors="ignore")
        time.sleep(0.05)
    return response.strip()

ser = serial.Serial("/dev/ttyS3", 9600, timeout=2)

# Одна команда або інтерактивний режим
if len(sys.argv) > 1:
   print(send_command(ser, sys.argv[1]))
else:
   while True:
       cmd = input("stm32> ").strip()
       if cmd == "quit": break
       resp = send_command(ser, cmd)
       if resp: print(f" ← {resp}")

Скрипт підтримує змінну оточення STM32_PORT для роботи з різними UART:

# Основний UART (U4)
python3 stm32_controller.py on

# Через UART1 (U3)
STM32_PORT=/dev/ttyS1 python3 stm32_controller.py blink 3

# Через UART4 (U11)
STM32_PORT=/dev/ttyS4 python3 stm32_controller.py off

Тестуємо blink — три рази блимнути LED:

$ python3 stm32_controller.py blink 3
Блимаємо 3 разів...
[1/3] ON → LED on
[1/3] OFF → LED off
[2/3] ON → LED on
[2/3] OFF → LED off
[3/3] ON → LED on
[3/3] OFF → LED off
Готово!

Linux керує STM32 через Python. Це вже не мигання LED — це архітектура. Мозок (Luckfox з Linux) дає команди м’язам (STM32 з bare-metal прошивкою).

Частина 6. А що тут за NPU?

Поки розбирався з DTS, звернув увагу на цікаву ноду:

npu@ff660000 {
    compatible = "rockchip,rknpu";
    ...
};

NPU — Neural Processing Unit. На нашій $15 платі є нейроприскорювач на 0.5 TOPS. Перевіряємо:

$ ls /dev/rknpu
/dev/rknpu

$ dmesg | grep -i npu
RKNPU ff660000.npu: Initialized RKNPU driver v0.9.2

$ find /oem -name '*.rknn'
$ ls /oem/usr/lib/librknn*
/oem/usr/lib/librknnmrt.so

Драйвер працює, C бібліотека є. А в SDK Luckfox знаходимо проект rk_smart_door з готовими моделями нейромереж: детекція облич, розпізнавання, визначення повороту голови. Python binding, що правда немає — тільки C API через rknn_api.h.

Це відкриває цікаву перспективу: камера на Luckfox знімає, NPU розпізнає обличчя, через UART дає команду STM32, а той вмикає реле через зсувний регістр. Повний ланцюжок від камери до фізичної дії — на двох платах за $20.

Але це вже тема наступної статті. Поки розповів вам про NPU, щоб заінтригувати в надії на підписку чи додавання в обране.

Філософія: SOLID для заліза

Є спокуса одразу будувати щось велике — розумний будинок, систему відеоспостереження, автономного робота. Але великі проекти вбивають мотивацію, бо результат далеко, а проблеми — ось вони, прямо зараз.

У цій серії, як і в житті загалом дотримуюсь іншого підходу, який нагадує принцип єдиної відповідальності з SOLID: одна задача — один проект. Кожен проект маленький, закінчений і самодостатній. Але з інтерфейсами для з’єднання з іншими.

Подивіться що ми вже маємо:

STM32 HAL — bare-metal бібліотека з чистим UART інтерфейсом. Не знає нічого про Linux.

Buildroot образ — Linux система з Go сервером, SSH, Python. Не знає нічого про STM32.

Device Tree — один рядок status = «okay» з’єднує ці два світи через /dev/ttyS3.

Python контролер — абстракція над UART. send_command("on") і все.

Плата Pi Pico Sim800 — фізична абстракція. Конектори як інтерфейси: встроми модуль і він працює.

Кожен з цих блонів можна використати окремо. Але разом вони починають складатись в систему: IoT розетка з SMS-керуванням (Pi Pico + SIM800L) → IP-камера зі стрімом (Luckfox) → Linux керує STM32 через UART → NPU розпізнає обличчя і вмикає реле.

Не треба будувати ракету одразу. Просто напрацьовуй модулі з правильними інтерфейсами, і одного дня вони самі складуться в ракету.

Підсумок

Ми пройшли від DTS до працюючої системи керування STM32 за допомогою Linux:

• Розібрали DTS свого пристрою і побачили ті ж концепції що на STM32 bare-metal

• Змінили один рядок — отримали три нових UART

• Підключили STM32 до Luckfox і написали Python контролер

• Зрозуміли як працює MTD, flashcp, і часткова прошивка

• Зазирнули в NPU і побачили що там чекає

Далі — GStreamer для відеостріму і якщо потягну, можливо детекція облич через NPU. Камера вже працює (стрім ми налаштували раніше), прийшов час додати до нього мізки.

Кому цікаво можете подивитись попередні проекти, які згадуються у тексті:

IoT PowerHub — Pi Pico + SIM800L + реле + MQTT — dou.ua/forums/topic/56126/

Та сама плата Pi Pico Sim800, тільки з Pi Pico замість Luckfox. Реле, зсувний регістр, GSM — все що ми сьогодні маппили на нові піни.

Luckfox Pico Pro — від ATmega8 до відеостріму — dou.ua/forums/topic/58244/

Перше знайомство з Luckfox, камера, MJPEG стрім. Тепер додаємо до цього STM32 і NPU.

Можливо, прийде час і ці маленькі проекти за допомогою зазделегідь передбачених інтерфейсів поступово складуться в щось більше. Може, колись і на Автобота комп’ютерний зір прикручу — камера є, NPU є, UART до мотор-контролера теж є. А що ще треба, для крутого автобота?

Довідники

dts_theory_guide.md — теорія DTS з порівнянням STM32 bare-metal на кожному кроці

dts_commands_cheatsheet.md — практичні команди для пошуку, перегляду, компіляції і діагностики DTS

Репозиторій: github.com/pipicosim800-maker/stm32F103

👍ПодобаєтьсяСподобалось9
До обраногоВ обраному5
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

Споріденні файли, з розширеннями: dtb, dts, dtsi, dtc compiler «dtc parameters».
Про компілятор у вас нічоґо не знaйшоy, а без цьоґо взаґалі, я впевнений, ніхто нічоґо не зрозуміє.
Very important : І як фінальний файл binary (dtb) використовувати. Я це робив через Лінукс софтлінки до модулів. І там ще е дуже велика ніша як їх використати.

Треба доповнити обов’азково.

— Для мене особисто, коли з цим працював залишилось незрозумілим різниця між файлами з розширеннями dts i dtsi.

Дякую!
DTS і DTSI та ж різниця що .c і .h в C:
.dtsi — це include-файл (бібліотека з описом SoC),
.dts — файл конкретної плати який включає потрібні .dtsi і перевизначає налаштування. Описував в статті як аналогію з HAL: rv1106.dtsi це як hal.h, а .dtsплати це як `main.c`.

Стосовно компіляція dtc, то:
в Luckfox SDK відбувається автоматично через ./build.sh kernel.
Але можна і вручну — dtc -I dts -O dtb -o output.dtb input.dts (компіляція),
dtc -I dtb -O dts -o readable.dts firmware.dtb (декомпіляція, щоб подивитись що всередині). Детальніше в шпаргалках dts_commands_cheatsheet.md

VsWorks RTOS:
Може комусь допоможе мій досвід: окремо компілюють кожний файл з описом dts, фінальний файл dtb за допомоґою софтлінк лінкують до усіх модулів. Потім іде білдінґ всієї систeми.

Дякую за доповнення! Цікаво що Device Tree використовується і в VxWorks отже DTS/DTB став стандартом не тільки для Linux, а і для embedded. Buildroot/Luckfox SDK компіляція DTS відбувається автоматично під час ./build.sh kernel, але принцип той самий — dtc компілює .dts -> .dtb, і далі DTB йде в boot image.

Ще важливе доповнення:
як правило все дженерек. Але для конкретних бордів треба робити перегляд, додавати чого не вистачає і перекомпілювати все. Займає також час. Я це робив для таких Samsung’s Exynos Auto V920, Xilinx/ZynqMP, iMX8 families.

Дякую, за важливе доповнення, у вас неймовірно багатий досвід

зсувний регістр SN74HC595N

Занадто олдскульно. Чи не ліпше було взяти розшируювач GPIО з SPI або І2С?

# Збираємо ядро (включає компіляцію DTS)
cd ~/luckfox-pico
./build.sh kernel

# Копіюємо boot.img на плату
scp -o PubkeyAuthentication=no output/image/boot.img \
[email protected]:/tmp/

# Прошиваємо тільки boot розділ (mtd3) і перезавантажуємо
ssh -o PubkeyAuthentication=no [email protected] \
«flashcp /tmp/boot.img /dev/mtd3 && reboot»

а там що boot.img 3 в 1: ядро, файлова система, і девайс трі?

Файлова система (rootfs) сидить окремо на mtd6.

Тому коли ми змінюємо DTS і перезбираємо ядро — прошиваємо тільки mtd3 (4MB), а не весь образ (250MB+). Rootfs залишається на місці з усіма файлами, Python скриптами, налаштуваннями.
Якщо потрібно оновити і rootfs — тоді повний образ через USB: sudo upgrade_tool uf output/image/update.img

Може й краще, мав напрацювання з іншої поделки, вщяв що було

Занадто олдскульно. Чи не ліпше було взяти розшируювач GPIО з SPI або І2С?

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