Zephyr против bare-metal: год спустя

Год назад я перевёл одно небольшое промышленное устройство с честно написанной от руки прошивки на Zephyr RTOS. Прошёл год. Расскажу, что получилось, что не очень, и стоило ли оно того. Спойлер: да, но не в тот момент, когда я об этом думал.

Контекст

Устройство — промышленный датчик с RS-485 наружу, парой аналоговых входов, BLE-радио для местной диагностики и небольшим экраном. Микроконтроллер — nRF52840. До переезда: main.c на 4500 строк, всё в суперлуппе с ручным state machine, прерывания пишут в кольцевые буферы, всё в одном .elf. Работало. Девять месяцев в production без ребутов на тестовых стендах.

Зачем я полез в RTOS? Три причины:

  • BLE-стек от Nordic (SoftDevice) — это, по сути, тоже RTOS, только не моя. Когда у меня было два cooperative-event-loop'а — мой и SD — они начинали друг другу мешать в неочевидных местах.
  • Нужно было добавить TCP-стек поверх ESP32, который висит на UART как модем. Реализовывать TCP вручную я не собирался.
  • Архитектор проекта (то есть я) очень устал от того, что каждый периферийный драйвер пишется заново с нуля.

Что получилось

Готовые драйверы

Драйверы для I2C, SPI, UART, ADC, GPIO работают, имеют единый API, и их не нужно писать. Это самая большая выгода, и она реализуется в первые две недели. Если бы я переезжал ради одного этого, было бы оправдано.

Девайс-три (DTS) поначалу выглядит как оккультная практика, но через месяц-два до тебя доходит, что это корректный способ описывать оборудование.

BLE начал работать предсказуемо

Главная боль раньше. Со старым SoftDevice'ом я никогда не был уверен, в какой момент я могу делать что-то «тяжёлое» в main loop, не нарушив тайминги стека. У Zephyr с Bluetooth Host есть ясные API, ясные потоки, и стек ругается понятными ошибками.

Тесты на хосте

Native posix backend Zephyr позволяет собирать большую часть моей логики как обычный linux-бинарник и гонять unit-тесты на CI. Раньше у меня была отдельная «testbench», и я её ненавидел. Сейчас не ненавижу.

Что не очень

Размер бинарника

Старая прошивка: 96 КБ. Новая, с тем же функционалом: 244 КБ. Ужал до 198 КБ — но это всё ещё в два раза больше, чем было. Если у тебя 64 КБ flash — забудь про Zephyr.

Время сборки

Чистая сборка bare-metal: 4 секунды. Чистая сборка Zephyr: 38 секунд. Инкрементальная — обе в районе секунды.

Кривая обучения

Месяц мне понадобился, чтобы перестать ругаться на Kconfig. Два — на DTS. Три — чтобы я начал писать драйверы под Zephyr-style правильно.

Документация

Документация Zephyr — это википедия. Там есть всё. Но «есть всё» означает, что когда тебе нужен конкретный ответ, ты находишь страницу с тремя способами сделать одно и то же, причём один устарел два релиза назад.

Сюрпризы

Логика стала чище

Это удивило меня больше всего. Когда у тебя BLE в одном thread'е, телеметрия в другом, бизнес-логика в третьем, и они общаются через message queue — становится проще ответить на вопрос «что вообще здесь происходит».

Watchdog работает «бесплатно»

В Zephyr есть встроенный механизм task watchdog: каждый поток отмечается, и если кто-то перестал — общий перезапуск. Десять строк Kconfig.

Я наконец стал писать тесты

Не потому что Zephyr заставил, а потому что инфраструктура стала ниже трения. Это, наверное, влияет на качество прошивки больше, чем сам RTOS.

Стоило ли

Да. Но я бы сэкономил себе три недели нервов, если бы понимал заранее: первые два месяца ты будешь медленнее, а не быстрее. Это инвестиция, не upgrade.

правка, февраль 2026: я был неправ про DTS. через год это уже моя любимая часть Zephyr. в 2025 я её ненавидел.

Если решились

  • Не пытайтесь портировать всё за раз. Сначала переезд, потом рефакторинг.
  • Включите CONFIG_THREAD_ANALYZER сразу.
  • Не воюйте с Kconfig. Если вам нужно что-то странное — наверное, вам это не нужно.
  • Читайте samples/. Там есть примерно всё.
← в архив · → в ленту