Отправка одного байта
Наша первая задача — отправить один байт с микроконтроллера на компьютер по последовательному соединению.
Для этого используем следующий фрагмент (он уже есть в 11-uart/examples/send-byte.rs):
#![no_main]
#![no_std]
use cortex_m::asm::wfi;
use cortex_m_rt::entry;
use panic_rtt_target as _;
use rtt_target::rtt_init_print;
use microbit::{
hal::uarte,
hal::uarte::{Baudrate, Parity},
};
use serial_setup::UartePort;
#[entry]
fn main() -> ! {
rtt_init_print!();
let board = microbit::Board::take().unwrap();
let mut serial = {
let serial = uarte::Uarte::new(
board.UARTE0,
board.uart.into(),
Parity::EXCLUDED,
Baudrate::BAUD115200,
);
UartePort::new(serial)
};
serial.write(b'X').unwrap();
serial.flush().unwrap();
loop {
wfi();
}
}
Возможно, вы заметили, что одна из используемых здесь библиотек, модуль serial_setup, не с crates.io, а написана специально для этого проекта. Назначение serial_setup — дать удобную обёртку над периферией UARTE. Если хотите, можете посмотреть, что именно делает этот модуль, но для понимания главы в целом это не обязательно.
Далее рассмотрим инициализацию UARTE. UARTE инициализируется таким фрагментом кода:
uarte::Uarte::new(
board.UARTE0,
board.uart.into(),
Parity::EXCLUDED,
Baudrate::BAUD115200,
);
Эта функция забирает во владение представление периферии UARTE в Rust (board.UARTE0) и выводы TX/RX платы (board.uart.into()), так что никто другой не может вмешаться ни в периферию UARTE, ни в наши выводы, пока мы ими пользуемся. Затем конструктору передаются два параметра: скорость в бодах (с ней вы уже знакомы) и параметр «parity». Чётность (parity) — это способ, с помощью которого линии последовательной связи проверяют, не были ли данные повреждены при передаче. Здесь он нам не нужен, поэтому мы его просто исключаем. Затем результат оборачивается в тип UartePort, чтобы им было удобно пользоваться.
После инициализации отправляем нашу X (ASCII-код 88) через только что созданный экземпляр UART. Эти последовательные функции «блокирующие»: они ждут, пока данные будут отправлены, и только потом возвращают управление. Это не всегда то, что нужно: пока байт уходит по проводу, микроконтроллер мог бы выполнить много работы. Но в нашем случае это удобно, да и другой работы у нас всё равно нет.
И наконец, мы вызываем flush() для последовательного порта. Дело в том, что UARTE может решить буферизовать вывод, пока не накопит определённое количество байтов для отправки. Вызов flush() заставляет его немедленно записать имеющиеся байты, вместо того чтобы ждать ещё.
Проверка
Перед прошивкой убедитесь, что вы запустили minicom или PuTTY: данные, которые мы получаем через последовательную связь, никуда не сохраняются, их нужно смотреть сразу. Когда монитор порта будет запущен, прошейте программу так же, как в главе 5:
$ cargo embed --example send-byte
(...)
После завершения прошивки в терминале minicom или PuTTY должен появиться символ X. Поздравляю!
Если пропустили, можно нажать кнопку сброса на обратной стороне MB2. Программа начнёт работу сначала и снова отправит X.