Add Uart trait, implement it for nrf.
This commit is contained in:
parent
1d53985abe
commit
0ab88ea279
@ -10,6 +10,7 @@ use cortex_m_rt::entry;
|
|||||||
use defmt::panic;
|
use defmt::panic;
|
||||||
use embassy::executor::{task, Executor};
|
use embassy::executor::{task, Executor};
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
|
use embassy::uart::Uart;
|
||||||
use embassy::util::Forever;
|
use embassy::util::Forever;
|
||||||
use embassy_nrf::{interrupt, pac, rtc, uarte};
|
use embassy_nrf::{interrupt, pac, rtc, uarte};
|
||||||
use futures::future::{select, Either};
|
use futures::future::{select, Either};
|
||||||
@ -24,7 +25,7 @@ async fn run(mut uart: uarte::Uarte<pac::UARTE0>) {
|
|||||||
let mut buf = [0; 8];
|
let mut buf = [0; 8];
|
||||||
buf.copy_from_slice(b"Hello!\r\n");
|
buf.copy_from_slice(b"Hello!\r\n");
|
||||||
|
|
||||||
uart.send(&buf).await;
|
unwrap!(uart.send(&buf).await);
|
||||||
info!("wrote hello in uart!");
|
info!("wrote hello in uart!");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -54,7 +55,7 @@ async fn run(mut uart: uarte::Uarte<pac::UARTE0>) {
|
|||||||
info!("read done, got {:[u8]}", received);
|
info!("read done, got {:[u8]}", received);
|
||||||
|
|
||||||
// Echo back received data
|
// Echo back received data
|
||||||
uart.send(received).await;
|
unwrap!(uart.send(received).await);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,51 +139,10 @@ where
|
|||||||
self.instance.enable.write(|w| w.enable().enabled());
|
self.instance.enable.write(|w| w.enable().enabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends serial data.
|
|
||||||
///
|
|
||||||
/// `tx_buffer` is marked as static as per `embedded-dma` requirements.
|
|
||||||
/// It it safe to use a buffer with a non static lifetime if memory is not
|
|
||||||
/// reused until the future has finished.
|
|
||||||
pub fn send<'a>(&'a mut self, tx_buffer: &'a [u8]) -> SendFuture<'a, T> {
|
|
||||||
// Panic if TX is running which can happen if the user has called
|
|
||||||
// `mem::forget()` on a previous future after polling it once.
|
|
||||||
assert!(!self.tx_started());
|
|
||||||
|
|
||||||
self.enable();
|
|
||||||
|
|
||||||
SendFuture {
|
|
||||||
uarte: self,
|
|
||||||
buf: tx_buffer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tx_started(&self) -> bool {
|
fn tx_started(&self) -> bool {
|
||||||
self.instance.events_txstarted.read().bits() != 0
|
self.instance.events_txstarted.read().bits() != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receives serial data.
|
|
||||||
///
|
|
||||||
/// The future is pending until the buffer is completely filled.
|
|
||||||
/// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel
|
|
||||||
/// unfinished transfers after a timeout to prevent lockup when no more data
|
|
||||||
/// is incoming.
|
|
||||||
///
|
|
||||||
/// `rx_buffer` is marked as static as per `embedded-dma` requirements.
|
|
||||||
/// It it safe to use a buffer with a non static lifetime if memory is not
|
|
||||||
/// reused until the future has finished.
|
|
||||||
pub fn receive<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> ReceiveFuture<'a, T> {
|
|
||||||
// Panic if RX is running which can happen if the user has called
|
|
||||||
// `mem::forget()` on a previous future after polling it once.
|
|
||||||
assert!(!self.rx_started());
|
|
||||||
|
|
||||||
self.enable();
|
|
||||||
|
|
||||||
ReceiveFuture {
|
|
||||||
uarte: self,
|
|
||||||
buf: rx_buffer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rx_started(&self) -> bool {
|
fn rx_started(&self) -> bool {
|
||||||
self.instance.events_rxstarted.read().bits() != 0
|
self.instance.events_rxstarted.read().bits() != 0
|
||||||
}
|
}
|
||||||
@ -231,6 +190,52 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> embassy::uart::Uart for Uarte<T> {
|
||||||
|
type ReceiveFuture<'a> = ReceiveFuture<'a, T>;
|
||||||
|
type SendFuture<'a> = SendFuture<'a, T>;
|
||||||
|
|
||||||
|
/// Sends serial data.
|
||||||
|
///
|
||||||
|
/// `tx_buffer` is marked as static as per `embedded-dma` requirements.
|
||||||
|
/// It it safe to use a buffer with a non static lifetime if memory is not
|
||||||
|
/// reused until the future has finished.
|
||||||
|
fn send<'a>(&'a mut self, tx_buffer: &'a [u8]) -> SendFuture<'a, T> {
|
||||||
|
// Panic if TX is running which can happen if the user has called
|
||||||
|
// `mem::forget()` on a previous future after polling it once.
|
||||||
|
assert!(!self.tx_started());
|
||||||
|
|
||||||
|
self.enable();
|
||||||
|
|
||||||
|
SendFuture {
|
||||||
|
uarte: self,
|
||||||
|
buf: tx_buffer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Receives serial data.
|
||||||
|
///
|
||||||
|
/// The future is pending until the buffer is completely filled.
|
||||||
|
/// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel
|
||||||
|
/// unfinished transfers after a timeout to prevent lockup when no more data
|
||||||
|
/// is incoming.
|
||||||
|
///
|
||||||
|
/// `rx_buffer` is marked as static as per `embedded-dma` requirements.
|
||||||
|
/// It it safe to use a buffer with a non static lifetime if memory is not
|
||||||
|
/// reused until the future has finished.
|
||||||
|
fn receive<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> ReceiveFuture<'a, T> {
|
||||||
|
// Panic if RX is running which can happen if the user has called
|
||||||
|
// `mem::forget()` on a previous future after polling it once.
|
||||||
|
assert!(!self.rx_started());
|
||||||
|
|
||||||
|
self.enable();
|
||||||
|
|
||||||
|
ReceiveFuture {
|
||||||
|
uarte: self,
|
||||||
|
buf: rx_buffer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Future for the [`Uarte::send()`] method.
|
/// Future for the [`Uarte::send()`] method.
|
||||||
pub struct SendFuture<'a, T>
|
pub struct SendFuture<'a, T>
|
||||||
where
|
where
|
||||||
@ -263,9 +268,9 @@ impl<'a, T> Future for SendFuture<'a, T>
|
|||||||
where
|
where
|
||||||
T: Instance,
|
T: Instance,
|
||||||
{
|
{
|
||||||
type Output = ();
|
type Output = Result<(), embassy::uart::Error>;
|
||||||
|
|
||||||
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
|
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
|
let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
|
||||||
|
|
||||||
if !uarte.tx_started() {
|
if !uarte.tx_started() {
|
||||||
@ -289,7 +294,7 @@ where
|
|||||||
uarte.tasks_starttx.write(|w| unsafe { w.bits(1) });
|
uarte.tasks_starttx.write(|w| unsafe { w.bits(1) });
|
||||||
}
|
}
|
||||||
|
|
||||||
T::state().tx_done.poll_wait(cx)
|
T::state().tx_done.poll_wait(cx).map(|()| Ok(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,7 +329,7 @@ impl<'a, T> Future for ReceiveFuture<'a, T>
|
|||||||
where
|
where
|
||||||
T: Instance,
|
T: Instance,
|
||||||
{
|
{
|
||||||
type Output = ();
|
type Output = Result<(), embassy::uart::Error>;
|
||||||
|
|
||||||
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
|
let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
|
||||||
@ -349,7 +354,7 @@ where
|
|||||||
uarte.tasks_startrx.write(|w| unsafe { w.bits(1) });
|
uarte.tasks_startrx.write(|w| unsafe { w.bits(1) });
|
||||||
}
|
}
|
||||||
|
|
||||||
T::state().rx_done.poll_wait(cx).map(|_| ())
|
T::state().rx_done.poll_wait(cx).map(|_| Ok(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +375,9 @@ mod private {
|
|||||||
pub trait Sealed {}
|
pub trait Sealed {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Instance: Deref<Target = pac::uarte0::RegisterBlock> + Sized + private::Sealed {
|
pub trait Instance:
|
||||||
|
Deref<Target = pac::uarte0::RegisterBlock> + Sized + private::Sealed + 'static
|
||||||
|
{
|
||||||
type Interrupt: OwnedInterrupt;
|
type Interrupt: OwnedInterrupt;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -12,4 +12,5 @@ pub mod interrupt;
|
|||||||
pub mod io;
|
pub mod io;
|
||||||
pub mod rand;
|
pub mod rand;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
|
pub mod uart;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
15
embassy/src/uart.rs
Normal file
15
embassy/src/uart.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use core::future::Future;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum Error {
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Uart {
|
||||||
|
type ReceiveFuture<'a>: Future<Output = Result<(), Error>>;
|
||||||
|
type SendFuture<'a>: Future<Output = Result<(), Error>>;
|
||||||
|
fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a>;
|
||||||
|
fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a>;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user