Под капотом бейджа OFFZONE

Под капотом бейджа OFFZONE


Железо

Сердце бейджа — STM32F103, известный, популярный и доступный микроконтроллер ARM-архитектуры с нативной поддержкой USB и достаточным для наших нужд объемом памяти.

Прошивка

Это коллективный труд Лабы и волонтеров OFFZONE. Прошивкой занимаются люди с разным опытом разработки под микроконтроллеры и вовсе без него. Наиболее важная задача — подобрать такой тулчейн или IDE, чтобы им было удобно пользоваться всем участникам процесса. И отдельная задача — смержить в одну прошивку полдюжины тасков, написанных разными людьми, и при этом не поломать базовую функциональность бейджа.

Существует несколько способов разработки прошивки под STM32. Они отличаются уровнем абстракции кода от железа, из-за чего имеют разный порог входа для разработчика. За всю историю бейджа мы перепробовали, пожалуй, все из них, кроме чистого ассемблера: Arduino IDE, STD_Periph_Lib от STmicroelectronics и HAL (hardware abstraction layer) от них же. И в итоге остановились на варианте с использованием библиотек HAL и самописной надстройкой над ними.

Прошивка бейджа OFFZONE 2025 написана с помощью STM32CubeIDE (Eclipse в основе) и чистого C. В ней используется:

  • FreeRTOS для конкуретности задач и управления памятью;
  • HAL-библиотека USB_CDC (эмуляция COM-порта по USB);
  • HAL-функции для получения данных и управления периферией микроконтроллера;
  • STM32 X-CUBE-CRYPTOLIB (для подписей и хеш-сумм);
  • библиотека microrl для пользовательского интерфейса.

Архитектура прошивки

Чтобы прошивка не зависела от какой-то конкретной библиотеки или от самого контроллера, мы разработали специальный слой совместимости. Он предоставляет свой API разработчику. Мы назвали этот слой совместимости SAL (software abstraction layer). SAL работает как высокоуровневая обертка над платформозависимыми низкоуровневыми функциями, такими как: обработка состояния кнопок, управление светодиодами, прием-отправка данных по COM-порту и все, что может понадобиться разработчику тасков на бейдже, но куда не хочется лишний раз лезть. Прототипом для SAL служил WinAPI.

Структура библиотеки SAL

В общей иерархии прошивки бейджа SAL вписался где-то между RTOS, HAL и тасками. 

Например, вот так выглядит прототип и документация для функции создания нового таска:

Те, кто программировал на WinAPI, могут заметить, что прототип этой функции похож на функцию CreateThread.

Посмотрим, как работает SAL, на примере создания таска-приложения echo. Echo читает и отправляет обратно данные, принятые по COM-порту. Все приложение — два файла.

Первый — файл-заголовок app_echo.h:

И второй — app_echo.c:

Благодаря SAL разработчик-волонтер может писать таск как самостоятельное высокоуровневое приложение, не задумываясь, как происходит чтение-запись в COM-порт, управление кнопками и другие операции с железом. А ответственный за сборку финальной прошивки может интегрировать таск в релизную сборку одной строкой, без каких либо физических и ментальных мук. Выглядеть это будет примерно так:

С этого момента SAL и FreeRTOS берут таск под свое крыло и сами контролируют распределение ресурсов микроконтроллера.

SAL — это большая библиотека, реализующая множество функций. Но самым интересным элементом в ней стала подсистема IPC (inter-process communication), для которой в SAL был реализован такой механизм межпроцессорного взаимодействия, как  PIPE (канал). В него можно писать данные в одном таске и читать их в другом. Каналы были реализованы на основе типа данных streambuffer из FreeRTOS. Однако у этого типа данных не было одной очень важной для IO API функции — инвалидации, т. е. удаления устаревших или неактуальных данных.

Могло произойти так, что канал «протухал», например в функции чтения данных из COM-порта. И эта функция тормозила исполнение программы до тех пор, пока не вычитывала столько данных, сколько ей было нужно, если не был указан дополнительный флаг, например O_NONBLOCK.

На практике это проявлялось так: если пользователь отключал USB от бейджа, функции read необходимо было прерваться и вернуть ошибку. Однако, используя чистый streambuffer из FreeRTOS, сделать это было невозможно, и функция read висела, ожидая приема недостающих данных. Поэтому в SAL пришлось добавлять примитивы для самостоятельного отслеживания таких ситуаций, а это оказалось непросто.

Итог

Одной из ключевых трудностей была коллективная разработка прошивки для микроконтроллера. Чтобы решить это проблему, создали общий для разработчиков инструмент, SAL. Все волонтеры-разработчики тасков получили одно универсальное и хорошо документированное средство взаимодействия с ресурсами микроконтроллера. Так мы сняли головную боль низкоуровневой разработки и облегчили интеграцию всех тасков в одну релизную прошивку. Кроме того, благодаря SAL удалось упростить механизм миграции на другие микроконтроллеры, что однозначно пригодится в будущем. Новый микроконтролер → больше ресурсов → больше тасков и интерактива!


Report Page