Словник embedded термінів

Мінімум, який має знати junior embedded-розробник, і про який реально питають на співбесіді. Не енциклопедія — а саме той зріз, що покриває bare-metal STM32 і Linux kernel modules з нашої серії. Колонка «💬 на співбесіді» — типовий ракурс питання.

◆ Загальні поняття

Термін Що це 💬 на співбесіді
Bare-metal Код, що працює прямо на залізі без ОС. Сам керуєш регістрами, перериваннями, пам’яттю «Чим bare-metal відрізняється від програмування під Linux?»
Firmware Прошивка — програма, зашита в пам’ять пристрою
RTOS Операційна система реального часу (FreeRTOS, Zephyr). Гарантує час реакції на подію «Навіщо RTOS, якщо є super-loop у while(1)
HAL Hardware Abstraction Layer — шар, що ховає роботу з регістрами за зручними функціями (gpio_write) «Що дає свій HAL і чим він гірший за прямі регістри?»
Toolchain Набір інструментів збірки: компілятор, лінкер, асемблер (arm-none-eabi-gcc)
Cross-compilation Збірка на одній архітектурі (x86) під іншу (ARM) «Чому не можна просто gcc на ПК для STM32?»
SoC System on Chip — процесор + периферія на одному кристалі (RV1106, BCM2837)

◆ Пам’ять і C

Термін Що це 💬 на співбесіді
volatile Каже компілятору «не оптимізуй це, значення може змінитись ззовні» Класика. «Навіщо volatile для регістрів і змінних з ISR?»
MMIO Memory-Mapped I/O — регістри периферії доступні як звичайні адреси пам’яті «Як CPU спілкується з GPIO?»
.text Секція з кодом програми (read-only, у Flash) «Де живе код, а де змінні?»
.data Ініціалізовані глобальні змінні (копіюються з Flash у RAM при старті)
.bss Неініціалізовані глобальні (обнуляються в Reset_Handler) «Що відбувається з .bss до main()
Stack Стек — локальні змінні, адреси повернення. Росте вниз «Stack vs heap, де що?»
Heap Купа — malloc. У bare-metal зазвичай уникають «Чому malloc погано в embedded?»
Linker script .ld-файл: де у пам’яті лежать секції, де стек, де вектори «Навіщо лінкер-скрипт?»
Endianness Порядок байтів: little-endian (ARM) vs big-endian «У якому порядку зберігається uint32_t

Чому volatile критичний (готова відповідь): Компілятор бачить while (!(SR & RXNE)); і думає: «SR я вже прочитав, він не міняється — зациклю на старому значенні». Без volatile цикл зависне назавжди. volatile змушує читати з пам’яті щоразу. Те саме з прапором, який ставить ISR: без volatile основний код його «не помітить».

◆ Периферія

Термін Що це 💬 на співбесіді
GPIO General Purpose I/O — універсальний цифровий пін (вхід/вихід)
UART Послідовний інтерфейс, 2 дроти (TX/RX), без тактового сигналу «Скільки дротів у UART? Що таке baud rate?»
I²C Двопровідна шина (SDA/SCL), багато пристроїв на адресах «Чим I²C відрізняється від SPI?»
SPI Швидка шина (MOSI/MISO/SCK/CS), full-duplex «Коли SPI, коли I²C?»
PWM Широтно-імпульсна модуляція — «середня» напруга через шпаруватість «Як керувати яскравістю LED / швидкістю мотора?»
ADC / DAC Аналого-цифровий / цифро-аналоговий перетворювач
Push-pull Вихід активно тягне і в 1, і в 0 «push-pull vs open-drain?»
Open-drain Вихід тягне тільки в 0; для 1 потрібен pull-up (так працює I²C)
Pull-up / pull-down Підтяжний резистор, що задає стан «висячого» входу «Навіщо pull-up на кнопці?»
Baud rate Швидкість UART у бітах/с (9600, 115200) «Що буде, якщо baud не збіжиться?»
Debounce Усунення «дребезгу» механічної кнопки «Кнопка дає кілька спрацювань — чому?»

◆ Переривання і час

Термін Що це 💬 на співбесіді
Interrupt / IRQ Сигнал, що змушує CPU кинути все й виконати обробник Класика. «Interrupt vs polling?»
ISR Interrupt Service Routine — функція-обробник переривання «Що НЕ можна робити в ISR?»
Polling Активне опитування в циклі замість переривання
Vector table Таблиця адрес обробників на початку Flash (у нас — startup.c) «Що лежить за адресою 0x08000000?»
NVIC Контролер переривань у Cortex-M (пріоритети, вмикання)
SysTick Системний таймер ядра Cortex-M (у нас — delay_ms) «Як зробити затримку без бібліотек?»
DMA Прямий доступ до пам’яті без участі CPU «Навіщо DMA при роботі з UART/ADC?»
Watchdog Сторожовий таймер: перезавантажує систему, якщо її «повісило» «Як захиститись від зависання?»
Race condition Гонитва: результат залежить від порядку доступу до спільних даних

Що не можна в ISR (готова відповідь): ISR має бути коротким. Не можна: довгі затримки, printf/malloc, блокуючі операції. Спільні з основним кодом дані — тільки через volatile (а в Linux — через блокування). Ідея: ISR ставить прапор / кладе байт у буфер, а важку роботу робить основний цикл.

◆ Завантаження

Термін Що це 💬 на співбесіді
Bootloader Перша програма після ввімкнення; готує систему й запускає основну «Що відбувається від подачі живлення до main()
Reset_Handler Перша функція bare-metal: копіює .data, чистить .bss, кличе main() «Хто викликає main() на STM32?»
U-Boot Універсальний bootloader для embedded Linux «Роль U-Boot у boot-ланцюгу?»
SPL Secondary Program Loader — мінімальний перший етап (вліз у малий SRAM)
Boot sequence ROM → SPL → U-Boot → kernel → init → userspace «Намалюй ланцюг завантаження Linux»
RCC / clock gating Тактування периферії: вимкнений блок не працює, поки не ввімкнеш такт «Чому GPIO мовчить, хоч код правильний?»

◆ Linux kernel

Термін Що це 💬 на співбесіді
udev User-space демон, що автоматично створює/видаляє /dev/* вузли, коли ядро повідомляє про новий пристрій «Звідки береться /dev/sdb1, коли встромляєш флешку?»
mknod Ручне створення device-вузла (mknod /dev/x c major minor). Потрібен тільки якщо драйвер НЕ використовує class_create/device_create «Чим відрізняється ручний mknod від автоматичного udev?»
class_create / device_create API ядра: драйвер сам реєструє клас і просить udev створити /dev/... без ручного mknod «Як /dev/mydev з’являється сам після insmod
Device permissions (udev rules) За замовчуванням device_create дає 0600 (тільки root). Права налаштовуються через /etc/udev/rules.d/*.rules, наприклад KERNEL=="mydev", MODE="0666" «Чому echo > /dev/mydev дає Permission denied навіть коли драйвер запущений?»
User space / kernel space Розділення: програми (обмежені права) vs ядро (повний доступ) Класика. «Чим відрізняються?»
System call Місток із user space у kernel (read, write, open) «Як userspace просить ядро щось зробити?»
Kernel module Код, що додається в ядро на льоту (insmod/rmmod) «Навіщо модуль, а не вкомпілювати в ядро?»
Character device Пристрій, з яким працюють побайтово як з потоком (/dev/ttyS0) «char vs block device?»
Block device Пристрій блоками з довільним доступом (диск, SD)
major / minor Старший номер = драйвер, молодший = конкретний пристрій «Що значать цифри в ls -l /dev/...
file_operations Структура з вказівниками на open/read/write/release драйвера «Як cat читає твій /dev/mydev?»
sysfs / procfs Віртуальні ФС, що показують стан ядра (/sys, /proc)
Device Tree Опис заліза для ядра у вигляді дерева (.dts.dtb) «Як ядро дізнається, яка периферія є на платі?»
printk printf ядра; вивід читаємо через dmesg
Platform driver / probe Драйвер, що «знаходить» своє залізо через DT; probe() викликається при збігу «Що таке probe і коли він спрацьовує?»
copy_to_user / copy_from_user Безпечне копіювання між kernel і user space «Чому не можна просто memcpy з userspace-вказівника?»
Kernel oops / panic oops — локальна помилка (модуль), panic — фатальна (система стає) «Різниця між oops і panic?»
Tainted kernel «Забруднене» ядро (сторонній модуль, oops) — впливає на підтримку

user vs kernel space (готова відповідь): User space — де живуть програми, з обмеженими правами й власною віртуальною пам’яттю; впала програма — впала тільки вона. Kernel space — ядро з повним доступом до заліза; помилка тут валить усю систему. Перехід — лише через системні виклики. Тому copy_from_user: вказівник з userspace не можна довіряти напряму (може бути невалідним або чужим).

◆ Конкурентність

Термін Що це 💬 на співбесіді
Mutex Блокування, що може спати; для довгих секцій, тільки в контексті процесу «mutex vs spinlock — коли що?»
Spinlock Блокування, що крутиться в циклі (busy-wait); для коротких секцій, можна в ISR
Semaphore Лічильник доступів; дозволяє N одночасних власників
Atomic Операція, яку не можна перервати посередині (atomic_inc) «Як безпечно інкрементувати лічильник?»

mutex vs spinlock (готова відповідь): Mutex може заснути, поки чекає — тому не можна в ISR (там спати не можна). Spinlock крутиться в циклі й не спить — підходить для ISR, але марнує CPU, тож тільки для дуже коротких секцій. Правило: довга критична секція в контексті процесу — mutex; коротка або в перериванні — spinlock.

◆ «Підступні» питання, на яких сиплються

Питання Коротка правильна відповідь
Навіщо volatile? Заборонити оптимізацію змінних, що міняються ззовні (регістри, прапори з ISR)
Чому не malloc в ISR? Може блокувати/спати, фрагментує купу, недетермінований час — ISR має бути швидким
sudo echo 1 > /sys/... не працює, чому? > виконує шел від користувача, не від root. Треба echo 1 | sudo tee
echo > /dev/mydev дає Permission denied, хоч модуль завантажений? device_create за замовчуванням ставить 0600 (тільки root). Треба sudo або udev rule з MODE="0666"
Чому GPIO мовчить, хоч код вірний? Не ввімкнене тактування порту (RCC / clock gating)
Stack чи heap росте вгору? Stack зазвичай вниз, heap вгору — назустріч одне одному
Що буде при колізії stack і heap? Stack overflow / пошкодження даних — у bare-metal без MMU тихо і боляче
Чому модуль під інше ядро не вставляється? Version magic: .ko прив’язаний до версії й конфігу ядра
open-drain навіщо? Кілька пристроїв на одній лінії (I²C), wired-AND, рівні через pull-up
insmod дає -517, а піни вільні за gpioinfo? Це EPROBE_DEFER, не «зайнято». Legacy gpio_request + module_init приречені — треба platform_driver + Device Tree
Перебираю піни в коді, а все одно failed — чому? Бо проблема не в пінах, а в моделі драйвера. Жоден номер не виправить EPROBE_DEFER на голому module_init
probe викликався, але -16 на GPIO? EBUSY: лінію тримає інший consumer. Частий винуватець — залишений у фоні gpiomon/gpioset. pkill його
Overlay зібрався, але &gpio не резолвиться? Забув -@ у dtc. Без symbols посилання в overlay не працюють
Після reboot /dev/hcsr04 зник? Overlay лише оголошує пристрій. Сам модуль треба insmod вручну або через /etc/modules-load.d/
throttled=0x50000 — живлення вмерло? Ні. Біти 16+18 = «траплялось у минулому». Активна проблема — тільки біти 0–3

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *