The CPU core has "peripherals" allowing it to communicate with the external world.
For example: a serial port (UART)
// Configure buffer for reads, using DMA
let mut buf = [0u8; 8];
p.UARTE0.rxd.ptr.write(|w| unsafe { w.bits(buf.as_mut_ptr() as _) });
p.UARTE0.rxd.maxcnt.write(|w| unsafe { w.bits(buf.len() as _) });
// Start read
p.UARTE0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
// Wait for read to finish.
while !p.UARTE0.events_endrx.read().events_endrx().bit() {}
info!("Read done, got {:02x}", buf);
Peripherals can signal an "interrupt" to the core, which:
Similar to a thread, but more like Unix signals.
Requires Send/Sync.
// Enable interrupt
p.UARTE0.intenset.write(|w| w.endrx().set_bit());
NVIC::unmask(nrf52840_pac::Interrupt::UARTE0_UART0);
// Start read
p.UARTE0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
// Sleep in low-power mode, with Wait For Interrupt
loop { cortex_m::asm::wfi(); }
static mut BUF: [u8; 8] = [0; 8];
#[interrupt]
fn UARTE0_UART0() {
let p = unsafe { nrf52840_pac::Peripherals::steal() };
if p.UARTE0.events_endrx.read().events_endrx().bit() {
p.UARTE0.events_endrx.reset();
info!("Read done, got {:02x}", unsafe { BUF });
}
}
static
and Send/Sync
.std
ports of varying quality and maintainednessstatic UART_WAKER: AtomicWaker = AtomicWaker::new();
struct UartFuture;
impl Future for UartFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
UART_WAKER.register(cx.waker());
let p = unsafe { nrf52840_pac::Peripherals::steal() };
if p.UARTE0.events_endrx.read().events_endrx().bit() {
Poll::Ready(())
} else {
Poll::Pending
}
}
}
#[interrupt]
fn UARTE0_UART0() {
let p = unsafe { nrf52840_pac::Peripherals::steal() };
if p.UARTE0.events_endrx.read().events_endrx().bit() {
p.UARTE0.intenclr.write(|w| w.endrx().set_bit());
UART_WAKER.wake();
}
}
// Start read
p.UARTE0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
// Wait for read done.
UartFuture.await;
info!("Read done, got {:02x}", buf);
#[embassy::main]
async fn main(_spawner: Spawner, p: embassy_nrf::Peripherals) -> ! {
let irq = interrupt::take!(UARTE0_UART0);
let mut uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, Default::default());
let mut buf = [0u8; 8];
match with_timeout(Duration::from_secs(1),
uart.read(&mut buf)).await {
Ok(_) => info!("Read done, got {:02x}", buf),
Err(_) => info!("Timeout!"),
}
}
static
, no Send
/Sync
.join
, select
, with_timeout
.static
s.type_alias_impl_trait
, nightly-onlyasync-trait
not usable, it needs alloc (Box<dyn Future>
)io_uring
Leak
auto trait