mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-27 12:20:37 +00:00
Merge pull request #4155 from marcemmers/remove-instance-from-rp-uart-type
[embassy-rp] Remove <T: Instance> from Uart and BufferedUart
This commit is contained in:
commit
f9f20ae217
@ -34,28 +34,29 @@ impl State {
|
||||
}
|
||||
|
||||
/// Buffered UART driver.
|
||||
pub struct BufferedUart<'d, T: Instance> {
|
||||
pub(crate) rx: BufferedUartRx<'d, T>,
|
||||
pub(crate) tx: BufferedUartTx<'d, T>,
|
||||
pub struct BufferedUart {
|
||||
pub(super) rx: BufferedUartRx,
|
||||
pub(super) tx: BufferedUartTx,
|
||||
}
|
||||
|
||||
/// Buffered UART RX handle.
|
||||
pub struct BufferedUartRx<'d, T: Instance> {
|
||||
pub(crate) phantom: PhantomData<&'d mut T>,
|
||||
pub struct BufferedUartRx {
|
||||
pub(super) info: &'static Info,
|
||||
pub(super) state: &'static State,
|
||||
}
|
||||
|
||||
/// Buffered UART TX handle.
|
||||
pub struct BufferedUartTx<'d, T: Instance> {
|
||||
pub(crate) phantom: PhantomData<&'d mut T>,
|
||||
pub struct BufferedUartTx {
|
||||
pub(super) info: &'static Info,
|
||||
pub(super) state: &'static State,
|
||||
}
|
||||
|
||||
pub(crate) fn init_buffers<'d, T: Instance + 'd>(
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
pub(super) fn init_buffers<'d>(
|
||||
info: &Info,
|
||||
state: &State,
|
||||
tx_buffer: Option<&'d mut [u8]>,
|
||||
rx_buffer: Option<&'d mut [u8]>,
|
||||
) {
|
||||
let state = T::buffered_state();
|
||||
|
||||
if let Some(tx_buffer) = tx_buffer {
|
||||
let len = tx_buffer.len();
|
||||
unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
|
||||
@ -76,61 +77,73 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>(
|
||||
// This means we can leave the interrupt enabled the whole time as long as
|
||||
// we clear it after it happens. The downside is that the we manually have
|
||||
// to pend the ISR when we want data transmission to start.
|
||||
let regs = T::regs();
|
||||
regs.uartimsc().write(|w| {
|
||||
info.regs.uartimsc().write(|w| {
|
||||
w.set_rxim(true);
|
||||
w.set_rtim(true);
|
||||
w.set_txim(true);
|
||||
});
|
||||
|
||||
T::Interrupt::unpend();
|
||||
unsafe { T::Interrupt::enable() };
|
||||
info.interrupt.unpend();
|
||||
unsafe { info.interrupt.enable() };
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> BufferedUart<'d, T> {
|
||||
impl BufferedUart {
|
||||
/// Create a buffered UART instance.
|
||||
pub fn new(
|
||||
pub fn new<'d, T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
tx_buffer: &'d mut [u8],
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Self {
|
||||
super::Uart::<'d, T, Async>::init(Some(tx.into()), Some(rx.into()), None, None, config);
|
||||
init_buffers::<T>(irq, Some(tx_buffer), Some(rx_buffer));
|
||||
super::Uart::<'d, Async>::init(T::info(), Some(tx.into()), Some(rx.into()), None, None, config);
|
||||
init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), Some(rx_buffer));
|
||||
|
||||
Self {
|
||||
rx: BufferedUartRx { phantom: PhantomData },
|
||||
tx: BufferedUartTx { phantom: PhantomData },
|
||||
rx: BufferedUartRx {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
},
|
||||
tx: BufferedUartTx {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a buffered UART instance with flow control.
|
||||
pub fn new_with_rtscts(
|
||||
pub fn new_with_rtscts<'d, T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
rts: Peri<'d, impl RtsPin<T>>,
|
||||
cts: Peri<'d, impl CtsPin<T>>,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
tx_buffer: &'d mut [u8],
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Self {
|
||||
super::Uart::<'d, T, Async>::init(
|
||||
super::Uart::<'d, Async>::init(
|
||||
T::info(),
|
||||
Some(tx.into()),
|
||||
Some(rx.into()),
|
||||
Some(rts.into()),
|
||||
Some(cts.into()),
|
||||
config,
|
||||
);
|
||||
init_buffers::<T>(irq, Some(tx_buffer), Some(rx_buffer));
|
||||
init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), Some(rx_buffer));
|
||||
|
||||
Self {
|
||||
rx: BufferedUartRx { phantom: PhantomData },
|
||||
tx: BufferedUartTx { phantom: PhantomData },
|
||||
rx: BufferedUartRx {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
},
|
||||
tx: BufferedUartTx {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,68 +173,75 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
|
||||
}
|
||||
|
||||
/// sets baudrate on runtime
|
||||
pub fn set_baudrate(&mut self, baudrate: u32) {
|
||||
super::Uart::<'d, T, Async>::set_baudrate_inner(baudrate);
|
||||
pub fn set_baudrate<'d>(&mut self, baudrate: u32) {
|
||||
super::Uart::<'d, Async>::set_baudrate_inner(self.rx.info, baudrate);
|
||||
}
|
||||
|
||||
/// Split into separate RX and TX handles.
|
||||
pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
|
||||
pub fn split(self) -> (BufferedUartTx, BufferedUartRx) {
|
||||
(self.tx, self.rx)
|
||||
}
|
||||
|
||||
/// Split the Uart into a transmitter and receiver by mutable reference,
|
||||
/// which is particularly useful when having two tasks correlating to
|
||||
/// transmitting and receiving.
|
||||
pub fn split_ref(&mut self) -> (&mut BufferedUartTx<'d, T>, &mut BufferedUartRx<'d, T>) {
|
||||
pub fn split_ref(&mut self) -> (&mut BufferedUartTx, &mut BufferedUartRx) {
|
||||
(&mut self.tx, &mut self.rx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> BufferedUartRx<'d, T> {
|
||||
impl BufferedUartRx {
|
||||
/// Create a new buffered UART RX.
|
||||
pub fn new(
|
||||
pub fn new<'d, T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Self {
|
||||
super::Uart::<'d, T, Async>::init(None, Some(rx.into()), None, None, config);
|
||||
init_buffers::<T>(irq, None, Some(rx_buffer));
|
||||
super::Uart::<'d, Async>::init(T::info(), None, Some(rx.into()), None, None, config);
|
||||
init_buffers(T::info(), T::buffered_state(), None, Some(rx_buffer));
|
||||
|
||||
Self { phantom: PhantomData }
|
||||
Self {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new buffered UART RX with flow control.
|
||||
pub fn new_with_rts(
|
||||
pub fn new_with_rts<'d, T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
rts: Peri<'d, impl RtsPin<T>>,
|
||||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Self {
|
||||
super::Uart::<'d, T, Async>::init(None, Some(rx.into()), Some(rts.into()), None, config);
|
||||
init_buffers::<T>(irq, None, Some(rx_buffer));
|
||||
super::Uart::<'d, Async>::init(T::info(), None, Some(rx.into()), Some(rts.into()), None, config);
|
||||
init_buffers(T::info(), T::buffered_state(), None, Some(rx_buffer));
|
||||
|
||||
Self { phantom: PhantomData }
|
||||
Self {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
}
|
||||
}
|
||||
|
||||
fn read<'a>(buf: &'a mut [u8]) -> impl Future<Output = Result<usize, Error>> + 'a
|
||||
where
|
||||
T: 'd,
|
||||
{
|
||||
fn read<'a>(
|
||||
info: &'static Info,
|
||||
state: &'static State,
|
||||
buf: &'a mut [u8],
|
||||
) -> impl Future<Output = Result<usize, Error>> + 'a {
|
||||
poll_fn(move |cx| {
|
||||
if let Poll::Ready(r) = Self::try_read(buf) {
|
||||
if let Poll::Ready(r) = Self::try_read(info, state, buf) {
|
||||
return Poll::Ready(r);
|
||||
}
|
||||
T::buffered_state().rx_waker.register(cx.waker());
|
||||
state.rx_waker.register(cx.waker());
|
||||
Poll::Pending
|
||||
})
|
||||
}
|
||||
|
||||
fn get_rx_error() -> Option<Error> {
|
||||
let errs = T::buffered_state().rx_error.swap(0, Ordering::Relaxed);
|
||||
fn get_rx_error(state: &State) -> Option<Error> {
|
||||
let errs = state.rx_error.swap(0, Ordering::Relaxed);
|
||||
if errs & RXE_OVERRUN != 0 {
|
||||
Some(Error::Overrun)
|
||||
} else if errs & RXE_BREAK != 0 {
|
||||
@ -235,15 +255,11 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_read(buf: &mut [u8]) -> Poll<Result<usize, Error>>
|
||||
where
|
||||
T: 'd,
|
||||
{
|
||||
fn try_read(info: &Info, state: &State, buf: &mut [u8]) -> Poll<Result<usize, Error>> {
|
||||
if buf.is_empty() {
|
||||
return Poll::Ready(Ok(0));
|
||||
}
|
||||
|
||||
let state = T::buffered_state();
|
||||
let mut rx_reader = unsafe { state.rx_buf.reader() };
|
||||
let n = rx_reader.pop(|data| {
|
||||
let n = data.len().min(buf.len());
|
||||
@ -252,7 +268,7 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
|
||||
});
|
||||
|
||||
let result = if n == 0 {
|
||||
match Self::get_rx_error() {
|
||||
match Self::get_rx_error(state) {
|
||||
None => return Poll::Pending,
|
||||
Some(e) => Err(e),
|
||||
}
|
||||
@ -262,8 +278,7 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
|
||||
|
||||
// (Re-)Enable the interrupt to receive more data in case it was
|
||||
// disabled because the buffer was full or errors were detected.
|
||||
let regs = T::regs();
|
||||
regs.uartimsc().write_set(|w| {
|
||||
info.regs.uartimsc().write_set(|w| {
|
||||
w.set_rxim(true);
|
||||
w.set_rtim(true);
|
||||
});
|
||||
@ -274,23 +289,19 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
|
||||
/// Read from UART RX buffer blocking execution until done.
|
||||
pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
loop {
|
||||
match Self::try_read(buf) {
|
||||
match Self::try_read(self.info, self.state, buf) {
|
||||
Poll::Ready(res) => return res,
|
||||
Poll::Pending => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_buf<'a>() -> impl Future<Output = Result<&'a [u8], Error>>
|
||||
where
|
||||
T: 'd,
|
||||
{
|
||||
fn fill_buf<'a>(state: &'static State) -> impl Future<Output = Result<&'a [u8], Error>> {
|
||||
poll_fn(move |cx| {
|
||||
let state = T::buffered_state();
|
||||
let mut rx_reader = unsafe { state.rx_buf.reader() };
|
||||
let (p, n) = rx_reader.pop_buf();
|
||||
let result = if n == 0 {
|
||||
match Self::get_rx_error() {
|
||||
match Self::get_rx_error(state) {
|
||||
None => {
|
||||
state.rx_waker.register(cx.waker());
|
||||
return Poll::Pending;
|
||||
@ -306,64 +317,70 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
|
||||
})
|
||||
}
|
||||
|
||||
fn consume(amt: usize) {
|
||||
let state = T::buffered_state();
|
||||
fn consume(info: &Info, state: &State, amt: usize) {
|
||||
let mut rx_reader = unsafe { state.rx_buf.reader() };
|
||||
rx_reader.pop_done(amt);
|
||||
|
||||
// (Re-)Enable the interrupt to receive more data in case it was
|
||||
// disabled because the buffer was full or errors were detected.
|
||||
let regs = T::regs();
|
||||
regs.uartimsc().write_set(|w| {
|
||||
info.regs.uartimsc().write_set(|w| {
|
||||
w.set_rxim(true);
|
||||
w.set_rtim(true);
|
||||
});
|
||||
}
|
||||
|
||||
/// we are ready to read if there is data in the buffer
|
||||
fn read_ready() -> Result<bool, Error> {
|
||||
let state = T::buffered_state();
|
||||
fn read_ready(state: &State) -> Result<bool, Error> {
|
||||
Ok(!state.rx_buf.is_empty())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
impl BufferedUartTx {
|
||||
/// Create a new buffered UART TX.
|
||||
pub fn new(
|
||||
pub fn new<'d, T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
tx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Self {
|
||||
super::Uart::<'d, T, Async>::init(Some(tx.into()), None, None, None, config);
|
||||
init_buffers::<T>(irq, Some(tx_buffer), None);
|
||||
super::Uart::<'d, Async>::init(T::info(), Some(tx.into()), None, None, None, config);
|
||||
init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), None);
|
||||
|
||||
Self { phantom: PhantomData }
|
||||
Self {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new buffered UART TX with flow control.
|
||||
pub fn new_with_cts(
|
||||
pub fn new_with_cts<'d, T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
cts: Peri<'d, impl CtsPin<T>>,
|
||||
tx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> Self {
|
||||
super::Uart::<'d, T, Async>::init(Some(tx.into()), None, None, Some(cts.into()), config);
|
||||
init_buffers::<T>(irq, Some(tx_buffer), None);
|
||||
super::Uart::<'d, Async>::init(T::info(), Some(tx.into()), None, None, Some(cts.into()), config);
|
||||
init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), None);
|
||||
|
||||
Self { phantom: PhantomData }
|
||||
Self {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
}
|
||||
}
|
||||
|
||||
fn write(buf: &[u8]) -> impl Future<Output = Result<usize, Error>> + '_ {
|
||||
fn write<'d>(
|
||||
info: &'static Info,
|
||||
state: &'static State,
|
||||
buf: &'d [u8],
|
||||
) -> impl Future<Output = Result<usize, Error>> + 'd {
|
||||
poll_fn(move |cx| {
|
||||
if buf.is_empty() {
|
||||
return Poll::Ready(Ok(0));
|
||||
}
|
||||
|
||||
let state = T::buffered_state();
|
||||
let mut tx_writer = unsafe { state.tx_buf.writer() };
|
||||
let n = tx_writer.push(|data| {
|
||||
let n = data.len().min(buf.len());
|
||||
@ -379,14 +396,13 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
// FIFO and the number of bytes drops below a threshold. When the
|
||||
// FIFO was empty we have to manually pend the interrupt to shovel
|
||||
// TX data from the buffer into the FIFO.
|
||||
T::Interrupt::pend();
|
||||
info.interrupt.pend();
|
||||
Poll::Ready(Ok(n))
|
||||
})
|
||||
}
|
||||
|
||||
fn flush() -> impl Future<Output = Result<(), Error>> {
|
||||
fn flush(state: &'static State) -> impl Future<Output = Result<(), Error>> {
|
||||
poll_fn(move |cx| {
|
||||
let state = T::buffered_state();
|
||||
if !state.tx_buf.is_empty() {
|
||||
state.tx_waker.register(cx.waker());
|
||||
return Poll::Pending;
|
||||
@ -403,8 +419,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
}
|
||||
|
||||
loop {
|
||||
let state = T::buffered_state();
|
||||
let mut tx_writer = unsafe { state.tx_buf.writer() };
|
||||
let mut tx_writer = unsafe { self.state.tx_buf.writer() };
|
||||
let n = tx_writer.push(|data| {
|
||||
let n = data.len().min(buf.len());
|
||||
data[..n].copy_from_slice(&buf[..n]);
|
||||
@ -416,7 +431,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
// FIFO and the number of bytes drops below a threshold. When the
|
||||
// FIFO was empty we have to manually pend the interrupt to shovel
|
||||
// TX data from the buffer into the FIFO.
|
||||
T::Interrupt::pend();
|
||||
self.info.interrupt.pend();
|
||||
return Ok(n);
|
||||
}
|
||||
}
|
||||
@ -425,8 +440,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
/// Flush UART TX blocking execution until done.
|
||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||
loop {
|
||||
let state = T::buffered_state();
|
||||
if state.tx_buf.is_empty() {
|
||||
if self.state.tx_buf.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -434,7 +448,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
|
||||
/// Check if UART is busy.
|
||||
pub fn busy(&self) -> bool {
|
||||
T::regs().uartfr().read().busy()
|
||||
self.info.regs.uartfr().read().busy()
|
||||
}
|
||||
|
||||
/// Assert a break condition after waiting for the transmit buffers to empty,
|
||||
@ -445,7 +459,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
/// This method may block for a long amount of time since it has to wait
|
||||
/// for the transmit fifo to empty, which may take a while on slow links.
|
||||
pub async fn send_break(&mut self, bits: u32) {
|
||||
let regs = T::regs();
|
||||
let regs = self.info.regs;
|
||||
let bits = bits.max({
|
||||
let lcr = regs.uartlcr_h().read();
|
||||
let width = lcr.wlen() as u32 + 5;
|
||||
@ -458,7 +472,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
let div_clk = clk_peri_freq() as u64 * 64;
|
||||
let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk;
|
||||
|
||||
Self::flush().await.unwrap();
|
||||
Self::flush(self.state).await.unwrap();
|
||||
while self.busy() {}
|
||||
regs.uartlcr_h().write_set(|w| w.set_brk(true));
|
||||
Timer::after_micros(wait_usecs).await;
|
||||
@ -466,28 +480,26 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
|
||||
impl Drop for BufferedUartRx {
|
||||
fn drop(&mut self) {
|
||||
let state = T::buffered_state();
|
||||
unsafe { state.rx_buf.deinit() }
|
||||
unsafe { self.state.rx_buf.deinit() }
|
||||
|
||||
// TX is inactive if the buffer is not available.
|
||||
// We can now unregister the interrupt handler
|
||||
if !state.tx_buf.is_available() {
|
||||
T::Interrupt::disable();
|
||||
if !self.state.tx_buf.is_available() {
|
||||
self.info.interrupt.disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
|
||||
impl Drop for BufferedUartTx {
|
||||
fn drop(&mut self) {
|
||||
let state = T::buffered_state();
|
||||
unsafe { state.tx_buf.deinit() }
|
||||
unsafe { self.state.tx_buf.deinit() }
|
||||
|
||||
// RX is inactive if the buffer is not available.
|
||||
// We can now unregister the interrupt handler
|
||||
if !state.rx_buf.is_available() {
|
||||
T::Interrupt::disable();
|
||||
if !self.state.rx_buf.is_available() {
|
||||
self.info.interrupt.disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -499,7 +511,7 @@ pub struct BufferedInterruptHandler<T: Instance> {
|
||||
|
||||
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for BufferedInterruptHandler<T> {
|
||||
unsafe fn on_interrupt() {
|
||||
let r = T::regs();
|
||||
let r = T::info().regs;
|
||||
if r.uartdmacr().read().rxdmae() {
|
||||
return;
|
||||
}
|
||||
@ -603,95 +615,95 @@ impl embedded_io::Error for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_io_async::ErrorType for BufferedUart<'d, T> {
|
||||
impl embedded_io_async::ErrorType for BufferedUart {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_io_async::ErrorType for BufferedUartRx<'d, T> {
|
||||
impl embedded_io_async::ErrorType for BufferedUartRx {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_io_async::ErrorType for BufferedUartTx<'d, T> {
|
||||
impl embedded_io_async::ErrorType for BufferedUartTx {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io_async::Read for BufferedUart<'d, T> {
|
||||
impl embedded_io_async::Read for BufferedUart {
|
||||
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
BufferedUartRx::<'d, T>::read(buf).await
|
||||
BufferedUartRx::read(self.rx.info, self.rx.state, buf).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io_async::Read for BufferedUartRx<'d, T> {
|
||||
impl embedded_io_async::Read for BufferedUartRx {
|
||||
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
Self::read(buf).await
|
||||
Self::read(self.info, self.state, buf).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io_async::ReadReady for BufferedUart<'d, T> {
|
||||
impl embedded_io_async::ReadReady for BufferedUart {
|
||||
fn read_ready(&mut self) -> Result<bool, Self::Error> {
|
||||
BufferedUartRx::<'d, T>::read_ready()
|
||||
BufferedUartRx::read_ready(self.rx.state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io_async::ReadReady for BufferedUartRx<'d, T> {
|
||||
impl embedded_io_async::ReadReady for BufferedUartRx {
|
||||
fn read_ready(&mut self) -> Result<bool, Self::Error> {
|
||||
Self::read_ready()
|
||||
Self::read_ready(self.state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io_async::BufRead for BufferedUart<'d, T> {
|
||||
impl embedded_io_async::BufRead for BufferedUart {
|
||||
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
|
||||
BufferedUartRx::<'d, T>::fill_buf().await
|
||||
BufferedUartRx::fill_buf(self.rx.state).await
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: usize) {
|
||||
BufferedUartRx::<'d, T>::consume(amt)
|
||||
BufferedUartRx::consume(self.rx.info, self.rx.state, amt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io_async::BufRead for BufferedUartRx<'d, T> {
|
||||
impl embedded_io_async::BufRead for BufferedUartRx {
|
||||
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
|
||||
Self::fill_buf().await
|
||||
Self::fill_buf(self.state).await
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: usize) {
|
||||
Self::consume(amt)
|
||||
Self::consume(self.info, self.state, amt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io_async::Write for BufferedUart<'d, T> {
|
||||
impl embedded_io_async::Write for BufferedUart {
|
||||
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
BufferedUartTx::<'d, T>::write(buf).await
|
||||
BufferedUartTx::write(self.tx.info, self.tx.state, buf).await
|
||||
}
|
||||
|
||||
async fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
BufferedUartTx::<'d, T>::flush().await
|
||||
BufferedUartTx::flush(self.tx.state).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io_async::Write for BufferedUartTx<'d, T> {
|
||||
impl embedded_io_async::Write for BufferedUartTx {
|
||||
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
Self::write(buf).await
|
||||
Self::write(self.info, self.state, buf).await
|
||||
}
|
||||
|
||||
async fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
Self::flush().await
|
||||
Self::flush(self.state).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io::Read for BufferedUart<'d, T> {
|
||||
impl embedded_io::Read for BufferedUart {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
self.rx.blocking_read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io::Read for BufferedUartRx<'d, T> {
|
||||
impl embedded_io::Read for BufferedUartRx {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
self.blocking_read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io::Write for BufferedUart<'d, T> {
|
||||
impl embedded_io::Write for BufferedUart {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
self.tx.blocking_write(buf)
|
||||
}
|
||||
@ -701,7 +713,7 @@ impl<'d, T: Instance + 'd> embedded_io::Write for BufferedUart<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd> embedded_io::Write for BufferedUartTx<'d, T> {
|
||||
impl embedded_io::Write for BufferedUartTx {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
self.blocking_write(buf)
|
||||
}
|
||||
@ -711,11 +723,11 @@ impl<'d, T: Instance + 'd> embedded_io::Write for BufferedUartTx<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d, T> {
|
||||
impl embedded_hal_02::serial::Read<u8> for BufferedUartRx {
|
||||
type Error = Error;
|
||||
|
||||
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||
let r = T::regs();
|
||||
let r = self.info.regs;
|
||||
if r.uartfr().read().rxfe() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
@ -736,7 +748,7 @@ impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d, T
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx<'d, T> {
|
||||
impl embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx {
|
||||
type Error = Error;
|
||||
|
||||
fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> {
|
||||
@ -755,7 +767,7 @@ impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedU
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d, T> {
|
||||
impl embedded_hal_02::serial::Read<u8> for BufferedUart {
|
||||
type Error = Error;
|
||||
|
||||
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||
@ -763,7 +775,7 @@ impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d, T>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUart<'d, T> {
|
||||
impl embedded_hal_02::blocking::serial::Write<u8> for BufferedUart {
|
||||
type Error = Error;
|
||||
|
||||
fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> {
|
||||
@ -782,25 +794,25 @@ impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedU
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_nb::serial::ErrorType for BufferedUartRx<'d, T> {
|
||||
impl embedded_hal_nb::serial::ErrorType for BufferedUartRx {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_nb::serial::ErrorType for BufferedUartTx<'d, T> {
|
||||
impl embedded_hal_nb::serial::ErrorType for BufferedUartTx {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_nb::serial::ErrorType for BufferedUart<'d, T> {
|
||||
impl embedded_hal_nb::serial::ErrorType for BufferedUart {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_nb::serial::Read for BufferedUartRx<'d, T> {
|
||||
impl embedded_hal_nb::serial::Read for BufferedUartRx {
|
||||
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||
embedded_hal_02::serial::Read::read(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, T> {
|
||||
impl embedded_hal_nb::serial::Write for BufferedUartTx {
|
||||
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
|
||||
self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other)
|
||||
}
|
||||
@ -810,13 +822,13 @@ impl<'d, T: Instance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_nb::serial::Read for BufferedUart<'d, T> {
|
||||
impl embedded_hal_nb::serial::Read for BufferedUart {
|
||||
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||
embedded_hal_02::serial::Read::read(&mut self.rx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_nb::serial::Write for BufferedUart<'d, T> {
|
||||
impl embedded_hal_nb::serial::Write for BufferedUart {
|
||||
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
|
||||
self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other)
|
||||
}
|
||||
|
@ -13,7 +13,8 @@ use pac::uart::regs::Uartris;
|
||||
use crate::clocks::clk_peri_freq;
|
||||
use crate::dma::{AnyChannel, Channel};
|
||||
use crate::gpio::{AnyPin, SealedPin};
|
||||
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||
use crate::interrupt::typelevel::{Binding, Interrupt as _};
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
use crate::pac::io::vals::{Inover, Outover};
|
||||
use crate::{interrupt, pac, peripherals, RegExt};
|
||||
|
||||
@ -135,37 +136,41 @@ pub struct DmaState {
|
||||
}
|
||||
|
||||
/// UART driver.
|
||||
pub struct Uart<'d, T: Instance, M: Mode> {
|
||||
tx: UartTx<'d, T, M>,
|
||||
rx: UartRx<'d, T, M>,
|
||||
pub struct Uart<'d, M: Mode> {
|
||||
tx: UartTx<'d, M>,
|
||||
rx: UartRx<'d, M>,
|
||||
}
|
||||
|
||||
/// UART TX driver.
|
||||
pub struct UartTx<'d, T: Instance, M: Mode> {
|
||||
pub struct UartTx<'d, M: Mode> {
|
||||
info: &'static Info,
|
||||
tx_dma: Option<Peri<'d, AnyChannel>>,
|
||||
phantom: PhantomData<(&'d mut T, M)>,
|
||||
phantom: PhantomData<M>,
|
||||
}
|
||||
|
||||
/// UART RX driver.
|
||||
pub struct UartRx<'d, T: Instance, M: Mode> {
|
||||
pub struct UartRx<'d, M: Mode> {
|
||||
info: &'static Info,
|
||||
dma_state: &'static DmaState,
|
||||
rx_dma: Option<Peri<'d, AnyChannel>>,
|
||||
phantom: PhantomData<(&'d mut T, M)>,
|
||||
phantom: PhantomData<M>,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
|
||||
impl<'d, M: Mode> UartTx<'d, M> {
|
||||
/// Create a new DMA-enabled UART which can only send data
|
||||
pub fn new(
|
||||
pub fn new<T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
tx_dma: Peri<'d, impl Channel>,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Uart::<T, M>::init(Some(tx.into()), None, None, None, config);
|
||||
Self::new_inner(Some(tx_dma.into()))
|
||||
Uart::<M>::init(T::info(), Some(tx.into()), None, None, None, config);
|
||||
Self::new_inner(T::info(), Some(tx_dma.into()))
|
||||
}
|
||||
|
||||
fn new_inner(tx_dma: Option<Peri<'d, AnyChannel>>) -> Self {
|
||||
fn new_inner(info: &'static Info, tx_dma: Option<Peri<'d, AnyChannel>>) -> Self {
|
||||
Self {
|
||||
info,
|
||||
tx_dma,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
@ -173,7 +178,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
|
||||
|
||||
/// Transmit the provided buffer blocking execution until done.
|
||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
let r = self.info.regs;
|
||||
for &b in buffer {
|
||||
while r.uartfr().read().txff() {}
|
||||
r.uartdr().write(|w| w.set_data(b));
|
||||
@ -183,14 +188,13 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
|
||||
|
||||
/// Flush UART TX blocking execution until done.
|
||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
while !r.uartfr().read().txfe() {}
|
||||
while !self.info.regs.uartfr().read().txfe() {}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check if UART is busy transmitting.
|
||||
pub fn busy(&self) -> bool {
|
||||
T::regs().uartfr().read().busy()
|
||||
self.info.regs.uartfr().read().busy()
|
||||
}
|
||||
|
||||
/// Assert a break condition after waiting for the transmit buffers to empty,
|
||||
@ -201,7 +205,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
|
||||
/// This method may block for a long amount of time since it has to wait
|
||||
/// for the transmit fifo to empty, which may take a while on slow links.
|
||||
pub async fn send_break(&mut self, bits: u32) {
|
||||
let regs = T::regs();
|
||||
let regs = self.info.regs;
|
||||
let bits = bits.max({
|
||||
let lcr = regs.uartlcr_h().read();
|
||||
let width = lcr.wlen() as u32 + 5;
|
||||
@ -222,65 +226,80 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> UartTx<'d, T, Blocking> {
|
||||
impl<'d> UartTx<'d, Blocking> {
|
||||
/// Create a new UART TX instance for blocking mode operations.
|
||||
pub fn new_blocking(_uart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self {
|
||||
Uart::<T, Blocking>::init(Some(tx.into()), None, None, None, config);
|
||||
Self::new_inner(None)
|
||||
pub fn new_blocking<T: Instance>(_uart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self {
|
||||
Uart::<Blocking>::init(T::info(), Some(tx.into()), None, None, None, config);
|
||||
Self::new_inner(T::info(), None)
|
||||
}
|
||||
|
||||
/// Convert this uart TX instance into a buffered uart using the provided
|
||||
/// irq and transmit buffer.
|
||||
pub fn into_buffered(
|
||||
pub fn into_buffered<T: Instance>(
|
||||
self,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
tx_buffer: &'d mut [u8],
|
||||
) -> BufferedUartTx<'d, T> {
|
||||
buffered::init_buffers::<T>(irq, Some(tx_buffer), None);
|
||||
) -> BufferedUartTx {
|
||||
buffered::init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), None);
|
||||
|
||||
BufferedUartTx { phantom: PhantomData }
|
||||
BufferedUartTx {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> UartTx<'d, T, Async> {
|
||||
impl<'d> UartTx<'d, Async> {
|
||||
/// Write to UART TX from the provided buffer using DMA.
|
||||
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
let ch = self.tx_dma.as_mut().unwrap().reborrow();
|
||||
let transfer = unsafe {
|
||||
T::regs().uartdmacr().write_set(|reg| {
|
||||
self.info.regs.uartdmacr().write_set(|reg| {
|
||||
reg.set_txdmae(true);
|
||||
});
|
||||
// If we don't assign future to a variable, the data register pointer
|
||||
// is held across an await and makes the future non-Send.
|
||||
crate::dma::write(ch, buffer, T::regs().uartdr().as_ptr() as *mut _, T::TX_DREQ.into())
|
||||
crate::dma::write(
|
||||
ch,
|
||||
buffer,
|
||||
self.info.regs.uartdr().as_ptr() as *mut _,
|
||||
self.info.tx_dreq.into(),
|
||||
)
|
||||
};
|
||||
transfer.await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
|
||||
impl<'d, M: Mode> UartRx<'d, M> {
|
||||
/// Create a new DMA-enabled UART which can only receive data
|
||||
pub fn new(
|
||||
pub fn new<T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
_irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
|
||||
rx_dma: Peri<'d, impl Channel>,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Uart::<T, M>::init(None, Some(rx.into()), None, None, config);
|
||||
Self::new_inner(true, Some(rx_dma.into()))
|
||||
Uart::<M>::init(T::info(), None, Some(rx.into()), None, None, config);
|
||||
Self::new_inner(T::info(), T::dma_state(), true, Some(rx_dma.into()))
|
||||
}
|
||||
|
||||
fn new_inner(has_irq: bool, rx_dma: Option<Peri<'d, AnyChannel>>) -> Self {
|
||||
fn new_inner(
|
||||
info: &'static Info,
|
||||
dma_state: &'static DmaState,
|
||||
has_irq: bool,
|
||||
rx_dma: Option<Peri<'d, AnyChannel>>,
|
||||
) -> Self {
|
||||
debug_assert_eq!(has_irq, rx_dma.is_some());
|
||||
if has_irq {
|
||||
// disable all error interrupts initially
|
||||
T::regs().uartimsc().write(|w| w.0 = 0);
|
||||
T::Interrupt::unpend();
|
||||
unsafe { T::Interrupt::enable() };
|
||||
info.regs.uartimsc().write(|w| w.0 = 0);
|
||||
info.interrupt.unpend();
|
||||
unsafe { info.interrupt.enable() };
|
||||
}
|
||||
Self {
|
||||
info,
|
||||
dma_state,
|
||||
rx_dma,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
@ -299,7 +318,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
|
||||
/// encountered. in both cases, `len` is the number of *good* bytes copied into
|
||||
/// `buffer`.
|
||||
fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, (usize, Error)> {
|
||||
let r = T::regs();
|
||||
let r = self.info.regs;
|
||||
for (i, b) in buffer.iter_mut().enumerate() {
|
||||
if r.uartfr().read().rxfe() {
|
||||
return Ok(i);
|
||||
@ -323,12 +342,12 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
|
||||
impl<'d, M: Mode> Drop for UartRx<'d, M> {
|
||||
fn drop(&mut self) {
|
||||
if self.rx_dma.is_some() {
|
||||
T::Interrupt::disable();
|
||||
self.info.interrupt.disable();
|
||||
// clear dma flags. irq handlers use these to disambiguate among themselves.
|
||||
T::regs().uartdmacr().write_clear(|reg| {
|
||||
self.info.regs.uartdmacr().write_clear(|reg| {
|
||||
reg.set_rxdmae(true);
|
||||
reg.set_txdmae(true);
|
||||
reg.set_dmaonerr(true);
|
||||
@ -337,23 +356,26 @@ impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> UartRx<'d, T, Blocking> {
|
||||
impl<'d> UartRx<'d, Blocking> {
|
||||
/// Create a new UART RX instance for blocking mode operations.
|
||||
pub fn new_blocking(_uart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self {
|
||||
Uart::<T, Blocking>::init(None, Some(rx.into()), None, None, config);
|
||||
Self::new_inner(false, None)
|
||||
pub fn new_blocking<T: Instance>(_uart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self {
|
||||
Uart::<Blocking>::init(T::info(), None, Some(rx.into()), None, None, config);
|
||||
Self::new_inner(T::info(), T::dma_state(), false, None)
|
||||
}
|
||||
|
||||
/// Convert this uart RX instance into a buffered uart using the provided
|
||||
/// irq and receive buffer.
|
||||
pub fn into_buffered(
|
||||
pub fn into_buffered<T: Instance>(
|
||||
self,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
rx_buffer: &'d mut [u8],
|
||||
) -> BufferedUartRx<'d, T> {
|
||||
buffered::init_buffers::<T>(irq, None, Some(rx_buffer));
|
||||
) -> BufferedUartRx {
|
||||
buffered::init_buffers(T::info(), T::buffered_state(), None, Some(rx_buffer));
|
||||
|
||||
BufferedUartRx { phantom: PhantomData }
|
||||
BufferedUartRx {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,7 +386,7 @@ pub struct InterruptHandler<T: Instance> {
|
||||
|
||||
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||
unsafe fn on_interrupt() {
|
||||
let uart = T::regs();
|
||||
let uart = T::info().regs;
|
||||
if !uart.uartdmacr().read().rxdmae() {
|
||||
return;
|
||||
}
|
||||
@ -380,13 +402,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
impl<'d> UartRx<'d, Async> {
|
||||
/// Read from UART RX into the provided buffer.
|
||||
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
// clear error flags before we drain the fifo. errors that have accumulated
|
||||
// in the flags will also be present in the fifo.
|
||||
T::dma_state().rx_errs.store(0, Ordering::Relaxed);
|
||||
T::regs().uarticr().write(|w| {
|
||||
self.dma_state.rx_errs.store(0, Ordering::Relaxed);
|
||||
self.info.regs.uarticr().write(|w| {
|
||||
w.set_oeic(true);
|
||||
w.set_beic(true);
|
||||
w.set_peic(true);
|
||||
@ -408,28 +430,33 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
// interrupt flags will have been raised, and those will be picked up immediately
|
||||
// by the interrupt handler.
|
||||
let ch = self.rx_dma.as_mut().unwrap().reborrow();
|
||||
T::regs().uartimsc().write_set(|w| {
|
||||
self.info.regs.uartimsc().write_set(|w| {
|
||||
w.set_oeim(true);
|
||||
w.set_beim(true);
|
||||
w.set_peim(true);
|
||||
w.set_feim(true);
|
||||
});
|
||||
T::regs().uartdmacr().write_set(|reg| {
|
||||
self.info.regs.uartdmacr().write_set(|reg| {
|
||||
reg.set_rxdmae(true);
|
||||
reg.set_dmaonerr(true);
|
||||
});
|
||||
let transfer = unsafe {
|
||||
// If we don't assign future to a variable, the data register pointer
|
||||
// is held across an await and makes the future non-Send.
|
||||
crate::dma::read(ch, T::regs().uartdr().as_ptr() as *const _, buffer, T::RX_DREQ.into())
|
||||
crate::dma::read(
|
||||
ch,
|
||||
self.info.regs.uartdr().as_ptr() as *const _,
|
||||
buffer,
|
||||
self.info.rx_dreq.into(),
|
||||
)
|
||||
};
|
||||
|
||||
// wait for either the transfer to complete or an error to happen.
|
||||
let transfer_result = select(
|
||||
transfer,
|
||||
poll_fn(|cx| {
|
||||
T::dma_state().rx_err_waker.register(cx.waker());
|
||||
match T::dma_state().rx_errs.swap(0, Ordering::Relaxed) {
|
||||
self.dma_state.rx_err_waker.register(cx.waker());
|
||||
match self.dma_state.rx_errs.swap(0, Ordering::Relaxed) {
|
||||
0 => Poll::Pending,
|
||||
e => Poll::Ready(Uartris(e as u32)),
|
||||
}
|
||||
@ -441,7 +468,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
Either::First(()) => {
|
||||
// We're here because the DMA finished, BUT if an error occurred on the LAST
|
||||
// byte, then we may still need to grab the error state!
|
||||
Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32)
|
||||
Uartris(self.dma_state.rx_errs.swap(0, Ordering::Relaxed) as u32)
|
||||
}
|
||||
Either::Second(e) => {
|
||||
// We're here because we errored, which means this is the error that
|
||||
@ -521,8 +548,8 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
) -> Result<usize, ReadToBreakError> {
|
||||
// clear error flags before we drain the fifo. errors that have accumulated
|
||||
// in the flags will also be present in the fifo.
|
||||
T::dma_state().rx_errs.store(0, Ordering::Relaxed);
|
||||
T::regs().uarticr().write(|w| {
|
||||
self.dma_state.rx_errs.store(0, Ordering::Relaxed);
|
||||
self.info.regs.uarticr().write(|w| {
|
||||
w.set_oeic(true);
|
||||
w.set_beic(true);
|
||||
w.set_peic(true);
|
||||
@ -555,13 +582,13 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
// interrupt flags will have been raised, and those will be picked up immediately
|
||||
// by the interrupt handler.
|
||||
let ch = self.rx_dma.as_mut().unwrap();
|
||||
T::regs().uartimsc().write_set(|w| {
|
||||
self.info.regs.uartimsc().write_set(|w| {
|
||||
w.set_oeim(true);
|
||||
w.set_beim(true);
|
||||
w.set_peim(true);
|
||||
w.set_feim(true);
|
||||
});
|
||||
T::regs().uartdmacr().write_set(|reg| {
|
||||
self.info.regs.uartdmacr().write_set(|reg| {
|
||||
reg.set_rxdmae(true);
|
||||
reg.set_dmaonerr(true);
|
||||
});
|
||||
@ -572,9 +599,9 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
// is held across an await and makes the future non-Send.
|
||||
crate::dma::read(
|
||||
ch.reborrow(),
|
||||
T::regs().uartdr().as_ptr() as *const _,
|
||||
self.info.regs.uartdr().as_ptr() as *const _,
|
||||
sbuffer,
|
||||
T::RX_DREQ.into(),
|
||||
self.info.rx_dreq.into(),
|
||||
)
|
||||
};
|
||||
|
||||
@ -582,8 +609,8 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
let transfer_result = select(
|
||||
transfer,
|
||||
poll_fn(|cx| {
|
||||
T::dma_state().rx_err_waker.register(cx.waker());
|
||||
match T::dma_state().rx_errs.swap(0, Ordering::Relaxed) {
|
||||
self.dma_state.rx_err_waker.register(cx.waker());
|
||||
match self.dma_state.rx_errs.swap(0, Ordering::Relaxed) {
|
||||
0 => Poll::Pending,
|
||||
e => Poll::Ready(Uartris(e as u32)),
|
||||
}
|
||||
@ -596,7 +623,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
Either::First(()) => {
|
||||
// We're here because the DMA finished, BUT if an error occurred on the LAST
|
||||
// byte, then we may still need to grab the error state!
|
||||
Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32)
|
||||
Uartris(self.dma_state.rx_errs.swap(0, Ordering::Relaxed) as u32)
|
||||
}
|
||||
Either::Second(e) => {
|
||||
// We're here because we errored, which means this is the error that
|
||||
@ -635,7 +662,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let regs = T::regs();
|
||||
let regs = self.info.regs;
|
||||
let all_full = next_addr == eval;
|
||||
|
||||
// NOTE: This is off label usage of RSR! See the issue below for
|
||||
@ -685,9 +712,9 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Uart<'d, T, Blocking> {
|
||||
impl<'d> Uart<'d, Blocking> {
|
||||
/// Create a new UART without hardware flow control
|
||||
pub fn new_blocking(
|
||||
pub fn new_blocking<T: Instance>(
|
||||
uart: Peri<'d, T>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
@ -697,7 +724,7 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
|
||||
}
|
||||
|
||||
/// Create a new UART with hardware flow control (RTS/CTS)
|
||||
pub fn new_with_rtscts_blocking(
|
||||
pub fn new_with_rtscts_blocking<T: Instance>(
|
||||
uart: Peri<'d, T>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
@ -720,24 +747,30 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
|
||||
|
||||
/// Convert this uart instance into a buffered uart using the provided
|
||||
/// irq, transmit and receive buffers.
|
||||
pub fn into_buffered(
|
||||
pub fn into_buffered<T: Instance>(
|
||||
self,
|
||||
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
|
||||
tx_buffer: &'d mut [u8],
|
||||
rx_buffer: &'d mut [u8],
|
||||
) -> BufferedUart<'d, T> {
|
||||
buffered::init_buffers::<T>(irq, Some(tx_buffer), Some(rx_buffer));
|
||||
) -> BufferedUart {
|
||||
buffered::init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), Some(rx_buffer));
|
||||
|
||||
BufferedUart {
|
||||
rx: BufferedUartRx { phantom: PhantomData },
|
||||
tx: BufferedUartTx { phantom: PhantomData },
|
||||
rx: BufferedUartRx {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
},
|
||||
tx: BufferedUartTx {
|
||||
info: T::info(),
|
||||
state: T::buffered_state(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Uart<'d, T, Async> {
|
||||
impl<'d> Uart<'d, Async> {
|
||||
/// Create a new DMA enabled UART without hardware flow control
|
||||
pub fn new(
|
||||
pub fn new<T: Instance>(
|
||||
uart: Peri<'d, T>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
@ -760,7 +793,7 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
|
||||
}
|
||||
|
||||
/// Create a new DMA enabled UART with hardware flow control (RTS/CTS)
|
||||
pub fn new_with_rtscts(
|
||||
pub fn new_with_rtscts<T: Instance>(
|
||||
uart: Peri<'d, T>,
|
||||
tx: Peri<'d, impl TxPin<T>>,
|
||||
rx: Peri<'d, impl RxPin<T>>,
|
||||
@ -785,8 +818,8 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
|
||||
fn new_inner(
|
||||
impl<'d, M: Mode> Uart<'d, M> {
|
||||
fn new_inner<T: Instance>(
|
||||
_uart: Peri<'d, T>,
|
||||
mut tx: Peri<'d, AnyPin>,
|
||||
mut rx: Peri<'d, AnyPin>,
|
||||
@ -798,6 +831,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self::init(
|
||||
T::info(),
|
||||
Some(tx.reborrow()),
|
||||
Some(rx.reborrow()),
|
||||
rts.as_mut().map(|x| x.reborrow()),
|
||||
@ -806,19 +840,20 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
|
||||
);
|
||||
|
||||
Self {
|
||||
tx: UartTx::new_inner(tx_dma),
|
||||
rx: UartRx::new_inner(has_irq, rx_dma),
|
||||
tx: UartTx::new_inner(T::info(), tx_dma),
|
||||
rx: UartRx::new_inner(T::info(), T::dma_state(), has_irq, rx_dma),
|
||||
}
|
||||
}
|
||||
|
||||
fn init(
|
||||
info: &Info,
|
||||
tx: Option<Peri<'_, AnyPin>>,
|
||||
rx: Option<Peri<'_, AnyPin>>,
|
||||
rts: Option<Peri<'_, AnyPin>>,
|
||||
cts: Option<Peri<'_, AnyPin>>,
|
||||
config: Config,
|
||||
) {
|
||||
let r = T::regs();
|
||||
let r = info.regs;
|
||||
if let Some(pin) = &tx {
|
||||
let funcsel = {
|
||||
let pin_number = ((pin.gpio().as_ptr() as u32) & 0x1FF) / 8;
|
||||
@ -896,7 +931,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
|
||||
});
|
||||
}
|
||||
|
||||
Self::set_baudrate_inner(config.baudrate);
|
||||
Self::set_baudrate_inner(info, config.baudrate);
|
||||
|
||||
let (pen, eps) = match config.parity {
|
||||
Parity::ParityNone => (false, false),
|
||||
@ -926,8 +961,8 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
|
||||
});
|
||||
}
|
||||
|
||||
fn lcr_modify<R>(f: impl FnOnce(&mut crate::pac::uart::regs::UartlcrH) -> R) -> R {
|
||||
let r = T::regs();
|
||||
fn lcr_modify<R>(info: &Info, f: impl FnOnce(&mut crate::pac::uart::regs::UartlcrH) -> R) -> R {
|
||||
let r = info.regs;
|
||||
|
||||
// Notes from PL011 reference manual:
|
||||
//
|
||||
@ -978,11 +1013,11 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
|
||||
|
||||
/// sets baudrate on runtime
|
||||
pub fn set_baudrate(&mut self, baudrate: u32) {
|
||||
Self::set_baudrate_inner(baudrate);
|
||||
Self::set_baudrate_inner(self.tx.info, baudrate);
|
||||
}
|
||||
|
||||
fn set_baudrate_inner(baudrate: u32) {
|
||||
let r = T::regs();
|
||||
fn set_baudrate_inner(info: &Info, baudrate: u32) {
|
||||
let r = info.regs;
|
||||
|
||||
let clk_base = crate::clocks::clk_peri_freq();
|
||||
|
||||
@ -1002,11 +1037,11 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
|
||||
r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd));
|
||||
r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd));
|
||||
|
||||
Self::lcr_modify(|_| {});
|
||||
Self::lcr_modify(info, |_| {});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
|
||||
impl<'d, M: Mode> Uart<'d, M> {
|
||||
/// Transmit the provided buffer blocking execution until done.
|
||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
self.tx.blocking_write(buffer)
|
||||
@ -1034,19 +1069,19 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
|
||||
|
||||
/// Split the Uart into a transmitter and receiver, which is particularly
|
||||
/// useful when having two tasks correlating to transmitting and receiving.
|
||||
pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) {
|
||||
pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) {
|
||||
(self.tx, self.rx)
|
||||
}
|
||||
|
||||
/// Split the Uart into a transmitter and receiver by mutable reference,
|
||||
/// which is particularly useful when having two tasks correlating to
|
||||
/// transmitting and receiving.
|
||||
pub fn split_ref(&mut self) -> (&mut UartTx<'d, T, M>, &mut UartRx<'d, T, M>) {
|
||||
pub fn split_ref(&mut self) -> (&mut UartTx<'d, M>, &mut UartRx<'d, M>) {
|
||||
(&mut self.tx, &mut self.rx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Uart<'d, T, Async> {
|
||||
impl<'d> Uart<'d, Async> {
|
||||
/// Write to UART TX from the provided buffer.
|
||||
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
self.tx.write(buffer).await
|
||||
@ -1076,10 +1111,10 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, M> {
|
||||
type Error = Error;
|
||||
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||
let r = T::regs();
|
||||
let r = self.info.regs;
|
||||
if r.uartfr().read().rxfe() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
@ -1100,11 +1135,11 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for UartTx<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::serial::Write<u8> for UartTx<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, word: u8) -> Result<(), nb::Error<Self::Error>> {
|
||||
let r = T::regs();
|
||||
let r = self.info.regs;
|
||||
if r.uartfr().read().txff() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
@ -1114,7 +1149,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for UartTx<'d,
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<(), nb::Error<Self::Error>> {
|
||||
let r = T::regs();
|
||||
let r = self.info.regs;
|
||||
if !r.uartfr().read().txfe() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
@ -1122,7 +1157,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for UartTx<'d,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
|
||||
@ -1134,7 +1169,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||
@ -1142,7 +1177,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for Uart<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::serial::Write<u8> for Uart<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, word: u8) -> Result<(), nb::Error<Self::Error>> {
|
||||
@ -1154,7 +1189,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for Uart<'d, T
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, M> {
|
||||
type Error = Error;
|
||||
|
||||
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
|
||||
@ -1177,21 +1212,21 @@ impl embedded_hal_nb::serial::Error for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, M> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, M> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, M> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, M> {
|
||||
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||
let r = T::regs();
|
||||
let r = self.info.regs;
|
||||
if r.uartfr().read().rxfe() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
@ -1212,7 +1247,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> {
|
||||
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
|
||||
self.blocking_write(&[char]).map_err(nb::Error::Other)
|
||||
}
|
||||
@ -1222,11 +1257,11 @@ impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, T,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_io::ErrorType for UartTx<'d, T, Blocking> {
|
||||
impl<'d> embedded_io::ErrorType for UartTx<'d, Blocking> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_io::Write for UartTx<'d, T, Blocking> {
|
||||
impl<'d> embedded_io::Write for UartTx<'d, Blocking> {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
self.blocking_write(buf).map(|_| buf.len())
|
||||
}
|
||||
@ -1236,13 +1271,13 @@ impl<'d, T: Instance> embedded_io::Write for UartTx<'d, T, Blocking> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, M> {
|
||||
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||
embedded_hal_02::serial::Read::read(&mut self.rx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, T, M> {
|
||||
impl<'d, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, M> {
|
||||
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
|
||||
self.blocking_write(&[char]).map_err(nb::Error::Other)
|
||||
}
|
||||
@ -1252,11 +1287,11 @@ impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, T, M>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_io::ErrorType for Uart<'d, T, Blocking> {
|
||||
impl<'d> embedded_io::ErrorType for Uart<'d, Blocking> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_io::Write for Uart<'d, T, Blocking> {
|
||||
impl<'d> embedded_io::Write for Uart<'d, Blocking> {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
self.blocking_write(buf).map(|_| buf.len())
|
||||
}
|
||||
@ -1266,13 +1301,17 @@ impl<'d, T: Instance> embedded_io::Write for Uart<'d, T, Blocking> {
|
||||
}
|
||||
}
|
||||
|
||||
struct Info {
|
||||
regs: pac::uart::Uart,
|
||||
tx_dreq: pac::dma::vals::TreqSel,
|
||||
rx_dreq: pac::dma::vals::TreqSel,
|
||||
interrupt: Interrupt,
|
||||
}
|
||||
|
||||
trait SealedMode {}
|
||||
|
||||
trait SealedInstance {
|
||||
const TX_DREQ: pac::dma::vals::TreqSel;
|
||||
const RX_DREQ: pac::dma::vals::TreqSel;
|
||||
|
||||
fn regs() -> pac::uart::Uart;
|
||||
fn info() -> &'static Info;
|
||||
|
||||
fn buffered_state() -> &'static buffered::State;
|
||||
|
||||
@ -1308,11 +1347,14 @@ pub trait Instance: SealedInstance + PeripheralType {
|
||||
macro_rules! impl_instance {
|
||||
($inst:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => {
|
||||
impl SealedInstance for peripherals::$inst {
|
||||
const TX_DREQ: pac::dma::vals::TreqSel = $tx_dreq;
|
||||
const RX_DREQ: pac::dma::vals::TreqSel = $rx_dreq;
|
||||
|
||||
fn regs() -> pac::uart::Uart {
|
||||
pac::$inst
|
||||
fn info() -> &'static Info {
|
||||
static INFO: Info = Info {
|
||||
regs: pac::$inst,
|
||||
tx_dreq: $tx_dreq,
|
||||
rx_dreq: $rx_dreq,
|
||||
interrupt: crate::interrupt::typelevel::$irq::IRQ,
|
||||
};
|
||||
&INFO
|
||||
}
|
||||
|
||||
fn buffered_state() -> &'static buffered::State {
|
||||
|
@ -31,7 +31,7 @@ use rand::RngCore;
|
||||
use static_cell::{ConstStaticCell, StaticCell};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, UART0, uart::Async>>;
|
||||
type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, uart::Async>>;
|
||||
|
||||
struct MyType {
|
||||
inner: u32,
|
||||
|
@ -48,7 +48,7 @@ async fn main(spawner: Spawner) {
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn reader(mut rx: BufferedUartRx<'static, UART0>) {
|
||||
async fn reader(mut rx: BufferedUartRx) {
|
||||
info!("Reading...");
|
||||
loop {
|
||||
let mut buf = [0; 31];
|
||||
|
@ -39,7 +39,7 @@ async fn main(spawner: Spawner) {
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn reader(mut rx: UartRx<'static, UART1, Async>) {
|
||||
async fn reader(mut rx: UartRx<'static, Async>) {
|
||||
info!("Reading...");
|
||||
loop {
|
||||
// read a total of 4 transmissions (32 / 8) and then print the result
|
||||
|
@ -31,7 +31,7 @@ use rand::RngCore;
|
||||
use static_cell::{ConstStaticCell, StaticCell};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, UART0, uart::Async>>;
|
||||
type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, uart::Async>>;
|
||||
|
||||
struct MyType {
|
||||
inner: u32,
|
||||
|
@ -48,7 +48,7 @@ async fn main(spawner: Spawner) {
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn reader(mut rx: BufferedUartRx<'static, UART0>) {
|
||||
async fn reader(mut rx: BufferedUartRx) {
|
||||
info!("Reading...");
|
||||
loop {
|
||||
let mut buf = [0; 31];
|
||||
|
@ -39,7 +39,7 @@ async fn main(spawner: Spawner) {
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn reader(mut rx: UartRx<'static, UART1, Async>) {
|
||||
async fn reader(mut rx: UartRx<'static, Async>) {
|
||||
info!("Reading...");
|
||||
loop {
|
||||
// read a total of 4 transmissions (32 / 8) and then print the result
|
||||
|
@ -8,17 +8,17 @@ teleprobe_meta::target!(b"pimoroni-pico-plus-2");
|
||||
use defmt::{assert_eq, *};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_rp::gpio::{Level, Output};
|
||||
use embassy_rp::uart::{Blocking, Config, Error, Instance, Parity, Uart, UartRx};
|
||||
use embassy_rp::uart::{Blocking, Config, Error, Parity, Uart, UartRx};
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
|
||||
fn read<const N: usize>(uart: &mut Uart<'_, Blocking>) -> Result<[u8; N], Error> {
|
||||
let mut buf = [255; N];
|
||||
uart.blocking_read(&mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
|
||||
fn read1<const N: usize>(uart: &mut UartRx<'_, Blocking>) -> Result<[u8; N], Error> {
|
||||
let mut buf = [255; N];
|
||||
uart.blocking_read(&mut buf)?;
|
||||
Ok(buf)
|
||||
|
@ -10,7 +10,7 @@ use embassy_executor::Spawner;
|
||||
use embassy_rp::bind_interrupts;
|
||||
use embassy_rp::gpio::{Level, Output};
|
||||
use embassy_rp::peripherals::UART0;
|
||||
use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
|
||||
use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Parity};
|
||||
use embassy_time::Timer;
|
||||
use embedded_io_async::{Read, ReadExactError, Write};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs {
|
||||
UART0_IRQ => BufferedInterruptHandler<UART0>;
|
||||
});
|
||||
|
||||
async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> {
|
||||
async fn read<const N: usize>(uart: &mut BufferedUart) -> Result<[u8; N], Error> {
|
||||
let mut buf = [255; N];
|
||||
match uart.read_exact(&mut buf).await {
|
||||
Ok(()) => Ok(buf),
|
||||
@ -29,7 +29,7 @@ async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Res
|
||||
}
|
||||
}
|
||||
|
||||
async fn read1<const N: usize>(uart: &mut BufferedUartRx<'_, impl Instance>) -> Result<[u8; N], Error> {
|
||||
async fn read1<const N: usize>(uart: &mut BufferedUartRx) -> Result<[u8; N], Error> {
|
||||
let mut buf = [255; N];
|
||||
match uart.read_exact(&mut buf).await {
|
||||
Ok(()) => Ok(buf),
|
||||
|
@ -10,7 +10,7 @@ use embassy_executor::Spawner;
|
||||
use embassy_rp::bind_interrupts;
|
||||
use embassy_rp::gpio::{Level, Output};
|
||||
use embassy_rp::peripherals::UART0;
|
||||
use embassy_rp::uart::{Async, Config, Error, Instance, InterruptHandler, Parity, Uart, UartRx};
|
||||
use embassy_rp::uart::{Async, Config, Error, InterruptHandler, Parity, Uart, UartRx};
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
@ -18,13 +18,13 @@ bind_interrupts!(struct Irqs {
|
||||
UART0_IRQ => InterruptHandler<UART0>;
|
||||
});
|
||||
|
||||
async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
|
||||
async fn read<const N: usize>(uart: &mut Uart<'_, Async>) -> Result<[u8; N], Error> {
|
||||
let mut buf = [255; N];
|
||||
uart.read(&mut buf).await?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
async fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
|
||||
async fn read1<const N: usize>(uart: &mut UartRx<'_, Async>) -> Result<[u8; N], Error> {
|
||||
let mut buf = [255; N];
|
||||
uart.read(&mut buf).await?;
|
||||
Ok(buf)
|
||||
|
Loading…
x
Reference in New Issue
Block a user