Rust ESP32: руководство новичка |
![]() |
Добавил(а) microsin |
В этой статье (перевод [1]) приведено простое руководство по аппаратуре и программированию на платформе чипов ESP32 с использованием языка программирования Rust. В этом руководстве мы сфокусируемся на ESP32, недорогом и мощном микроконтроллере, который отлично подойдет как для новичков, так и для экспертов. Вы можете купить микроконтроллер ESP32 как часть какого-нибудь стартер-кита, на плате которого могут быть установлены различные датчики, такие как датчики температуры или освещения. [Программное обеспечение] Для ESP32 написано большое количество хорошо документированных библиотек, которые помогут вам быстро освоить программирование Rust, см. документацию по ESP-RS [3]. Мы рассмотрим шаги для настройки ESP32-программирования на Rust, от установки необходимых утилит до написания вашей первой программы. Также будут описаны решения возможных проблем, которые не всегда можно найти в официальной документации. Шаг 1: std против no_std На языке Rust существует два различных подхода к программированию: использование полностью стандартной библиотеки (опция std) или возможность использовать нестандартных библиотек (опция no_std). Понимание разницы между этими вариантами имеет решающее значение при работе со встроенными системами, где ресурсы (память и время процессора) часто ограничены. std • Библиотека std предоставляет множество функций "из коробки", такие как коллекции (например Vec), работа с файлами, сетевыми протоколами и потоками. Это ускоряет и упрощает разработку. no_std • no_std разработана для систем с очень ограниченными ресурсами, что идеально подходит для встраиваемых устройств. При разработке на Rust встраиваемых устройств, когда микроконтроллеры работают в условиях очень ограниченной оперативной памяти и без наличия операционной системы, лучшим выбором будет no_std. Этот вариант удалит функции, которые потребляют большое количество системных ресурсов, сосредоточив внимание на основном функционале, необходимом для низкоуровневого программирования. В этом руководстве мы будем использовать no_std для непосредственной работы с аппаратурой микроконтроллера ESP32. Шаг 2: установка Перед тем, как можно будет начать программировать, нам понадобится установить рабочее окружение, основанное на архитектуре вашего программируемого устройства. Чипы Espressif SoC (System on Chip, системы на чипе, другое название микроконтроллера) могут использовать различные архитектуры, такие как RISC-V и Xtensa, и процесс установки зависит от того, чип какой архитектуры вы используете. Идентификация архитектуры. Таким образом, необходимо определить, на какой архитектуре работает ваш чип ESP32. Xtensa: на этой архитектуре работают чипы ESP32 (например, ESP32-WROOM, ESP32-Ethernet-Kit и другие). RISC-V: это устройства наподобие чипа ESP32-C3 (платы ESP32-C3 SuperMini, LUATOS.COM/T/ESP32C3, LUATOS.COM/T/ESP32C3 b и другие). Чтобы узнать, к какой архитектуре относится ваше устройство, обратитесь к его документации, обычно доступной в соответствующем даташите или на сайте производителя платы. Установка тулчейна. Чтобы разрабатывать Rust-приложения на чипах Espressif SoC, нам нужно установить подходящий программный инструментарий (тулчейн). Это то место, где вступает в игру espup [2] — эта программа поможет установить и обслуживать утилиты тулчейна для вашей используемой архитектуры. Чтобы установить espup, запустите в терминале следующую команду: $ cargo install espup
Затем установите необходимые тулчейны: $ espup install
После завершения установки вы увидите сообщение наподобие следующего, где вам советуют установить некоторые переменные окружения: [info]: Installation successfully completed!
Если вы столкнетесь с ошибкой: Caused by:
process didn't exit successfully: `/tmp/cargo-installlfnEMgk/release/build
/libudev-sys-678fd6d3ec7ef9ed/build-script-build` (exit status: 101)
...
--- stderr
thread 'main' panicked at '/home/danielez/.cargo/registry/src/index.crates
.io-6f17d22bba15001f/libudev-sys-0.1.4/build.rs:38:41:
called `Result::unwrap()` on an `Err` value: "pkg-config exited with
status code 1
PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 pkg-config
--libs --cflags libudev
.. то можете её исправить запуском команды (см. https://github.com/esp-rs/espflash/issues/108): $ sudo apt-get install libudev-dev
[Создание программы на основе шаблона] Следующий шаг - создание проекта с помощью шаблона. Установите утилиту cargo-generate, которая позволит вам создать новый проект на основе существующего шаблона: $ cargo install cargo-generate
Затем сгенерируйте проект с использованием шаблона esp-template: $ cargo generate esp-rs/esp-template
Когда проект сгенерируется, откройте его (например, с помощью любой вашей среды IDE наподобие VScode, или просто перейдя в директорию проекта в терминале), и проверьте код внутри файла src/main.rs. Этот код будет выглядеть примерно так: #![no_std] Давайте разберемся что тут происходит. #![no_std]
Эта директива говорит Rust не использовать стандартную библиотеку, что часто применяется для программирования встраиваемых систем. #![no_main]
Это показывает, что обычная точка входа main в программе не используется. Вместо неё предоставляется указываемая пользователем точка входа (custom entry point), что является одним из типовых решений для встраиваемых систем. #[entry] Это определяет точку входа в программу с помощью функции main, из которой никогда не происходит возврат (-> ! указывает на дивергентную функцию). Вы также можете заметить, что строчкой use esp_hal::{ импортируется HAL. Аббревиатура HAL означает Hardware Abstraction Layer, библиотека абстракции аппаратуры, что часто используется для встраиваемых систем. let peripherals = Peripherals::take(); Эта строка получает доступ к аппаратным периферийным устройствам микроконтроллера. let system = SystemControl::new(peripherals.SYSTEM); Эта строка активирует системный контроллер, используемый системными утилитами микроконтроллера. let clocks = ClockControl::max(system.clock_control).freeze(); Это запустит системное тактирование на самой высокой частоте и блокирует это состояние. Это гарантирует, что микроконтроллер будет работать с самой высокой возможной производительностью. Блокировка (.freeze) этой настройки гарантирует, что скорость остается постоянной во время работы, поэтому не должно быть неожиданных замедлений или изменений тактирования. [Выполнение программы - Hello World] Подключите вашу платку через USB и запустите команду: $ cargo run
При первом запуске на Linux вы можете увидеть следующую ошибку: WARNING: use --release
We *strongly* recommend using release profile when building esp-hal.
The dev profile can potentially be one or more orders of magnitude
slower than release, and may cause issues with timing-senstive
peripherals and/or devices.
Эта ошибка связана с отсутствием прав доступа текущего пользователя к последовательным устройствам, что исправляется командой: $ sudo usermod -a -G dialout $USER
После того, как ваш пользователь был добавлен в группу dialout, вам нужно перелогиниться, чтобы изменения вступили в силу. Альтернативно вы можете перезагрузить свой компьютер. Ваше членство в группе dialout можно проверить командой: $ groups
Будет выведен список групп, в которые входит текущий пользователь, и в этом списке должна присутствовать группа dialout. Теперь снова попробуйте запустить команду: $ cargo run
Вы должны увидеть следующий вывод: I (31) boot: ESP-IDF v5.1-beta1-378-gea5e0ff298-dirt 2nd stage bootloader
Строка вывода в лог log::info!("Hello world!"); обычно посылает текстовое сообщение в последовательный терминал через интерфейс UART ESP32. Это сообщение в результате передается в подключенное устройство (наподобие компьютера), что дает возможность увидеть его с помощью специального программного обеспечения. [Программа, мигающая светодиодом] Большинство плат с микроконтроллером ESP32 оборудованы светодиодом (LED). Давайте попробуем им помигать. В примере, предоставленном ESP-RS, вы можете найти следующий код: #![no_std] Здесь есть две новые строки, которые поначалу могут быть непонятны: let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); Эта строка инициализирует аппаратуру периферийного устройства GPIO (General Purpose Input/Output), которая управляет вводом и выводом через ножки портов микроконтроллера. IO MUX (Input/Output multiplexer) позволяет микроконтроллеру перенаправлять различные внутренние сигналы на физические выводы корпуса чипа. let mut led = Output::new(io.pins.gpio7, Level::Low); Эта строка настраивает на вывод ножку порта GPIO7, к которой может быть подключен светодиод. Светодиод может быть подключен и к другому порту, например GPIO2, проконсультируйтесь с принципиальной схемой вашей платы. После запуска команды cargo run на плате начет мигать светодиод с периодом 1 секунда, это обеспечивает бесконечный цикл: loop { [Подключение кнопки] Теперь мы сделаем наш проект интерактивным, добавив опрос состояния кнопки. По нажатиям на кнопку мы будем зажигать и гасить светодиод. Для этого нам понадобятся: • ESP32 DEVKIT V1 Схема соединений: Код Rust: #![no_std] Мы использовали порты GPIO4 и GPIO5 для подключения светодиода (LED) и кнопки (button) соответственно. Настройка порта для опроса кнопки отражена следующей строчкой кода: let button = Input::new(io.pins.gpio4, Pull::Up); Кнопка подключена к GPIO4, и сконфигурирована как вход с верхним подтягивающим резистором (Pull::Up). Подтяжка такого типа гарантирует, что уровень порта кнопки считывается как лог. 1, если кнопка не нажата. В нажатом состоянии кнопки ножка порта замыкается на землю, и её низкий потенциал относительно GND считывается как уровень лог. 0. let mut red_led = Output::new(io.pins.gpio5, Level::Low); Порт для подключения светодиода GPIO5 сконфигурирован как выход. По умолчанию светодиод должен быть погашен, поэтому в соответствии с его подключением мы инициализируем GPIO5 в состоянии лог. 0 (Level::Low). Опрос кнопки и включение и выключение светодиода обеспечивается телом бесконечного цикла: loop { [Ссылки] 1. Introduction to Embedded Systems with Rust: A Beginner's Guide Using ESP32 site:rust-dd.com. |