Как стать автором
Обновить

DevOps для производства Firmware

Уровень сложностиПростой
Время на прочтение6 мин
Количество просмотров9.1K

Пролог

Часто слышал мнение, что в embedded программировании в принципе не может быть никакого DevOps(а).  Якобы вот есть GUI(ня) в IAR и там надо много мышкой водить. "Ты же не станешь ставить шаговые двигатели для сдвигания мышки" и т. п.

В этом тексте я намерен пофантазировать каким мог бы быть абстрактный процесс разработки firmware с точки зрения DevOps. И перечислить атрибуты такого процесса.

По правде, говоря все мы немного dev ops(ы). Сейчас объясню почему... Мы же не вручную код на assembler(е) пишем. Вовсе нет! Мы из абстрактного языка Си компилятором генерируем артефакты (*.hex, *.bin файл). A это значит, что мы DevOps(еры) все.

Однако этого конечно же не достаточно. Нужно рассмотреть ещё вот эти атрибуты.

1. Репозиторий с кодом (репа)

Это может быть. Git, SVN, Mercurial, ClearCase, Perforce. Репозиторий нужен не только для хранения, распространения кодовой базы среди разработчиков, но и в случае поломки сборок репозиторий позволит откатиться в истории на прежние версии кода, когда все было относительно хорошо. Можно восстановить случайно удаленные файлы. Репозиторий позволяет распределить работу среди нескольких вкладчиков. Контроль версий запоминает все шаги. С репозиторием намного спокойнее работать.  

Плохие примеры когда код в компании передают через DropBox, USB-Flash(ку) или архивом в электронном письме. В этом случае нет никаких гарантий, что у каждого разработчика та же версия, что у остальных.

2. Код-генерация

В firmware проектах часто много повторяющегося кода. Это синтаксический разбор содержимого payload бинарных пакетов (например CAN, RS485 и пр.). Синтаксический разбор регистров каких-н умных навороченных периферийных SPI, I2C, MDIO микросхем (драйверы сенсорных экранов, внешние ADC, трансиверы, драйверы исполнительных механизмов, интеллектуальное управление питанием и пр.). Для автоматизации написания кода синтаксического разбора можно прибегнуть к созданию простых консольных утилит код-генераторов. На основе текстовых файликов структуры пакета при помощи код генераторов можно мгновенно сформировать огромные *.c *.h файлы. Код генератор повысит гибкость проекта, уменьшит вероятность ошибки, ускорит внесение изменений.

3. Проект должен собираться скриптами

Многие IDE (IAR, Code Composer Studio) могут запускать сборки из командной строки Windows, просто запустив *.bat скрипт. Запускать сборки со скриптов полезно еще и по той причине, что окна GUI(ни) в IDE IAR часто зависают.

Классический ежедневный пример зависания Code Composer Studio
Классический ежедневный пример зависания Code Composer Studio

А в окно log(а) сборки в CCS не помещается весь текст 6 минут работы компилятора и теряются первые сообщения о критических предупреждениях. Если вы собираете проект из скриптов, то у вас останется log файл компилятора и вы сможете проанализировать все сообщения и исправить их.

4. Сборок должно быть много

Чтобы создать хорошую модульную кодовую базу с полной изоляцией компонентов надо собирать проект по частям. Подобно тому как в математике интегрируют по частям. Например если это IoT устройство, то надо подготовить сборку только с GNSS, сборку только с LTE модемом, сборку для проверки качества пайки платы, загрузчик, приложение, сборка с тестами. Также полезно сделать сборку для какого-н другого микроконтроллера (ESP32, STM, TI, AVR). Это даст гарантию, что код переносимый. Если каждая сборка собирается без ошибок, то это значит, что код достаточно модульный.

5. Проект собирать Make файлами

Когда Make файлы являются для вас исходниками, то вы можете делать супер модульный код. Буквально одной строчкой в *.mk файле добавлять и исключать компоненты из сборок. Если же вы привыкли пользоваться IDE, то вам для добавления одного компонента придется в одной вкладке IDE добавить пути к include(ам) в другом окне добывать переменные препроцессора, в третьем окне IDE добавлять сами *.с файлики и так для всех 55 сборок. И это все мышковозня. В Make файлах это будет 1 строка.

IDE хороши в основном для прототипирования. Разработчики, которые пользуются только IDE не понимают какой путь проходит код от написания до попадания в Flash. Не догадываются даже о существовании файлов с расширениями *.mk,*.a, *.opt, *.so, *.dot, *.i, *.asm, *.o, *.icf, *.ld, *.cmd, *.elf, *.out, и прочее. Хотя все эти файлы мелькают в workspace директории.

В промышленном подходе к разработке надо писать Make *.mk файлы вручную и подвергать их версионному контролю.
https://habr.com/ru/articles/723054/

6. Статические анализаторы

После компиляции код следует подвергать статическому анализу. Можно воспользоваться бесплатным CppCheck. Это позволит выявить и исправить еще некоторые критические ошибки.

7. Автосборки

Можно клонировать код из репозитория и выяснить, что он уже как полгода не собирается и никто об этом не догадывался так как код собирался только локально на DeskTop(е) разработчика. Забыли подвергнуть версионному контролю какие-то файлики.

Кодовая база в репозитории должна быть валидной каждый день. То есть сборки должны собираться без ошибок и без предупреждений компилятора из кода, что в репозитории. Кто за этим будет следить? Когда есть репозиторий и скрипты сборки можно автоматизировать запуск сборок при помощи бесплатной программы Jenkins. Это утилита с Web интерфейсом, которая запускает скрипты. Когда работает Jenkins, то можно не только удостовериться, что код синтаксически правильный, но и всегда каждый день брать свежие артефакты. Там есть удобная навигация и сортировка по категориям Job(ов). Можно даже открыть доступ Jenkins(у) клиентам продукта и они не будут беспокоить разработчиков вопросами, где же нам взять прошивку. Клиенты сами смогут взять ту прошивку, которая им нужна из Jenkins.

8. Сервер сборки

Настроить Jenkins это весьма кропотливая работа и много мышковозни. Запускать CI на каждом компьютере каждого разработчика это еще и бессмысленная повторная работа. Плюс нагрузка LapTop(а), лишний шум во время работы от кулера. Но это достаточно сделать 1 раз для всех разработчиков. Нужен какой-то общий компьютер. Можно задействовать дешевенький Win(довый) NetTop PC (Зомбик). Запустить на нем Jenkins и оставить работать 24/7. За ночь он соберет все сборки. Когда кому-то понадобился артефакт, то он подключается по Win Remote Desktop Connection или TeamViewer к зомбику и скачивает себе артефакт, посмотрит все ли в порядке с остальными сборками и в случае поломки сделает коммиты, чтобы починить код.

https://habr.com/ru/articles/695978/

9. Модульные тесты (скрепы)

То что код собирается в репе это еще ни о чем не говорит. Код может собираться без единого предупреждения, а при загрузке на target плата будет бесконечно Reset(тся). Код должен корректно стартовать и исполняться. Как это проверить автоматически? Это можно сделать при помощи модульных тестов. Модульные тесты это просто функции, которые запускают другие функции и проверяют output. Должна быть сборка для тестирования программы изнутри (методом белого ящика). В идеале надо тестировать все нетривиальные функции. В каждом firmware проекте есть hardware зависимый  код и hardware независимый код (математика, строки, абстрактные структуры данных). Часть кода, который не зависит от железа можно собирать, запускать и тестировать прямо на x86-64. Памяти на PC много  и все тесты поместятся. В Jenkins должен быть отдельный Job для запуска тестов на PC.

Если же в MCU не хватает достаточно NorFlash памяти для сборки проекта с модульными тестами, то можно задействовать отладочную плату с чипом того же семейства но с большим объёмом NorFlash. Подключив нужную периферию перемычками получится прототип тестируемого устройства.
https://habr.com/ru/articles/698092/

10. Hardware In The Loop (HIL) стенд 

Остаются аппаратно-зависимые тесты. Их надо запускать и выполнять прямо на target(е). Чтобы это автоматизировать надо минимум 3 вещи. Устройство, загрузчик и CLI. Соединив Target c NetTop компьютером по UART получится HIL стенд. Загрузчик позволит автоматически обновлять прошивку по тому же UART. CLI позволит подключиться к target по UART и запустить тесты, вычитать лог и сохранить отчет. Все это можно упаковать в отдельные Job(ы) на Jenkins. 

11. Code Coverage (advanсed)

Как понять, что составлено достаточно модульных тестов? Может случится, что какие-то строки протестированы 100 раз а другие ни разу. Ответить на этот вопрос можно только если как-то считать по каким строкам код прошил во время тестов, а какой код является недостижимым. Для этого есть специальные проприетарные Tool(ы) например Testwell CTC++.  

  1. Ежедневные планерки

Когда несколько разработчиков делают одну кодовую базу надо как-то координировать действия, переоценивать трудоемкость задач, расставлять приоритеты, сообщать от том что сделано, какие есть загвоздки и что каждый собирается делать. Для этого надо собираться каждый день в первой половина на 5...7 минут и устно проговаривать. Так можно исключить ситуации, когда одно и то же сделано несколько раз каждым разработчиком.

Еще раз хочу отметить, что все перечисленные 12 DevOps атрибутов всего на всего плоды моей фантазии. И если кто-то увидит в этом какие-то корреляции с реальностью, то это всего лишь совпадение.

Эпилог

При налаженном DevOps можно организовать полностью удаленную работу даже для процесса разработки Firmware. Разработчику достаточно делать коммиты в репозиторий и анализировать Job(ы) Jenkins(а) и изредка подключаться к HIL стенду. В теории не обязательно даже локально устанавливать ToolChain, ничего кроме своего любимого текстового редактора и браузера. Так 1 человек может контролировать до 20 сборок. Надеюсь этот текст поможет кому-нибудь автоматизировать свои проекты. Если есть дополнения, то предлагаю обсудить их в комментариях.

Links:

CI/CD прошивок для микроконтроллеров в Wiren Board (Начало на 25:50)
https://www.youtube.com/watch?v=HEEVxZ4rBCo&t=366s

Конвеерум #30: Эволюция рабочего окружения для embedded разработки
https://www.youtube.com/watch?v=vmuO4bHjTSo&list=WL&index=1

https://www.youtube.com/watch?v=vmuO4bHjTSo&t=12s

17 атрибутов хорошей PCB
https://habr.com/ru/post/655879/

9 атрибутов хорошего firmware
https://habr.com/ru/post/655641/

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы используете в работе Jenkins?
22.73% да20
77.27% нет68
Проголосовали 88 пользователей. Воздержались 14 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы строите HIL стенды?
36.59% да30
63.41% нет52
Проголосовали 82 пользователя. Воздержались 14 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собираете проект из-под IDE?
55.32% да52
44.68% нет42
Проголосовали 94 пользователя. Воздержались 12 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы умеете делать Code Coverage прошивок?
23.53% да20
76.47% нет65
Проголосовали 85 пользователей. Воздержались 13 пользователей.
Теги:
Хабы:
+6
Комментарии36

Публикации

Изменить настройки темы

Истории

Работа

Программист С
49 вакансий
DevOps инженер
45 вакансий

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн