Rust ESP FAQ |
![]() |
Добавил(а) microsin |
Описание решения различных вопросов, касающихся программирования микроконтроллеров Espressif на языке Rust. Следующий код выдает предупреждение на неиспользуемую переменную i (warning: unused variable: `i`): for i in 0..256 { Переменная i на самом деле не используется. Есть несколько способов устранить это предупреждение: Способ 1: использовать префикс нижнего подчеркивания (conventional-конструкция Rust). for _i in 0..256 { Способ 2: использовать вместо имени переменной символ подчеркивания (наиболее часто используемый метод для таких случаев). for _ in 0..256 { Способ 3: использовать итератор range (функциональный стиль). (0..256).for_each(|_| { Рекомендация: используйте Способ 2 (просто _), поскольку это самый идиоматический метод Rust, когда вам в теле цикла не нужна переменная счетчика. Нижнее подчеркивание говорит компилятору, что вы намеренно не используете эту переменную, что подавит вывод соответствующего предупреждения. Вызываемая функция или метод возвращает значение, которое в коде не проверяется. Компилятор считает это неправильным, и генерирует соответствующее предупреждение. warning: unused `Result` that must be used --> src/bin/main.rs:201:5 | 137 | spawner.spawn(adc_task(peripherals.GPIO3, peripherals.ADC1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this `Result` may be an `Err` variant, which should be handled = note: `#[warn(unused_must_use)]` on by default help: use `let _ = ...` to ignore the resulting value | 137 | let _ = spawner.spawn(adc_task(peripherals.GPIO3, peripherals.ADC1)); | +++++++ В этом предупреждении сразу дается совет, как его устранить: с помощью оператора let выполните присвоение возвращаемого результата функции временной переменной _: let _ = spawner.spawn(adc_task(peripherals.GPIO3, peripherals.ADC1)); Разделение кода приложения на отдельные файлы (модули кода) помогает в логической организации функционала вашего приложения, делая код понятнее и удобнее для поддержки. Это становится особенно важным по мере разрастания проекта. Пошаговое руководство по добавлению модуля кода в приложение Rus: [Шаг 1: создание файловой структуры для модуля] Вариант A: модуль с одним файлом your_project/ Вариант B: модуль из нескольких файлов (директория) your_project/ [Шаг 2: написание кода модуля] Для одиночного модуля (src/your_module.rs): // Публичные функции (доступные снаружи модуля): Для модуля директории (src/your_module/mod.rs): // src/your_module/mod.rs [Шаг 3: декларация модуля в основном файле приложения] В файле src/main.rs: // Декларация модуля (говорит для Rust искать модуль в your_module.rs [Шаг 4, опциональный: создание субмодулей] Создайте файл src/your_module/submodule.rs: pub fn submodule_function() -> &'static str { Обновите src/your_module/mod.rs для экспорта субмодуля: // src/your_module/mod.rs [Шаг 5: использование субмодулей в основной программе] В src/main.rs: mod your_module; [Шаг 6: организация нескольких модулей] Для нескольких модулей: your_project/ В главном файле приложения src/main.rs: // Декларация всех модулей: [Ключевые концепции] 1. mod module_name; - декларирует модуль (Rust ищет module_name.rs или module_name/mod.rs). 2. pub - делает элементы модуля публичными, т. е. доступными вне модуля. 3. use - импорт элементов в текущую область видимости (current scope) кода. 4. Именование файлов - имена модуля должны совпадать с именами файлов. 5. mod.rs - специальный файл, который определяет содержимое модуля, когда для модуля используется директория. [Общие шаблоны] Ре-экспорт: // В вашем your_module/mod.rs: Приватные модули: // Модули без 'pub' являются приватными для своего родительского модуля: Для устранения этой ошибки добавьте в модуль директиву компилятора #![no_main]: #![no_std] Ошибка компиляции в модуле Rust "error: #[panic_handler] function required, but not found" возникает обычно в ситуации, когда выполняется сборка проекта Rust, линкуемого без использования стандартной библиотеки (например это no_std проект). В таких условиях обработчик паники (panic handler) стандартной библиотеки недоступен, вы должны предоставить свой собственный обработчик. В случае no_std рабочего окружения, когда вы собираете приложение микроконтроллера (embedded system), ядро операционной системы (operating system kernel) или работаете с другим окружением, где стандартная библиотека Rust недоступна, вы используете атрибут #![no_std] в своем файле main.rs или lib.rs. Panic Handling. На языке Rust термин "panic" (паника) означает невосстановимую ошибку, обозначающую серьезную проблему в состоянии программы. Когда возникает паника в no_std окружении, компилятор Rust нуждается в специально выделенной функции для обработки этой ситуации, поскольку panic handler стандартной библиотеки отсутствует. #[panic_handler]
Этот атрибут помечает функцию как выделенный panic handler вашей no_std-программы. Чтобы устранить ошибку "`#[panic_handler]` function required, but not found", вам нужно определить функцию с атрибутом #[panic_handler] в крейте, где применен атрибут #![no_std]. Обычная минимальная реализация запускает пустой бесконечный цикл, попадание в который эффективно подвешивает выполнение при возникновении паники. Более сложные реализации подразумевают вывод в лог осмысленных сообщений, описывающих ошибку. Пример (в main.rs или lib.rs): use core::panic::PanicInfo; [Дополнительные замечания] 1. panic = "abort": для приложений no_std часто рекомендуется конфигурировать ваш файл Cargo.toml для настройки стратегии паники "abort". Это говорит компилятору генерировать код, который обрывает обработку при возникновении паники вместо того, чтобы пытаться отмотать стек (unwind), что может не поддерживаться или не является желательным для вашего целевого рабочего окружения. # В файле Cargo.toml Custom Panic Logic: хотя простой цикл loop {} допускается как базовый panic handler, вы можете реализовать более продвинутую логику, в которой функция паники обработает ситуацию сбоя с учетом специфики вашего приложения (например выведет в лог сообщения об ошибке, показывающие информацию диагностики, или инициирует system reset). Предоставлением функции #[panic_handler] и потенциальным конфигурированием panic = "abort" в файле Cargo.toml вы обеспечиваете реализацию требования для panic handler в no_std-проектах Rust и устраните ошибку "function required, but not found". Это предупреждение указывает, что функция была определена, но нигде не используется, что соответствует "мертвому коду" (dead code). Такое поведение задается lint-атрибутом #[warn(dead_code)], который по умолчанию применяется ко всем функциям, переменным или полям структур. Атрибут #[warn(dead_code)] помогает идентифицировать неиспользуемый код, что потенциально способствует устранению разрастания кода и связанных с этим потенциальных ошибок. Атрибут #[allow(dead_code)] обладает противоположным действием: он отменит это предупреждение. Пример: #[allow(dead_code)] Прошивка скомпилированной программы Rust ESP выбирается опцией runner секции [target.riscv32imc-unknown-none-elf] файла настроек .cargo/config.toml: [target.riscv32imc-unknown-none-elf] Здесь указано, что прошивка осуществляется утилитой espflash с запуском монитора после перепрошивки. Обычно утилита espflash сама найдет последовательный порт для передачи скомпилированного двоичного кода, или предложит выбрать, через какой порт прошивать. Но иногда бывают случаи, когда это необходимо указывать вручную. Это можно сделать передачей опции -p или --port: espflash flash -p /dev/ttyACM0 # Пример для Linux/macOS example
espflash flash -p COM3 # Пример для Windows
[Ссылки] 1. rustup + espup: тулчейн для Rust на платформе ESP32. |