Вокруг языка программирования Rust много шумихи, и я вижу, как его внедряют в различных проектах, не в последнюю очередь в ядре Linux. Однако до сих пор мне было неясно, подходит ли он для разработки встраиваемого ПО, поскольку аппаратные ресурсы микроконтроллеров ограничены. Требуется малый объём памяти и хранилища, а также может быть важна оптимальная производительность, например, для снижения энергопотребления устройств с батарейным питанием.
Исследование Корнелльского университета под названием «Lessons from an Industrial Microcontroller Use Case with Ariel OS» пытается ответить на этот вопрос с помощью встраиваемых C и Rust, и вывод таков: Rust — жизнеспособный вариант.
По мере того как Rust набирает обороты в разработке более безопасного системного ПО, необходима проверка реальностью сегмента микроконтроллерного оборудования. Насколько экосистема Rust готова к этому сегменту? Может ли Rust на практике конкурировать с C?
В этой статье сообщается об индустриальном тематическом исследовании IoT, которое помогает ответить на эти вопросы. Анализируются две команды, параллельно разрабатывающие одну и ту же функциональность (одна на C, другая на Rust) в течение нескольких месяцев. Приводится сравнительный анализ их подходов, результатов и итеративных усилий. Анализ и измерения на оборудовании не дают веских оснований предпочесть C вместо Rust для прошивок микроконтроллеров по критериям объёма памяти или скорости выполнения.
Кроме того, показано, что Ariel OS обеспечивает эффективную и переносимую системную среду выполнения на Rust, размер которой меньше, чем у современного стека bare-metal C, традиционно используемого в этом контексте. Делается вывод, что Rust сегодня является разумным выбором для разработки прошивок в этой области.
Но не будем принимать вывод как данность, ознакомимся с исследованием (PDF) чтобы лучше понять метод и результаты.
Использовалось оборудование: отладочный набор SensorTile.box Pro с микроконтроллером STMicro STM32U585AI Arm Cortex-M33, BLE и NFC (здесь не использовались), 6-осевым IMU LSM6DSV16X3, а пакет ST AIoT Craft Edge AI Suite обеспечивал обработку захваченных данных с сенсора с помощью ИИ.
Отладочный набор запускает прошивку Vanilla Data Logger (VDL), написанную на C или Rust, и взаимодействует с ПК, на котором работает GUI, по протоколу Vanilla Datalog Protocol (VDP) через интерфейс UART.
Каждая команда работала независимо в течение шести недель на этапе 1 реализации прошивки VDL на C и Rust, а затем сотрудничала ещё четыре недели для оптимизации работы друг друга. Реализация на C опирается на STM32CubeMX, конечный автомат (FSM), написанный на голом C, и открытую библиотеку Parson для де/сериализации JSON (примечание: использует динамическое выделение памяти).

Прошивка на Rust опирается на Ariel OS — RTOS для микроконтроллеров на Rust , и реализует сериализацию/десериализацию JSON с помощью крейта serde , предоставляющего фреймворк для сериализации/десериализации, и крейта heapless для статического выделения памяти.

Поскольку архитектуры довольно разные, это не будет прямым сравнением C и Rust, но вот итоговые результаты по объёму памяти и хранилища.
| Metric (bytes) | VDL-C | VDL-Rust | Δ (Rust − C) |
|---|---|---|---|
| .text | 66,240 | 69,764 | 3,524 |
| Total ROM | 76,744 | 84,100 | 7,356 |
| Stack RAM | 2,048 | 10,240 | 8,192 |
| Static RAM | 14,960 | 14,400 | -560 |
| Heap RAM | 25,600 | 0 | -25,600 |
| Total RAM | 44,656 | 24,640 | -20,016 |
Оба бинарных файла прошивки VDL довольно малы, но прошивка на C всё же меньше, чем на Rust. Здесь это не имеет большого значения, так как STM32U585AI имеет 2 МБ флеш-памяти, но может быть важно, если мы приблизимся к пределу хранилища на ещё более ресурсоограниченных МК, и потребуется либо дополнительная оптимизация, либо переход на другой компонент. Сравнение ОЗУ сложнее из-за динамического выделения памяти, которое требует кучи для реализации на C. Показанное число — это максимальный замеренный пик использования кучи. Также отмечается, что «существуют менее затратные по памяти варианты, вообще не требующие кучи» по сравнению с библиотекой Parson, поскольку оптимизация памяти не была основной целью.

Обе прошивки, на Rust и на C, в итоге работали с одинаковым уровнем производительности, измеряемым по частоте выходных данных (ODR): 7468 Гц. Диаграмма ниже показывает, что независимо от того, выберете ли вы C или Rust для своего следующего встраиваемого проекта, прошивка не станет автоматически оптимизированной по размеру и/или производительности без серьёзной работы.

Реализация на Rust была вдвое быстрее реализации на C во время первого теста, а затем C и Rust по очереди занимали первое место после оптимизаций, которые включали тривиальные изменения, такие как отключение логирования (для отладки) и включение кэша инструкций и упреждающей выборки из флеш-памяти для снижения задержки I2C. Подробнее о тонкостях и подводных камнях можно узнать из полного PDF.
Интересно, что на втором этапе каждая команда помогла другой создать лучшую прошивку, сравнивая прошивки на C и Rust. Теоретически лучше всего выбрать и C, и Rust для вашего следующего продукта, но на практике это вряд ли сработает из-за бюджетных ограничений. Исходный код проекта будет опубликован на STM32 Hotspot .
Выражаем свою благодарность источнику, с которого взята и переведена статья, сайту cnx-software.com.
Оригинал статьи вы можете прочитать здесь.


