Переносимость
(Этот раздел необязательный. Можете смело перейти к следующему разделу, где мы немного почистим код и на этом закончим.)
Возможно, вы задаётесь вопросом, стоит ли вся эта продвинутая экосистема своих усилий. Настройка нашей мигалки довольно замысловата и использует много крейтов и возможностей Rust для такой простой задачи.
Но у этого есть и приятный плюс: наш код становится по-настоящему переносимым. На другой плате настройка может отличаться, но сам цикл мигалки будет точно таким же!
Посмотрим на мигалку для Sipeed Longan Nano. Это небольшая плата примерно за 5 долларов, которая, как и MB2, является встраиваемой платой с MCU. А во всём остальном она совершенно другая: другой процессор (GD32VF103 с системой команд RISC-V, совсем не похожей на Arm, которую используем мы), другая периферия, другая плата. Но к ней подключён светодиод через GPIO-вывод, так что её тоже можно заставить мигать.
#![no_std]
#![no_main]
use panic_halt as _;
use riscv_rt::entry;
use gd32vf103xx_hal::{pac, prelude::*, delay::McycleDelay};
use embedded_hal::{blocking::delay::DelayMs, digital::v2::OutputPin};
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut rcu = dp.RCU.configure().ext_hf_clock(8.mhz()).sysclk(108.mhz()).freeze();
let gpioc = dp.GPIOC.split(&mut rcu);
let mut led = gpioc.pc13.into_push_pull_output();
let mut delay = McycleDelay::new(&rcu.clocks);
loop {
delay.delay_ms(500);
led.set_high().unwrap();
delay.delay_ms(500);
led.set_low().unwrap();
}
}
Различия в настройке объясняются отчасти разным железом, а отчасти тем, что этот код использует более старый HAL-крейт, который ещё не обновлён под embedded-hal 1.0. Тем не менее основной цикл, как и обещано, идентичен, а остальной код довольно узнаваем. Благодаря переносимости, которую дают простая кросс-компиляция Rust и экосистема встраиваемого Rust, мигалка остаётся мигалкой.
Полный рабочий пример nanoblinky есть на GitHub: если хотите увидеть все детали или даже купить собственную плату и попробовать самостоятельно — пожалуйста.