stm32: Add support for read_until_idle on UART
This commit is contained in:
parent
ff76fde299
commit
9cac649fcf
@ -46,16 +46,44 @@ impl<'d, T: BasicInstance> Unpin for BufferedUart<'d, T> {}
|
|||||||
impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
state: &'d mut State<'d, T>,
|
state: &'d mut State<'d, T>,
|
||||||
_uart: Uart<'d, T, NoDma, NoDma>,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||||
tx_buffer: &'d mut [u8],
|
tx_buffer: &'d mut [u8],
|
||||||
rx_buffer: &'d mut [u8],
|
rx_buffer: &'d mut [u8],
|
||||||
|
config: Config,
|
||||||
) -> BufferedUart<'d, T> {
|
) -> BufferedUart<'d, T> {
|
||||||
into_ref!(irq);
|
into_ref!(_peri, rx, tx, irq);
|
||||||
|
|
||||||
|
T::enable();
|
||||||
|
T::reset();
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
|
configure(r, &config, T::frequency(), T::MULTIPLIER);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
r.cr1().modify(|w| {
|
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||||
|
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||||
|
|
||||||
|
r.cr2().write(|_w| {});
|
||||||
|
r.cr3().write(|_w| {});
|
||||||
|
r.cr1().write(|w| {
|
||||||
|
w.set_ue(true);
|
||||||
|
w.set_te(true);
|
||||||
|
w.set_re(true);
|
||||||
|
w.set_m0(if config.parity != Parity::ParityNone {
|
||||||
|
vals::M0::BIT9
|
||||||
|
} else {
|
||||||
|
vals::M0::BIT8
|
||||||
|
});
|
||||||
|
w.set_pce(config.parity != Parity::ParityNone);
|
||||||
|
w.set_ps(match config.parity {
|
||||||
|
Parity::ParityOdd => vals::Ps::ODD,
|
||||||
|
Parity::ParityEven => vals::Ps::EVEN,
|
||||||
|
_ => vals::Ps::EVEN,
|
||||||
|
});
|
||||||
w.set_rxneie(true);
|
w.set_rxneie(true);
|
||||||
w.set_idleie(true);
|
w.set_idleie(true);
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
|
use core::future::poll_fn;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use atomic_polyfill::{compiler_fence, Ordering};
|
||||||
|
use embassy_cortex_m::interrupt::InterruptExt;
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
|
|
||||||
use crate::dma::NoDma;
|
use crate::dma::NoDma;
|
||||||
@ -10,6 +14,7 @@ use crate::gpio::sealed::AFType;
|
|||||||
use crate::pac::lpuart::{regs, vals, Lpuart as Regs};
|
use crate::pac::lpuart::{regs, vals, Lpuart as Regs};
|
||||||
#[cfg(not(any(lpuart_v1, lpuart_v2)))]
|
#[cfg(not(any(lpuart_v1, lpuart_v2)))]
|
||||||
use crate::pac::usart::{regs, vals, Usart as Regs};
|
use crate::pac::usart::{regs, vals, Usart as Regs};
|
||||||
|
use crate::time::Hertz;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{peripherals, Peripheral};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
@ -44,6 +49,10 @@ pub struct Config {
|
|||||||
pub data_bits: DataBits,
|
pub data_bits: DataBits,
|
||||||
pub stop_bits: StopBits,
|
pub stop_bits: StopBits,
|
||||||
pub parity: Parity,
|
pub parity: Parity,
|
||||||
|
/// if true, on read-like method, if there is a latent error pending,
|
||||||
|
/// read will abort, the error reported and cleared
|
||||||
|
/// if false, the error is ignored and cleared
|
||||||
|
pub detect_previous_overrun: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -53,6 +62,8 @@ impl Default for Config {
|
|||||||
data_bits: DataBits::DataBits8,
|
data_bits: DataBits::DataBits8,
|
||||||
stop_bits: StopBits::STOP1,
|
stop_bits: StopBits::STOP1,
|
||||||
parity: Parity::ParityNone,
|
parity: Parity::ParityNone,
|
||||||
|
// historical behavior
|
||||||
|
detect_previous_overrun: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,10 +81,11 @@ pub enum Error {
|
|||||||
Overrun,
|
Overrun,
|
||||||
/// Parity check error
|
/// Parity check error
|
||||||
Parity,
|
Parity,
|
||||||
|
/// Buffer too large for DMA
|
||||||
|
BufferTooLong,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
|
pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
|
||||||
tx: UartTx<'d, T, TxDma>,
|
tx: UartTx<'d, T, TxDma>,
|
||||||
rx: UartRx<'d, T, RxDma>,
|
rx: UartRx<'d, T, RxDma>,
|
||||||
}
|
}
|
||||||
@ -84,8 +96,9 @@ pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
|
pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
rx_dma: PeripheralRef<'d, RxDma>,
|
rx_dma: PeripheralRef<'d, RxDma>,
|
||||||
|
detect_previous_overrun: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||||
@ -135,10 +148,112 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||||
fn new(rx_dma: PeripheralRef<'d, RxDma>) -> Self {
|
/// usefull if you only want Uart Rx. It saves 1 pin and consumes a little less power
|
||||||
|
pub fn new(
|
||||||
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
|
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||||
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
into_ref!(peri, irq, rx, rx_dma);
|
||||||
|
|
||||||
|
T::enable();
|
||||||
|
T::reset();
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
|
||||||
|
configure(r, &config, T::frequency(), T::MULTIPLIER);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||||
|
|
||||||
|
r.cr2().write(|_w| {});
|
||||||
|
r.cr3().write(|w| {
|
||||||
|
// enable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||||
|
w.set_eie(true);
|
||||||
|
});
|
||||||
|
r.cr1().write(|w| {
|
||||||
|
// enable uart
|
||||||
|
w.set_ue(true);
|
||||||
|
// enable receiver
|
||||||
|
w.set_re(true);
|
||||||
|
// configure word size
|
||||||
|
w.set_m0(if config.parity != Parity::ParityNone {
|
||||||
|
vals::M0::BIT9
|
||||||
|
} else {
|
||||||
|
vals::M0::BIT8
|
||||||
|
});
|
||||||
|
// configure parity
|
||||||
|
w.set_pce(config.parity != Parity::ParityNone);
|
||||||
|
w.set_ps(match config.parity {
|
||||||
|
Parity::ParityOdd => vals::Ps::ODD,
|
||||||
|
Parity::ParityEven => vals::Ps::EVEN,
|
||||||
|
_ => vals::Ps::EVEN,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
irq.set_handler(Self::on_interrupt);
|
||||||
|
irq.unpend();
|
||||||
|
irq.enable();
|
||||||
|
|
||||||
|
// create state once!
|
||||||
|
let _s = T::state();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
_peri: peri,
|
||||||
rx_dma,
|
rx_dma,
|
||||||
phantom: PhantomData,
|
detect_previous_overrun: config.detect_previous_overrun,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_interrupt(_: *mut ()) {
|
||||||
|
let r = T::regs();
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) };
|
||||||
|
|
||||||
|
let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
|
||||||
|
|
||||||
|
if has_errors {
|
||||||
|
// clear all interrupts and DMA Rx Request
|
||||||
|
unsafe {
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
// disable RXNE interrupt
|
||||||
|
w.set_rxneie(false);
|
||||||
|
// disable parity interrupt
|
||||||
|
w.set_peie(false);
|
||||||
|
// disable idle line interrupt
|
||||||
|
w.set_idleie(false);
|
||||||
|
});
|
||||||
|
r.cr3().modify(|w| {
|
||||||
|
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||||
|
w.set_eie(false);
|
||||||
|
// disable DMA Rx Request
|
||||||
|
w.set_dmar(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
s.rx_waker.wake();
|
||||||
|
} else if cr1.idleie() && sr.idle() {
|
||||||
|
// IDLE detected: no more data will come
|
||||||
|
unsafe {
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
// disable idle line detection
|
||||||
|
w.set_idleie(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
r.cr3().modify(|w| {
|
||||||
|
// disable DMA Rx Request
|
||||||
|
w.set_dmar(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
s.rx_waker.wake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,17 +261,8 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
where
|
where
|
||||||
RxDma: crate::usart::RxDma<T>,
|
RxDma: crate::usart::RxDma<T>,
|
||||||
{
|
{
|
||||||
let ch = &mut self.rx_dma;
|
self.inner_read(buffer, false).await?;
|
||||||
let request = ch.request();
|
|
||||||
unsafe {
|
|
||||||
T::regs().cr3().modify(|reg| {
|
|
||||||
reg.set_dmar(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.
|
|
||||||
let transfer = crate::dma::read(ch, request, rdr(T::regs()), buffer);
|
|
||||||
transfer.await;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,13 +317,202 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
|
||||||
|
where
|
||||||
|
RxDma: crate::usart::RxDma<T>,
|
||||||
|
{
|
||||||
|
self.inner_read(buffer, true).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn inner_read(&mut self, buffer: &mut [u8], enable_idle_line_detection: bool) -> Result<usize, Error>
|
||||||
|
where
|
||||||
|
RxDma: crate::usart::RxDma<T>,
|
||||||
|
{
|
||||||
|
if buffer.is_empty() {
|
||||||
|
return Ok(0);
|
||||||
|
} else if buffer.len() > 0xFFFF {
|
||||||
|
return Err(Error::BufferTooLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
|
||||||
|
let buffer_len = buffer.len();
|
||||||
|
|
||||||
|
let ch = &mut self.rx_dma;
|
||||||
|
let request = ch.request();
|
||||||
|
|
||||||
|
// SAFETY: The only way we might have a problem is using split rx and tx
|
||||||
|
// here we only modify or read Rx related flags, interrupts and DMA channel
|
||||||
|
unsafe {
|
||||||
|
// Start USART DMA
|
||||||
|
// will not do anything yet because DMAR is not yet set
|
||||||
|
ch.start_read(request, rdr(r), buffer, Default::default());
|
||||||
|
|
||||||
|
// clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer
|
||||||
|
if !self.detect_previous_overrun {
|
||||||
|
let sr = sr(r).read();
|
||||||
|
// This read also clears the error and idle interrupt flags on v1.
|
||||||
|
rdr(r).read_volatile();
|
||||||
|
clear_interrupt_flags(r, sr);
|
||||||
|
}
|
||||||
|
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
// disable RXNE interrupt
|
||||||
|
w.set_rxneie(false);
|
||||||
|
// enable parity interrupt if not ParityNone
|
||||||
|
w.set_peie(w.pce());
|
||||||
|
});
|
||||||
|
|
||||||
|
r.cr3().modify(|w| {
|
||||||
|
// enable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||||
|
w.set_eie(true);
|
||||||
|
// enable DMA Rx Request
|
||||||
|
w.set_dmar(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
// In case of errors already pending when reception started, interrupts may have already been raised
|
||||||
|
// and lead to reception abortion (Overrun error for instance). In such a case, all interrupts
|
||||||
|
// have been disabled in interrupt handler and DMA Rx Request has been disabled.
|
||||||
|
|
||||||
|
let cr3 = r.cr3().read();
|
||||||
|
|
||||||
|
if !cr3.dmar() {
|
||||||
|
// something went wrong
|
||||||
|
// because the only way to get this flag cleared is to have an interrupt
|
||||||
|
|
||||||
|
// abort DMA transfer
|
||||||
|
ch.request_stop();
|
||||||
|
while ch.is_running() {}
|
||||||
|
|
||||||
|
let sr = sr(r).read();
|
||||||
|
// This read also clears the error and idle interrupt flags on v1.
|
||||||
|
rdr(r).read_volatile();
|
||||||
|
clear_interrupt_flags(r, sr);
|
||||||
|
|
||||||
|
if sr.pe() {
|
||||||
|
return Err(Error::Parity);
|
||||||
|
}
|
||||||
|
if sr.fe() {
|
||||||
|
return Err(Error::Framing);
|
||||||
|
}
|
||||||
|
if sr.ne() {
|
||||||
|
return Err(Error::Noise);
|
||||||
|
}
|
||||||
|
if sr.ore() {
|
||||||
|
return Err(Error::Overrun);
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear idle flag
|
||||||
|
if enable_idle_line_detection {
|
||||||
|
let sr = sr(r).read();
|
||||||
|
// This read also clears the error and idle interrupt flags on v1.
|
||||||
|
rdr(r).read_volatile();
|
||||||
|
clear_interrupt_flags(r, sr);
|
||||||
|
|
||||||
|
// enable idle interrupt
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
w.set_idleie(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
let res = poll_fn(move |cx| {
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
ch.set_waker(cx.waker());
|
||||||
|
s.rx_waker.register(cx.waker());
|
||||||
|
|
||||||
|
// SAFETY: read only and we only use Rx related flags
|
||||||
|
let sr = unsafe { sr(r).read() };
|
||||||
|
|
||||||
|
// SAFETY: only clears Rx related flags
|
||||||
|
unsafe {
|
||||||
|
// This read also clears the error and idle interrupt flags on v1.
|
||||||
|
rdr(r).read_volatile();
|
||||||
|
clear_interrupt_flags(r, sr);
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
let has_errors = sr.pe() || sr.fe() || sr.ne() || sr.ore();
|
||||||
|
|
||||||
|
if has_errors {
|
||||||
|
// all Rx interrupts and Rx DMA Request have already been cleared in interrupt handler
|
||||||
|
|
||||||
|
// stop dma transfer
|
||||||
|
ch.request_stop();
|
||||||
|
while ch.is_running() {}
|
||||||
|
|
||||||
|
if sr.pe() {
|
||||||
|
return Poll::Ready(Err(Error::Parity));
|
||||||
|
}
|
||||||
|
if sr.fe() {
|
||||||
|
return Poll::Ready(Err(Error::Framing));
|
||||||
|
}
|
||||||
|
if sr.ne() {
|
||||||
|
return Poll::Ready(Err(Error::Noise));
|
||||||
|
}
|
||||||
|
if sr.ore() {
|
||||||
|
return Poll::Ready(Err(Error::Overrun));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sr.idle() {
|
||||||
|
// Idle line
|
||||||
|
|
||||||
|
// stop dma transfer
|
||||||
|
ch.request_stop();
|
||||||
|
while ch.is_running() {}
|
||||||
|
|
||||||
|
let n = buffer_len - (ch.remaining_transfers() as usize);
|
||||||
|
|
||||||
|
return Poll::Ready(Ok(n));
|
||||||
|
} else if !ch.is_running() {
|
||||||
|
// DMA complete
|
||||||
|
return Poll::Ready(Ok(buffer_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
Poll::Pending
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// clear all interrupts and DMA Rx Request
|
||||||
|
// SAFETY: only clears Rx related flags
|
||||||
|
unsafe {
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
// disable RXNE interrupt
|
||||||
|
w.set_rxneie(false);
|
||||||
|
// disable parity interrupt
|
||||||
|
w.set_peie(false);
|
||||||
|
// disable idle line interrupt
|
||||||
|
w.set_idleie(false);
|
||||||
|
});
|
||||||
|
r.cr3().modify(|w| {
|
||||||
|
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||||
|
w.set_eie(false);
|
||||||
|
// disable DMA Rx Request
|
||||||
|
w.set_dmar(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
_inner: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
|
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||||
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
@ -225,13 +520,14 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
|
|
||||||
Self::new_inner(_inner, rx, tx, tx_dma, rx_dma, config)
|
Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_rtscts(
|
pub fn new_with_rtscts(
|
||||||
_inner: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
|
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||||
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
|
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
|
||||||
cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
|
cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
|
||||||
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
||||||
@ -251,32 +547,29 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
w.set_ctse(true);
|
w.set_ctse(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Self::new_inner(_inner, rx, tx, tx_dma, rx_dma, config)
|
Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
_inner: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
|
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||||
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
tx_dma: impl Peripheral<P = TxDma> + 'd,
|
||||||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(_inner, rx, tx, tx_dma, rx_dma);
|
into_ref!(peri, rx, tx, irq, tx_dma, rx_dma);
|
||||||
|
|
||||||
let pclk_freq = T::frequency();
|
|
||||||
|
|
||||||
// TODO: better calculation, including error checking and OVER8 if possible.
|
|
||||||
let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * T::MULTIPLIER;
|
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
|
configure(r, &config, T::frequency(), T::MULTIPLIER);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||||
|
|
||||||
r.cr2().write(|_w| {});
|
r.cr2().write(|_w| {});
|
||||||
r.brr().write_value(regs::Brr(div));
|
|
||||||
r.cr1().write(|w| {
|
r.cr1().write(|w| {
|
||||||
w.set_ue(true);
|
w.set_ue(true);
|
||||||
w.set_te(true);
|
w.set_te(true);
|
||||||
@ -295,10 +588,20 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
irq.set_handler(UartRx::<T, RxDma>::on_interrupt);
|
||||||
|
irq.unpend();
|
||||||
|
irq.enable();
|
||||||
|
|
||||||
|
// create state once!
|
||||||
|
let _s = T::state();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
tx: UartTx::new(tx_dma),
|
tx: UartTx::new(tx_dma),
|
||||||
rx: UartRx::new(rx_dma),
|
rx: UartRx {
|
||||||
phantom: PhantomData {},
|
_peri: peri,
|
||||||
|
rx_dma,
|
||||||
|
detect_previous_overrun: config.detect_previous_overrun,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +635,13 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
self.rx.blocking_read(buffer)
|
self.rx.blocking_read(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
|
||||||
|
where
|
||||||
|
RxDma: crate::usart::RxDma<T>,
|
||||||
|
{
|
||||||
|
self.rx.read_until_idle(buffer).await
|
||||||
|
}
|
||||||
|
|
||||||
/// Split the Uart into a transmitter and receiver, which is
|
/// Split the Uart into a transmitter and receiver, which is
|
||||||
/// particuarly useful when having two tasks correlating to
|
/// particuarly useful when having two tasks correlating to
|
||||||
/// transmitting and receiving.
|
/// transmitting and receiving.
|
||||||
@ -340,6 +650,15 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32) {
|
||||||
|
// TODO: better calculation, including error checking and OVER8 if possible.
|
||||||
|
let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * multiplier;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
r.brr().write_value(regs::Brr(div));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod eh02 {
|
mod eh02 {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -389,6 +708,7 @@ mod eh1 {
|
|||||||
Self::Noise => embedded_hal_1::serial::ErrorKind::Noise,
|
Self::Noise => embedded_hal_1::serial::ErrorKind::Noise,
|
||||||
Self::Overrun => embedded_hal_1::serial::ErrorKind::Overrun,
|
Self::Overrun => embedded_hal_1::serial::ErrorKind::Overrun,
|
||||||
Self::Parity => embedded_hal_1::serial::ErrorKind::Parity,
|
Self::Parity => embedded_hal_1::serial::ErrorKind::Parity,
|
||||||
|
Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -573,13 +893,30 @@ unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
pub struct State {
|
||||||
|
pub rx_waker: AtomicWaker,
|
||||||
|
pub tx_waker: AtomicWaker,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
rx_waker: AtomicWaker::new(),
|
||||||
|
tx_waker: AtomicWaker::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait BasicInstance: crate::rcc::RccPeripheral {
|
pub trait BasicInstance: crate::rcc::RccPeripheral {
|
||||||
const MULTIPLIER: u32;
|
const MULTIPLIER: u32;
|
||||||
type Interrupt: crate::interrupt::Interrupt;
|
type Interrupt: crate::interrupt::Interrupt;
|
||||||
|
|
||||||
fn regs() -> Regs;
|
fn regs() -> Regs;
|
||||||
|
fn state() -> &'static State;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FullInstance: BasicInstance {
|
pub trait FullInstance: BasicInstance {
|
||||||
@ -587,7 +924,7 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BasicInstance: sealed::BasicInstance {}
|
pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {}
|
||||||
|
|
||||||
pub trait FullInstance: sealed::FullInstance {}
|
pub trait FullInstance: sealed::FullInstance {}
|
||||||
|
|
||||||
@ -609,6 +946,11 @@ macro_rules! impl_lpuart {
|
|||||||
fn regs() -> Regs {
|
fn regs() -> Regs {
|
||||||
Regs(crate::pac::$inst.0)
|
Regs(crate::pac::$inst.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state() -> &'static crate::usart::sealed::State {
|
||||||
|
static STATE: crate::usart::sealed::State = crate::usart::sealed::State::new();
|
||||||
|
&STATE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BasicInstance for peripherals::$inst {}
|
impl BasicInstance for peripherals::$inst {}
|
||||||
|
@ -7,6 +7,7 @@ use core::fmt::Write;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, p.DMA1_CH4, NoDma, config);
|
let irq = interrupt::take!(USART1);
|
||||||
|
let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, irq, p.DMA1_CH4, NoDma, config);
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
@ -15,7 +16,8 @@ fn main() -> ! {
|
|||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, NoDma, NoDma, config);
|
let irq = interrupt::take!(USART3);
|
||||||
|
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, NoDma, NoDma, config);
|
||||||
|
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
|
||||||
use embassy_stm32::interrupt;
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{BufferedUart, Config, State, Uart};
|
use embassy_stm32::usart::{BufferedUart, Config, State};
|
||||||
use embedded_io::asynch::BufRead;
|
use embedded_io::asynch::BufRead;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
@ -16,13 +15,21 @@ async fn main(_spawner: Spawner) {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let usart = Uart::new(p.USART3, p.PD9, p.PD8, NoDma, NoDma, config);
|
|
||||||
|
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
let irq = interrupt::take!(USART3);
|
let irq = interrupt::take!(USART3);
|
||||||
let mut tx_buf = [0u8; 32];
|
let mut tx_buf = [0u8; 32];
|
||||||
let mut rx_buf = [0u8; 32];
|
let mut rx_buf = [0u8; 32];
|
||||||
let mut buf_usart = BufferedUart::new(&mut state, usart, irq, &mut tx_buf, &mut rx_buf);
|
let mut buf_usart = BufferedUart::new(
|
||||||
|
&mut state,
|
||||||
|
p.USART3,
|
||||||
|
p.PD9,
|
||||||
|
p.PD8,
|
||||||
|
irq,
|
||||||
|
&mut tx_buf,
|
||||||
|
&mut rx_buf,
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let buf = buf_usart.fill_buf().await.unwrap();
|
let buf = buf_usart.fill_buf().await.unwrap();
|
||||||
|
@ -7,6 +7,7 @@ use core::fmt::Write;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, p.DMA1_CH3, NoDma, config);
|
let irq = interrupt::take!(USART3);
|
||||||
|
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, p.DMA1_CH3, NoDma, config);
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -7,6 +7,7 @@ use core::fmt::Write;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -15,7 +16,8 @@ use {defmt_rtt as _, panic_probe as _};
|
|||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, p.DMA1_CH1, NoDma, config);
|
let irq = interrupt::take!(UART7);
|
||||||
|
let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, irq, p.DMA1_CH1, NoDma, config);
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -6,6 +6,7 @@ use cortex_m_rt::entry;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -15,7 +16,8 @@ async fn main_task() {
|
|||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, NoDma, NoDma, config);
|
let irq = interrupt::take!(UART7);
|
||||||
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, NoDma, NoDma, config);
|
||||||
|
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -8,6 +8,7 @@ use cortex_m_rt::entry;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
@ -18,7 +19,8 @@ async fn main_task() {
|
|||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_CH0, NoDma, config);
|
let irq = interrupt::take!(UART7);
|
||||||
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, NoDma, config);
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::peripherals::{DMA1_CH1, UART7};
|
use embassy_stm32::peripherals::{DMA1_CH1, UART7};
|
||||||
use embassy_stm32::usart::{Config, Uart, UartRx};
|
use embassy_stm32::usart::{Config, Uart, UartRx};
|
||||||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||||
@ -31,7 +32,8 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_CH0, p.DMA1_CH1, config);
|
let irq = interrupt::take!(UART7);
|
||||||
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, p.DMA1_CH1, config);
|
||||||
unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
|
unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
|
||||||
|
|
||||||
let (mut tx, rx) = usart.split();
|
let (mut tx, rx) = usart.split();
|
||||||
|
@ -4,13 +4,15 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, p.DMA1_CH2, p.DMA1_CH3, Config::default());
|
let irq = interrupt::take!(USART1);
|
||||||
|
let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, irq, p.DMA1_CH2, p.DMA1_CH3, Config::default());
|
||||||
|
|
||||||
usart.write(b"Hello Embassy World!\r\n").await.unwrap();
|
usart.write(b"Hello Embassy World!\r\n").await.unwrap();
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
|
||||||
use embassy_stm32::interrupt;
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{BufferedUart, Config, State, Uart};
|
use embassy_stm32::usart::{BufferedUart, Config, State};
|
||||||
use embedded_io::asynch::{Read, Write};
|
use embedded_io::asynch::{Read, Write};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
@ -21,15 +20,18 @@ async fn main(_spawner: Spawner) {
|
|||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.baudrate = 9600;
|
config.baudrate = 9600;
|
||||||
|
|
||||||
let usart = Uart::new(p.USART2, p.PA3, p.PA2, NoDma, NoDma, config);
|
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
|
let irq = interrupt::take!(USART2);
|
||||||
let mut usart = unsafe {
|
let mut usart = unsafe {
|
||||||
BufferedUart::new(
|
BufferedUart::new(
|
||||||
&mut state,
|
&mut state,
|
||||||
usart,
|
p.USART2,
|
||||||
interrupt::take!(USART2),
|
p.PA3,
|
||||||
|
p.PA2,
|
||||||
|
irq,
|
||||||
&mut TX_BUFFER,
|
&mut TX_BUFFER,
|
||||||
&mut RX_BUFFER,
|
&mut RX_BUFFER,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
@ -14,7 +15,8 @@ fn main() -> ! {
|
|||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, NoDma, NoDma, config);
|
let irq = interrupt::take!(UART4);
|
||||||
|
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, NoDma, NoDma, config);
|
||||||
|
|
||||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
info!("wrote Hello, starting echo");
|
info!("wrote Hello, starting echo");
|
||||||
|
@ -7,6 +7,7 @@ use core::fmt::Write;
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use heapless::String;
|
use heapless::String;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, p.DMA1_CH3, NoDma, config);
|
let irq = interrupt::take!(UART4);
|
||||||
|
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, p.DMA1_CH3, NoDma, config);
|
||||||
|
|
||||||
for n in 0u32.. {
|
for n in 0u32.. {
|
||||||
let mut s: String<128> = String::new();
|
let mut s: String<128> = String::new();
|
||||||
|
@ -7,6 +7,7 @@ mod example_common;
|
|||||||
use defmt::assert_eq;
|
use defmt::assert_eq;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
@ -18,22 +19,22 @@ async fn main(_spawner: Spawner) {
|
|||||||
// Arduino pins D0 and D1
|
// Arduino pins D0 and D1
|
||||||
// They're connected together with a 1K resistor.
|
// They're connected together with a 1K resistor.
|
||||||
#[cfg(feature = "stm32f103c8")]
|
#[cfg(feature = "stm32f103c8")]
|
||||||
let (tx, rx, usart) = (p.PA9, p.PA10, p.USART1);
|
let (tx, rx, usart, irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1));
|
||||||
#[cfg(feature = "stm32g491re")]
|
#[cfg(feature = "stm32g491re")]
|
||||||
let (tx, rx, usart) = (p.PC4, p.PC5, p.USART1);
|
let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
|
||||||
#[cfg(feature = "stm32g071rb")]
|
#[cfg(feature = "stm32g071rb")]
|
||||||
let (tx, rx, usart) = (p.PC4, p.PC5, p.USART1);
|
let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
|
||||||
#[cfg(feature = "stm32f429zi")]
|
#[cfg(feature = "stm32f429zi")]
|
||||||
let (tx, rx, usart) = (p.PG14, p.PG9, p.USART6);
|
let (tx, rx, usart, irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6));
|
||||||
#[cfg(feature = "stm32wb55rg")]
|
#[cfg(feature = "stm32wb55rg")]
|
||||||
let (tx, rx, usart) = (p.PA2, p.PA3, p.LPUART1);
|
let (tx, rx, usart, irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1));
|
||||||
#[cfg(feature = "stm32h755zi")]
|
#[cfg(feature = "stm32h755zi")]
|
||||||
let (tx, rx, usart) = (p.PB6, p.PB7, p.USART1);
|
let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
|
||||||
#[cfg(feature = "stm32u585ai")]
|
#[cfg(feature = "stm32u585ai")]
|
||||||
let (tx, rx, usart) = (p.PD8, p.PD9, p.USART3);
|
let (tx, rx, usart, irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3));
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(usart, rx, tx, NoDma, NoDma, config);
|
let mut usart = Uart::new(usart, rx, tx, irq, NoDma, NoDma, config);
|
||||||
|
|
||||||
// We can't send too many bytes, they have to fit in the FIFO.
|
// We can't send too many bytes, they have to fit in the FIFO.
|
||||||
// This is because we aren't sending+receiving at the same time.
|
// This is because we aren't sending+receiving at the same time.
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
mod example_common;
|
mod example_common;
|
||||||
use defmt::assert_eq;
|
use defmt::assert_eq;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::usart::{Config, Uart};
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
@ -17,22 +18,53 @@ async fn main(_spawner: Spawner) {
|
|||||||
// Arduino pins D0 and D1
|
// Arduino pins D0 and D1
|
||||||
// They're connected together with a 1K resistor.
|
// They're connected together with a 1K resistor.
|
||||||
#[cfg(feature = "stm32f103c8")]
|
#[cfg(feature = "stm32f103c8")]
|
||||||
let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH4, p.DMA1_CH5);
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
||||||
|
p.PA9,
|
||||||
|
p.PA10,
|
||||||
|
p.USART1,
|
||||||
|
interrupt::take!(USART1),
|
||||||
|
p.DMA1_CH4,
|
||||||
|
p.DMA1_CH5,
|
||||||
|
);
|
||||||
#[cfg(feature = "stm32g491re")]
|
#[cfg(feature = "stm32g491re")]
|
||||||
let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
|
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
||||||
|
(p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
|
||||||
#[cfg(feature = "stm32g071rb")]
|
#[cfg(feature = "stm32g071rb")]
|
||||||
let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2);
|
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
||||||
|
(p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
|
||||||
#[cfg(feature = "stm32f429zi")]
|
#[cfg(feature = "stm32f429zi")]
|
||||||
let (tx, rx, usart, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, p.DMA2_CH6, p.DMA2_CH1);
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
||||||
|
p.PG14,
|
||||||
|
p.PG9,
|
||||||
|
p.USART6,
|
||||||
|
interrupt::take!(USART6),
|
||||||
|
p.DMA2_CH6,
|
||||||
|
p.DMA2_CH1,
|
||||||
|
);
|
||||||
#[cfg(feature = "stm32wb55rg")]
|
#[cfg(feature = "stm32wb55rg")]
|
||||||
let (tx, rx, usart, tx_dma, rx_dma) = (p.PA2, p.PA3, p.LPUART1, p.DMA1_CH1, p.DMA1_CH2);
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
||||||
|
p.PA2,
|
||||||
|
p.PA3,
|
||||||
|
p.LPUART1,
|
||||||
|
interrupt::take!(LPUART1),
|
||||||
|
p.DMA1_CH1,
|
||||||
|
p.DMA1_CH2,
|
||||||
|
);
|
||||||
#[cfg(feature = "stm32h755zi")]
|
#[cfg(feature = "stm32h755zi")]
|
||||||
let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH0, p.DMA1_CH1);
|
let (tx, rx, usart, irq, tx_dma, rx_dma) =
|
||||||
|
(p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH0, p.DMA1_CH1);
|
||||||
#[cfg(feature = "stm32u585ai")]
|
#[cfg(feature = "stm32u585ai")]
|
||||||
let (tx, rx, usart, tx_dma, rx_dma) = (p.PD8, p.PD9, p.USART3, p.GPDMA1_CH0, p.GPDMA1_CH1);
|
let (tx, rx, usart, irq, tx_dma, rx_dma) = (
|
||||||
|
p.PD8,
|
||||||
|
p.PD9,
|
||||||
|
p.USART3,
|
||||||
|
interrupt::take!(USART3),
|
||||||
|
p.GPDMA1_CH0,
|
||||||
|
p.GPDMA1_CH1,
|
||||||
|
);
|
||||||
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let mut usart = Uart::new(usart, rx, tx, tx_dma, rx_dma, config);
|
let mut usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config);
|
||||||
|
|
||||||
// We can't send too many bytes, they have to fit in the FIFO.
|
// We can't send too many bytes, they have to fit in the FIFO.
|
||||||
// This is because we aren't sending+receiving at the same time.
|
// This is because we aren't sending+receiving at the same time.
|
||||||
|
Loading…
Reference in New Issue
Block a user