素朴なアプローチと write!
素朴なアプローチ
おそらく、次のようなプログラムを思いついたでしょう(examples/naive-send-string.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::{self, 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)
};
for byte in b"The quick brown fox jumps over the lazy dog.\r\n".iter() {
serial.write(*byte).unwrap();
}
serial.flush().unwrap();
loop {
wfi();
}
}
これは完全に有効な実装ですが、いずれは引数のフォーマットなど、print! の持つ便利な
機能をすべて使いたくなるかもしれません。どうすればそれができるのか気になるなら、このまま読み進めてください。
write! と core::fmt::Write
core::fmt::Write トレイトを使うと、それを実装する任意の構造体を、std の世界で
print! を使うのと基本的に同じ方法で使えるようになります。この場合、nrf HAL の Uart
構造体は core::fmt::Write を実装しているので、先ほどのプログラムを次のようにリファクタリング
できます(examples/send-string.rs):
#![no_main]
#![no_std]
use core::fmt::Write;
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::{self, 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)
};
write!(serial, "The quick brown fox jumps over the lazy dog.\r\n").unwrap();
serial.flush().unwrap();
loop {
wfi();
}
}
このプログラムを micro:bit に書き込むと、あなたが思いついたイテレータベースのプログラムと 機能的に等価であることがわかるでしょう。