ARM для Ардуїнщиків, які прагнуть чогось більшого

Від архітектури ядра до реального заліза на столі. Це ввідна стаття серії уроків STM32 з нуля без HAL: що під капотом Blue Pill · ST-Link v2 · Linux · arm-none-eabi-gcc

Як пише Ю. Ревич у вступі до книги «Занимательная електроника», — «як відомо кожен сходить з розуму по своєму. Є люди, здвинуті на збиранні сірникових етикеток чи монет, є ті хто стрибає з парашутом». Один з різновидів подібних психічних здвигів — радіолюбителі до яких зокрема і відносяться усілякі распберіПіЩики, ардуїнЩики, stmЩики, espШніки та інші Щики і Шніки цієї категорії.

Тож якщо ти, як і я входиш до цієї категорії або вже намагався світлодіодом на Arduino, підключав DHT22 через бібліотеку і загалом розумієш навіщо потрібен pull-up резистор тоді, ця стаття якраз для тебе. Сьогодні поговоримо про ARM: що це таке насправді, чому половина заліза на твоєму столі на ньому і побудована, і як взагалі орієнтуватись у цьому зоопарку чіпів.

Пишу з особистого досвіду: у мене на столі одночасно живуть Raspberry Pi Pico, Luckfox Pico Pro, STM32F103, Esp32 і купа периферії. Всі вони в якомусь сенсі «ARM» — але написати прошивку для одного і запустити на іншому без змін неможливо. Чому? Давай розбиратись.

ARM це не процесор. Це бізнес-модель

Перший факт, який ламає мозок новачкові: Arm Holdings не виробляє жодного фізичного чіпа. Взагалі жодного. Вони продають ліцензії на право використовувати розроблену ними архітектуру процесорного ядра.

Схема виглядає так: Arm розробляє ядро (наприклад, Cortex-M3), описує його в специфікаціях та RTL-коді, а компанії типу STMicroelectronics, Raspberry Pi Ltd, Espressif і ще кількасот інших платять за право це ядро вставити у свій чіп і додати власну периферію: таймери, UART, SPI, ADC, Wi-Fi стеки тощо.

Саме тому STM32F103 і Raspberry Pi Pico обидва є ARM, але вони несумісні на рівні прошивки. Однакове ядро, але різна периферія, різне відображення пам’яті, різні SDK і HAL-бібліотеки.

Станом на 2026 рік ARM-архітектура присутня у більш ніж 95% смартфонів, більшості embedded-мікроконтролерів і активно заходить у серверний сегмент — AWS Graviton4, Apple M4, Qualcomm Oryon. RISC-V наступає знизу, але в embedded Cortex-M поки тримає позиції впевнено.

Три сімейства: Cortex-A, R і M

Arm ділить свої ядра на три великих сімейства. Якщо ти займаєшся embedded то тобі потрібне переважно щось одне, але знати про решту корисно, бо вони іноді зустрічаються в одному і тому ж проекті.

Cortex-A — там, де є Linux

Application-процесори. Тут живуть Android-смартфони, Raspberry Pi, роутери, одноплатники. Головна фіча — MMU (Memory Management Unit), тобто апаратна підтримка віртуальної пам’яті. Саме вона дозволяє запускати повноцінні ОС з ізольованими процесами.

Актуальна лінійка: Cortex-A55 (ефективне ядро у більшості Android SoC), Cortex-A78/X2 (продуктивні ядра), Cortex-A720 (2023+). На відміну від статті 2019 року, сьогодні «Cortex-A15 для флагманів» — це вже музейний експонат.

  • Наш приклад: Luckfox Pico Pro на базі RV1106 — Cortex-A7 @ 1.2 ГГц. Ми на ньому крутимо Buildroot Linux, Go HTTP-сервер і RTSP відеострім. Все на чіпі розміром з ніготь.

Cortex-R — real-time для серйозних дядьків

Realtime-процесори з жорсткими часовими гарантіями та підвищеною відмовостійкістю. Живуть у ABS-системах, жорстких дисках, SSD-контролерах, промисловій автоматиці. Детермінований час відповіді — головна фішка.

В домашніх поробках embedded ці ядра не зустрінеш, але в automotive або industrial, вони точно є.

Cortex-M — наш мікроконтролерний бродяга

Microcontroller-процесори. Саме тут живе більшість embedded-розробки: від датчиків до складних приблуд. Немає MMU але є детермінований час реакції, мало жере і норм ціна. Ключові представники:

  • Cortex-M0/M0+: мінімальне ядро, 2-ступінчастий конвейер, тільки Thumb-2. Raspberry Pi Pico (RP2040) — два ядра M0+ @ 133 МГц.
  • Cortex-M3: 3-ступінчастий конвейер, апаратне ділення, bit-banding. STM32F103 мабуть класика жанру, 72 МГц.
  • Cortex-M4: додається DSP-інструкції та опційний FPU одинарної точності. STM32F4 серія.
  • Cortex-M7: 6-ступінчастий суперскалярний конвейер, FPU подвійної точності, кеш. На 2025–2026 роки на думку гуглШІ STM32H7 залишається «королем» серед класичних мікроконтролерів (MCU), але контекст «топовості» трохи змістився через появу нових гравців.
  • Cortex-M33/M85: нові ARMv8-M ядра з TrustZone для безпечних застосунків.

Cortex-M зсередини: що варто знати

Всі Cortex-M ядра мають схожу внутрішню організацію. І варто зазначити, що embedded на ARM відчувається інакше ніж на AVR.

Thumb-2: один набір інструкцій

Cortex-M використовує виключно Thumb-2 — змішаний набір 16 і 32-бітних інструкцій в одному потоці без перемикання режимів. Результат: менший розмір коду ніж у повному 32-бітному ARM (16-бітні інструкції для частих операцій), але продуктивно.

NVIC: переривання

Nested Vectored Interrupt Controller вбудований прямо в ядро контролер переривань. Підтримує до 240 зовнішніх переривань з 256 рівнями пріоритетів. Головнае тут автоматичне збереження стану: 8 регістрів пушаться апаратно при вході в ISR, без жодної інструкції пролога.

Саме тому FreeRTOS так добре живе на STM32 бо переключення контексту відбувається через PendSV переривання, а NVIC забезпечує передбачувані латентності. На STM32F103 при 72 МГц час входу в переривання — ~12 циклів (≈167 нс).

SysTick: системний таймер

24-бітний спадний таймер, вбудований у кожне Cortex-M ядро. Не залежить від периферії конкретного чіпа, тому будь-яка RTOS норм на ньому. На STM32 HAL_GetTick() і vTaskDelay() у FreeRTOS живуть на SysTick, зазвичай 1 мс на тік.

Bit-banding

Технологія атомарного доступу до окремих бітів через аліасний регіон пам’яті (є в M3/M4, немає в M0). Кожен біт в 1 МБ зоні відображається на окреме 32-бітне слово у 32 МБ зоні. Запис 0×00000001 у аліас = атомарна установка одного біта без read-modify-write.

На практиці в сучасному коді з HAL/LL-бібліотеками STM32 bit-banding майже не потрібен — бібліотеки використовують SET_BIT/CLEAR_BIT через атомарні операції або критичні секції. Але знати про нього треба, бо в легасі-коді зустрічається.

Наші герої: залізо на столі

Raspberry Pi Pico — RP2040, Cortex-M0+

RP2040 — перший власний чіп Raspberry Pi Ltd (2021),як на мене дуже цікавий. Два ядра Cortex-M0+ @ 133 МГц, 264 КБ SRAM, Flash зовнішній через QSPI — і PIO (Programmable I/O), якого немає більше ніде.

PIO — це вісім програмованих стейт-машин з власним набором інструкцій, які виконуються незалежно від CPU. Можна реалізувати WS2812, UART на нестандартній швидкості, VGA-сигнал, I2S — все без завантаження процесора. Мабуть, найоригінальніша фіча у low-end ARM-чіпах за останні роки.

У нашому проекті PiPicoSim800: RP2040 тягне MQTT 3.1.1 стек (написаний руками без бібліотек), двоядерну архітектуру (core0 — бізнес-логіка, core1 — комунікація з SIM800L через UART), 74HC595 для розширення GPIO на реле, BMP180 через I2C, EEPROM через SPI, XOR-шифрування з динамічною сіллю на основі ADC-шуму.

Cortex-M0+ — найпростіше ядро лінійки: немає FPU, немає DSP, 2-ступінчастий конвейер, тільки ARMv6-M ISA. Але він мінімально споживає і найменший за площею кристала. Саме тому він у смарт-картках, BLE-сенсорах і будь-де, де важлива батарея.

STM32F103 — Cortex-M3, класика жанру

STM32F103 — мабуть, найпоширеніший ARM-мікроконтролер у DIY-просторі. Cortex-M3 @ 72 МГц, 20-64 КБ SRAM, 64-512 КБ Flash (залежно від суфіксу). Повноцінний Thumb-2, апаратне ділення, bit-banding, NVIC — і при цьому коштує 2-3 долари.

Cortex-M3 — перше ядро з повноцінним ARMv7-M ISA. Саме з F103 починалась епоха «ARM для всіх» на початку 2010-х, і він досі актуальний. Є нюанс: у продажу повно клонів GD32F103 (GigaDevice). Вони майже сумісні, але є відмінності у Flash-latency та тактуванні — іноді треба підправляти SystemInit.

У нашому проекті Автобот: Pi Pico — платформа для RC-ровера з маніпулятором. Маємо живий досвід з PX4: виявилось, що PX4 офіційно не підтримує MPU6050 через I2C (драйвер MPU6000 на SPI, а MPU9250 I2C відкидає WHO_AM_I=0×68). Купили MPU9250 — проблему вирішено, і це стало темою для статті.

ESP32 — не ARM, але сусід по столу

Окремо скажемо про ESP32, бо він є мало не у кожного, хто прийшов з Arduino. ESP32 — це не ARM. Класичний ESP32 (ESP32-D0/S2/S3) використовує Xtensa LX6/LX7 — власну архітектуру Tensilica/Cadence. ESP32-C3, C6, H2 — вже RISC-V, ще одна відкрита альтернатива.

Але підхід до розробки дуже схожий: Arduino-фреймворк, FreeRTOS всередині esp-idf, Flash через UART, GPIO/SPI/I2C периферія, OTA оновлення. Якщо ти прийшов з ESP32 — у тебе вже правильний майндсет. Просто архітектура ядра інша, і низькорівневі деталі будуть різнитись.

Конкуренція ARM vs RISC-V у low-end embedded — одна з головних тем 2025-26 років. ESP32-C6 з RISC-V вже популярніший за деякі ARM-альтернативи в IoT. Але для STM32 та RP2040-рівня екосистема ARM поки незамінна.

Luckfox Pico Pro — Cortex-A7, Linux у мініатюрі

Тут ми вже в іншому світі. RV1103 від Rockchip — це Cortex-A7 @ 1.2 ГГц з Mali-G52 GPU, 256 МБ DDR3L на борту і окремим NPU для нейромереж. Розмір — як USB-флешка.

Cortex-A7 підтримує ARMv7-A: MMU, NEON SIMD, VFPv4 FPU. Це дозволяє запускати Python, Go, Node.js і TensorFlow Lite без особливого болю. Принципова відмінність від Cortex-M: є ОС, є процеси, є файлова система. Але й складність зростає — замість простого HAL_GPIO_WritePin() у тебе /sys/class/gpio/ або /dev/mem через devmem2.

У нашому стрімінговому проекті: RTSP з камери MIS5001 → ffmpeg → Python HTTP-проксі з ThreadingHTTPServer (окремий ffmpeg-процес на клієнта, з retry-логікою) → браузерний дашборд. Go-сервер для температурного API і syslog-ендпоінту. Автостарт через /etc/init.d/S9x скрипти з sleep-затримками для правильного порядку залежностей.

Порівняння: що у нас є і навіщо

Параметр

Pi Pico (RP2040)

STM32F103

ESP32 (не ARM!)

Luckfox (RV1103)

Ядро

2× Cortex-M0+

Cortex-M3

Xtensa LX6

Cortex-A7

Частота

133 МГц

72 МГц

240 МГц

1.2 ГГц

SRAM

264 КБ

20–64 КБ

520 КБ

256 МБ DDR3L

Flash

2 МБ (QSPI)

64–512 КБ

4–16 МБ

MicroSD

FPU

Немає

Немає

Є

VFPv4

ОС

Bare-metal / FreeRTOS

Bare-metal / FreeRTOS

FreeRTOS / Arduino

Linux (Buildroot)

Wi-Fi/BT

Немає (Pico W — є)

Немає

Wi-Fi + BT вбудований

SoC з Ethernet

Ціна, $

~4

~2—5

~3—8

~15—20

Наш проект

PiPicoSim800 IoT / Автобот

навчальний стенд

MJPEG стрімінг

Інструменти: з чим реально працюємо

STM32CubeIDE — офіційна IDE від ST, заснована на Eclipse. Вбудований HAL-генератор через CubeMX, дебагер через ST-Link, профайлер. Безплатна. Важка як танк, але працює.

PlatformIO — якщо хочеш VSCode замість Eclipse і підтримку купи платформ (STM32, RP2040, ESP32, AVR) в одному місці. Файл platformio.ini замість купи XML-конфігів.

OpenOCD + GDB — для тих, хто хоче розуміти що відбувається. Відкриває ARM CoreSight debug через ST-Link, J-Link або CMSIS-DAP. На Linux — просто ставиться, на Windows — потребує драйверів.

picotool — утиліта для RP2040: перегляд бінарників, flash через USB в режимі BOOTSEL, інформація про UF2-образи.

arm-none-eabi-gcc — cross-компілятор для всього ARM bare-metal. Однаковий тулчейн для STM32 і Pi Pico, що зручно.

Що вибрати для свого проекту

Без зайвого маркетингу — практична шпаргалка:

  • GPIO / I2C / SPI, мінімум коду, бюджет важливий → STM32F103 або Pi Pico. Cortex-M0+/M3 справляться з 99% задач.
  • Нестандартні протоколи або паралельна логіка без CPU → Pi Pico з PIO. Окрема магія, серйозно.
  • Wi-Fi + BT вбудовані, не принципово ARM чи ні → ESP32. Найпростіший старт для IoT, величезна спільнота.
  • RTOS з жорсткими real-time гарантіями, FPU потрібен → STM32F4 (Cortex-M4) або STM32H7 (Cortex-M7). Бюджет відповідний.
  • Linux, камера, мережевий стек, Python/Go потрібні → Luckfox або Raspberry Pi. Cortex-A7+ відкриває інший рівень.
  • TinyML на мікроконтролері → Pi Pico + Edge Impulse або STM32 + STM32Cube.AI. Cortex-M4/M7 з DSP помітно швидші за M0+.

Практика: мигаємо LED без HAL за 272 байти

Всі ці теорії про регістри і memory map — це добре. Але краще один раз побачити в терміналі. Ось що відбувається коли пишеш під STM32 без жодної бібліотеки.

Структура проекту

Нам потрібно рівно чотири файли — і жодного HAL, жодного CubeMX, жодного XML:

  • src/startup.c — таблиця векторів переривань і Reset_Handler
  • src/main.c — наш код
  • ld/stm32f103.ld — лінкер скрипт з memory map
  • Makefile — збірка через arm-none-eabi-gcc

Лінкер скрипт — це і є ARM memory map

Перший файл який пишемо — лінкер скрипт. Саме він описує де живе Flash і SRAM нашого чіпа:

MEMORY
{
FLASH (rx) : ORIGIN = 0×08000000, LENGTH = 64K
SRAM (rwx) : ORIGIN = 0×20000000, LENGTH = 20K
}

Ці дві адреси — 0×08000000 і 0×20000000 — не вигадані. Вони прописані в datasheet STM32F103 і є частиною ARM Cortex-M memory map. Після reset процесор завжди стартує з 0×08000000 і читає звідти першу інструкцію.

Reset_Handler — що відбувається після увімкнення

Перше що робить Cortex-M3 після reset — читає два 32-бітних слова з початку Flash: початкову адресу стеку і адресу Reset_Handler. Далі стрибає туди і виконує наш код:

Reset_Handler копіює .data секцію з Flash у SRAM (там глобальні змінні з початковими значеннями), обнуляє .bss (неініціалізовані змінні), і викликає main(). Саме цей код виконується ще до першої строчки твого main — на AVR це робив компілятор, тут ти бачиш це явно.

main.c — тільки регістри

Весь код керування GPIO — це три макроси і три рядки в main. Ніяких HAL_GPIO_WritePin(), ніяких #include «stm32f1xx_hal.h»:

// вмикаємо тактування порту C через RCC
RCC_APB2ENR |= RCC_APB2ENR_IOPCEN;
// PC13 — вихід push-pull 2MHz (біти [23:20] в CRH)
GPIOC_CRH &= ~(0xF << 20);
GPIOC_CRH |= (0×2 << 20);
// toggle PC13 в циклі
GPIOC_ODR ^= GPIO_PIN_13;

PC13 на Blue Pill інвертований — LOW = LED горить. І він підтягнутий до 3.3V через резистор, тому при старті без коду LED теж горить. Це не баг плати, це особливість схеми.

Результат збірки

Збираємо одною командою make і флашимо через make flash через st-flash:

text data bss dec hex filename
272 0 0 272 110 blink.elf

272 байти. Для порівняння — порожній HAL-проект з CubeMX на тому ж F103 важить ~3-4 КБ тільки на ініціалізацію. Ми зробили те саме за 272 байти тому що знаємо що відбувається на кожному кроці.

Flash written and verified! jolly good! — і зелений LED на Blue Pill швидко мигає. Cortex-M3, 72 МГц, наші власні 272 байти коду. Ось це і є ARM зсередини.

У наступних частинах серія Уроків STM32 з нуля без HAL: що під капотом Blue Pill · ST-Link v2 · Linux · arm-none-eabi-gcc

Сподобалась стаття? Підписуйтесь на автора, щоб отримувати сповіщення про нові публікації на пошту.

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

👍ПодобаєтьсяСподобалось16
До обраногоВ обраному12
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
Arm Holdings не виробляє жодного фізичного чіпа.

www.theregister.com/2026/03/24/arm_agi_cpu

Дякую, але то наче прототип тільки, а не серійне виробництво

А чи буде тут 72МГц? Треба ж налаштувати кварц і дільники.

Буде. Це перша частина, по переду ще 5 вже готових, які стоять у черзі

Я саме так писав для 8бітного мікрочіпа (PIC10/12/16/18). під кінець того досвіду у них стали з’являтися бібліотеки периферії. Але ж там і регістрів було менше.

Ну нічого, що з’явились. Досвід здобули, цікаво і корисно провели час )

Доречі, я на них і не планував переходити, бо не розумів нашо такий великий город, якщо можна проініціалізувати буквально за 3-4 присвоювань в певні регістри)))
Зараз без таких бібліотек не уявляю старт з якимось складним модулем, там не так біти треба знати треба, як послідовність їх встановленя бо то грає роль.

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