Компиляция для микроконтроллера
Теперь поговорим о встраиваемых системах. Компиляция Rust-кода для микроконтроллера работает немного иначе, чем на обычных настольных системах. Микроконтроллеры обычно не запускают полноценную операционную систему вроде Linux или Windows. Вместо этого они работают в минимальном окружении, часто вообще без ОС. Такое окружение называется bare-metal, то есть «голое железо».
Rust поддерживает такой режим через no_std. В обычных программах на Rust стандартная библиотека (std) отвечает за файловые системы, потоки, выделение памяти в куче и ввод-вывод. Но ничего этого нет на bare-metal микроконтроллере. Поэтому вместо std мы используем значительно меньшую библиотеку core, которая предоставляет только базовые строительные блоки.
ESP32 и std
Интересный момент: ESP32 действительно может работать со std, но только если использовать официальный фреймворк ESP-IDF. ESP-IDF предоставляет возможности, похожие на ОС, и благодаря этому на ESP32 можно использовать код на Rust, основанный на std.
В этой книге мы не будем использовать std. Мы сосредоточимся исключительно на bare-metal подходе с no_std.
Target triple для ESP32
Чтобы скомпилировать Rust-код для микроконтроллера, нужно указать особую цель (target). Для bare-metal разработки под ESP32 target triple выглядит так:
xtensa-esp32-none-elf
Разберём его по частям:
- Архитектура (xtensa): ESP32 основан на архитектуре Xtensa, а не ARM или x86.
- Вендор (esp32): указывает на конкретное семейство чипов от Espressif.
- ОС (none): сообщает Rust, что операционная система не используется, то есть это bare-metal.
- Формат (elf): эта четвёртая часть важна. Во многих целях четвёртый элемент — это ABI (например,
gnuилиmsvc). Но здесь это не ABI, а формат объектных файлов. Это ELF (Executable and Linkable Format), который часто используется во встраиваемых системах.
Постойте… Вы можете спросить: мы же ни разу не использовали команду rustup target add для ESP32! Так получилось потому, что об этом позаботился инструмент espup. Мы уже настроили его в разделе о среде разработки. Дело в том, что добавить target ESP32 обычной командой rustup нельзя. Вместо этого espup устанавливает отдельный тулчейн Rust с именем «esp» (или любым другим именем, которое вы выберете), и в этом тулчейне уже есть поддержка target ESP32.
Конфигурация Cargo
В быстром старте вы могли заметить, что мы ни разу не передавали флаг --target при запуске cargo. Откуда же Cargo знал, для какой цели собирать? Дело в том, что target уже был задан в файле .cargo/config.toml.
Этот файл позволяет хранить настройки, связанные с cargo, включая цель сборки по умолчанию. Чтобы настроить его для ESP32, создайте папку .cargo в корне проекта и добавьте в неё файл config.toml со следующим содержимым:
[build]
target = "xtensa-esp32-none-elf"
Теперь не нужно передавать --target каждый раз: Cargo будет использовать эту настройку автоматически.