Початок кар’єри в Embedded-розробці. Які інструменти варто освоїти для роботи з мікроконтролерами
Привіт! Мене звати Максим, я працюю в GlobalLogic на посаді Associated C++ Developer. До компанії потрапив, як і більшість студентів, через РОС-проєкт. Маю вже рік комерційного досвіду, спеціалізуюся на C++, Embedded і розробці ПЗ під мікроконтролери.
У цій статті хотів би розповісти спеціалістам, які тільки починають свій шлях в Embedded-напрямі, якими були мої перші кроки та які базові інструменти варто опанувати для розробки під мікроконтролери.
Почнемо з бази: різниця між CPU і MCU
В Embedded-розробці часто доводиться працювати з мікроконтролерами (MCU), які мають свою власну архітектуру, що відрізняється від звичайних процесорів (CPU).
В чому взагалі різниця між CPU і MCU? CPU — це Central Processor Unit. Процесори в загальновідомих персональних комп’ютерах, які ми використовуємо повсякденно. Також існують мікроконтролери, які зазвичай зустрічаються в менших девайсах. Їх, як правило, називають constraint-девайси — тобто ті, що мають обмежені можливості.
Ці два типи обчислювальних чипів відрізняються тим, що процесори виконують лише обчислення, а мікроконтролери поєднують кілька функцій. Не лише обчислюють, але й зберігають інформацію, що робить їх багатофункціональними.
Які інструменти для розробки під мікроконтролери опанувати першими
До того, як я потрапив в Embedded-розробку, закінчив декілька базових курсів з IoT на Coursera та брав участь в Embedded-хакатоні. Хоча певне уявлення про напрям я вже мав, безпосередньо навичок було обмаль для роботи на реальному проєкті.
Щоб початківцю стати на шлях вивчення Embedded, варто добре розбиратися в ООП, процесі компіляції, знати мови програмування C/C++, і, що не менш важливо, мати бажання досліджувати та працювати в цьому напрямі.
Для базового розуміння добре підійдуть різні Arduino Kit, а також мікроконтролери від Espressif, наприклад, ESP32. Зокрема, потрібно добре володіти такими інструментами для розробки:
- CMake.
- GNU Make.
- GNU Compiler Collection (gcc, g++).
Серед базових — саме CMake. Можливо, хтось вже стикався і знає про Gnu Compiler Collection (gcc), g++ інструменти, які використовуються в процесі компіляції під якусь цільову платформу. Але в основному такі компілятори призначені для операційних систем загального призначення на кшталт Linux.
Для компіляції коду в firmware, яка буде запущена на мікроконтролері, використовуються більш вузькоспрямовані компілятори типу ARM. А також інструменти як-то Gnu Make для управління процесом компіляції. До прикладу: якщо цільова платформа, яка повинна запускати написаний код, має мікроконтролер з ARM-архітектурою, то доцільно використовувати відповідний компілятор по типу arm-none-eabi.
Також, залежно від платформи, може змінюватись кількість інтерфейсів для взаємодії та безпосередньо «розпіновка» (pinout). Зробити процес компіляції більш універсальним можна з використанням директив (макросів), щоб включати в firmware тільки ті компоненти та ту частину коду, які підходять нашій цільовій платформі. Цей процес називається умовною компіляцією.
У Makefile зазвичай вказуються необхідні параметри, такі як змінні середовища або параметри при його запуску, щоб зробити процес компіляції більш гнучким. Це дозволяє макросам в коді вирішувати, чи включати певні частини коду, залежно від інформації в Makefile. Втім варто памʼятати: згідно з кращими практиками, не слід зловживати використанням макросів, пишучи код на C++. Це може призвести до непередбачуваної поведінки й надалі ускладнити процес дебагу безпосередньо коду. В такому випадку краще ініціалізувати значення «на стеці», використовуючи для цього окремий namespace.
Одне з практичних рішень в Embedded-розробці — це використання ESP-IDF фреймворку. Він полегшує розробку ПЗ під сімейство мікроконтролерів компанії ESP.
Окреслити основні переваги використання саме ESP-IDF фреймворку можна так:
- Легкість використання — він бере на себе складний процес компіляції й створення build pipeline.
- User friendly документація.
- Багато офіційних прикладів коду — це ціла Вікіпедія. Можна зайти на сайт офіційної документації та знайти там приклади коду й документації по різних частинах. Саме тому для бізнесу це доволі валідна штука.
- Інтеграція з іншими системами, підтримка багатьох протоколів;
- Низька цінабезпосередньо мікроконтролерів ESP.
Особисто мені вже доволі великий проміжок часу доводиться працювати з ESP-IDF фреймворком, який показує високу гнучкість і великий функціонал для адаптації під свої потреби та інтеграції з іншими системами.
Процес компіляції у розробці
Процес компіляції може здатися доволі незвичним і складним для новачків, проте його необхідно зрозуміти, щоб стати кращим спеціалістом у майбутньому.
Ось з чого він складається:
- На першому етапі компіляції залучається препроцесор, який замінює директиви та константи реальними значеннями в коді. Всі ці значення будуть розміщені в такому сегменті пам’яті мікроконтролера, як bss storage, який зберігає в собі всі константні та неініціалізовані значення.
- На другому етапі код компілюється в object-файли з розширенням .o . Такі файли буквально містять в собі двійкові значення.
- На третьому етапі починає дію лінкувальник, ціль якого — об’єднати всі object-файли в один.
- І як завершальний етап всього процесу виконується робота локатора, який розміщує firmware на цільовій платформі.
Слід зазначити, що написаний нами код зберігається в енергонезалежній пам’яті, в code memory сегменті. А інформація про запуск нашого коду (application) — в сегментах енергозалежної пам’яті stack та heap.
Тут важливо розуміти організацію памʼяті, а саме розрізняти volatile та non-volatile storage. Перший тип пам’яті використовується для зберігання інформації, яка з кожним перезапуском буде стиратися. Іншими словами — енергозалежна пам’ять. Другий тип — енергонезалежний, і використовується він для зберігання критичної інформації, що не може бути втрачена. Прикладом енергозалежної пам’яті є RAM, а енергонезалежної — EEPROM, Flash та NVS.
Розуміння всіх цих процесів допоможе в створенні гнучкого build pipeline, який можна адаптувати під будь-які потреби.
Перші кроки в Embedded: кейс з практики
Раніше GlobalLogic розробили POC-проєкт, який мав на меті менеджмент енергії, що споживається на різних підприємствах та у багатоквартирних будинках. До прикладу: у нас є домашні пристрої, які споживають електроенергію. Щоб не виходити за певні ліміти, потрібно надавати пріоритети кожному з них. І кожен девайс — це певна плата, яка підключається до Raspberry Pi 3 сервера і взаємодіє з ним. А сервер вже розподіляв, чи надавати доступ до електромережі такому пристрою, чи ні.
Цей проєкт продовжував розвиватись. Одним з перших завдань моєї команди (і перших моїх завдань у напрямі Embedded загалом) стала імплементація рішення для його інтеграції з іншою платформою. Клієнти, які підключаються до сервера, були реалізовані на базі мікроконтролера Raspberry Pi Zero, а нам слід було зробити міграцію на Raspberry Pi Pico.
У чому полягав челендж? Існує інструмент Avahi, який є імплементацією zero-conf мережі та робить комунікацію між девайсами більш доступною, даючи змогу взаємодіяти девайсам за допомогою hostname.
Який принцип роботи цієї технології? Уявімо девайс, який підключений до мережі й має свою IP-адресу. Він хоче надіслати якийсь запит на сервер. На цьому етапі він може зіткнутися з проблемою, коли IP-адреса сервера в мережі постійно змінюється. Оскільки він міг під’єднатися раніше та отримати одну IP-адресу, а міг зробити це пізніше та отримати іншу, яка визначається маскою мережі. Завдяки hostname не потрібно знати IP-адресу нашого сервера, коли в мережі наявний DNS-сервер, що зберігає в собі інформацію про IP-адреси пристроїв і рівнозначні ним hostname.
Проблемою нашої адаптації під іншу платформу стало те, що Avahi Service, який працював з попередньою Raspberry Pi Zero платформою, не був сумісний з Raspberry Pi Pico.
Як ми вийшли з цієї ситуації? Змінили підхід взаємодії між клієнтами та сервером в мережі. Відтепер сервер мав статичну IP-адресу, що давало гарантію підключення до нього і незмінність його IP-адреси. На основі цього ми адаптували POC-проєкт під Raspberry Pi Pico мікроконтролери.
Досвід на проєкті дав мені можливість не лише ознайомитися з новими технологіями, а й спробувати глибше зрозуміти наявну архітектуру та адаптувати її під специфічні потреби. Що є досить важливою навичкою для Software Engineer загалом.
Висновки
Отже, розробка під мікроконтролери відрізняється від звичної розробки ПЗ тим, що має певні особливості своєї платформи. А також безпосередньо розробка залежить від багатьох факторів, як-то розмір пам’яті та тип мікроконтролера. Окреме місце займає процес компіляції, оскільки його розуміння є необхідним для розробки універсальних програм, які використовуватимуть всі спроможності цільової платформи та будуть гнучкими у використанні.
Початківцям порадив би вкластися фінансово у свої Embedded-знання і купити Arduino kit або ж ESP32 мікроконтролер. Це не стало б дорогою покупкою, проте дало б досвід роботи з мікроконтролерами та розуміння їх взаємодії.
Особисто для себе з подальших викликів в кар’єрі виділяю покращення розуміння в програмуванні, різних технологіях та роботу не лише з мікроконтролерами, а й з іншими платформами.
70 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів