Add support for splitting stm32 usart into TX and RX
* Keeps existing API for usart, but wraps it in Tx and Rx sub-types * Adds split() method similar to nRF for getting indepdendent TX and RX parts * Implements e-h traits for TX and RX types * Add stm32h7 example
This commit is contained in:
parent
cb1be3983a
commit
e09bde9345
2 changed files with 251 additions and 75 deletions
|
@ -72,57 +72,26 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
|
pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
|
||||||
inner: T,
|
phantom: PhantomData<&'d mut T>,
|
||||||
|
tx: UartTx<'d, T, TxDma>,
|
||||||
|
rx: UartRx<'d, T, RxDma>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UartTx<'d, T: Instance, TxDma = NoDma> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
tx_dma: TxDma,
|
tx_dma: TxDma,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UartRx<'d, T: Instance, RxDma = NoDma> {
|
||||||
|
phantom: PhantomData<&'d mut T>,
|
||||||
rx_dma: RxDma,
|
rx_dma: RxDma,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
impl<'d, T: Instance, TxDma> UartTx<'d, T, TxDma> {
|
||||||
pub fn new(
|
fn new(tx_dma: TxDma) -> Self {
|
||||||
inner: impl Unborrow<Target = T> + 'd,
|
|
||||||
rx: impl Unborrow<Target = impl RxPin<T>> + 'd,
|
|
||||||
tx: impl Unborrow<Target = impl TxPin<T>> + 'd,
|
|
||||||
tx_dma: impl Unborrow<Target = TxDma> + 'd,
|
|
||||||
rx_dma: impl Unborrow<Target = RxDma> + 'd,
|
|
||||||
config: Config,
|
|
||||||
) -> Self {
|
|
||||||
unborrow!(inner, rx, tx, tx_dma, rx_dma);
|
|
||||||
|
|
||||||
T::enable();
|
|
||||||
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;
|
|
||||||
|
|
||||||
let r = inner.regs();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
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.brr().write_value(regs::Brr(div));
|
|
||||||
r.cr1().write(|w| {
|
|
||||||
w.set_ue(true);
|
|
||||||
w.set_te(true);
|
|
||||||
w.set_re(true);
|
|
||||||
w.set_m0(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,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner,
|
|
||||||
phantom: PhantomData,
|
|
||||||
tx_dma,
|
tx_dma,
|
||||||
rx_dma,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,16 +102,43 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||||
let ch = &mut self.tx_dma;
|
let ch = &mut self.tx_dma;
|
||||||
let request = ch.request();
|
let request = ch.request();
|
||||||
unsafe {
|
unsafe {
|
||||||
self.inner.regs().cr3().modify(|reg| {
|
T::regs().cr3().modify(|reg| {
|
||||||
reg.set_dmat(true);
|
reg.set_dmat(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let r = self.inner.regs();
|
let dst = tdr(T::regs());
|
||||||
let dst = tdr(r);
|
|
||||||
crate::dma::write(ch, request, buffer, dst).await;
|
crate::dma::write(ch, request, buffer, dst).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||||
|
unsafe {
|
||||||
|
let r = T::regs();
|
||||||
|
for &b in buffer {
|
||||||
|
while !sr(r).read().txe() {}
|
||||||
|
tdr(r).write_volatile(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||||
|
unsafe {
|
||||||
|
let r = T::regs();
|
||||||
|
while !sr(r).read().tc() {}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, RxDma> UartRx<'d, T, RxDma> {
|
||||||
|
fn new(rx_dma: RxDma) -> Self {
|
||||||
|
Self {
|
||||||
|
rx_dma,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
RxDma: crate::usart::RxDma<T>,
|
RxDma: crate::usart::RxDma<T>,
|
||||||
|
@ -150,11 +146,11 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||||
let ch = &mut self.rx_dma;
|
let ch = &mut self.rx_dma;
|
||||||
let request = ch.request();
|
let request = ch.request();
|
||||||
unsafe {
|
unsafe {
|
||||||
self.inner.regs().cr3().modify(|reg| {
|
T::regs().cr3().modify(|reg| {
|
||||||
reg.set_dmar(true);
|
reg.set_dmar(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let r = self.inner.regs();
|
let r = T::regs();
|
||||||
let src = rdr(r);
|
let src = rdr(r);
|
||||||
crate::dma::read(ch, request, src, buffer).await;
|
crate::dma::read(ch, request, src, buffer).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -162,7 +158,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||||
|
|
||||||
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let r = self.inner.regs();
|
let r = T::regs();
|
||||||
for b in buffer {
|
for b in buffer {
|
||||||
loop {
|
loop {
|
||||||
let sr = sr(r).read();
|
let sr = sr(r).read();
|
||||||
|
@ -187,36 +183,96 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||||
|
pub fn new(
|
||||||
|
_inner: impl Unborrow<Target = T> + 'd,
|
||||||
|
rx: impl Unborrow<Target = impl RxPin<T>> + 'd,
|
||||||
|
tx: impl Unborrow<Target = impl TxPin<T>> + 'd,
|
||||||
|
tx_dma: impl Unborrow<Target = TxDma> + 'd,
|
||||||
|
rx_dma: impl Unborrow<Target = RxDma> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
unborrow!(_inner, rx, tx, tx_dma, rx_dma);
|
||||||
|
|
||||||
|
T::enable();
|
||||||
|
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;
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
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.brr().write_value(regs::Brr(div));
|
||||||
|
r.cr1().write(|w| {
|
||||||
|
w.set_ue(true);
|
||||||
|
w.set_te(true);
|
||||||
|
w.set_re(true);
|
||||||
|
w.set_m0(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,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
phantom: PhantomData,
|
||||||
|
tx: UartTx::new(tx_dma),
|
||||||
|
rx: UartRx::new(rx_dma),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
TxDma: crate::usart::TxDma<T>,
|
||||||
|
{
|
||||||
|
self.tx.write(buffer).await
|
||||||
|
}
|
||||||
|
|
||||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||||
unsafe {
|
self.tx.blocking_write(buffer)
|
||||||
let r = self.inner.regs();
|
|
||||||
for &b in buffer {
|
|
||||||
while !sr(r).read().txe() {}
|
|
||||||
tdr(r).write_volatile(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||||
unsafe {
|
self.tx.blocking_flush()
|
||||||
let r = self.inner.regs();
|
|
||||||
while !sr(r).read().tc() {}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
|
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
RxDma: crate::usart::RxDma<T>,
|
||||||
|
{
|
||||||
|
self.rx.read(buffer).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
|
self.rx.blocking_read(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Split the Uart into a transmitter and receiver, which is
|
||||||
|
/// particuarly useful when having two tasks correlating to
|
||||||
|
/// transmitting and receiving.
|
||||||
|
pub fn split(self) -> (UartTx<'d, T, TxDma>, UartRx<'d, T, RxDma>) {
|
||||||
|
(self.tx, self.rx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod eh02 {
|
mod eh02 {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::serial::Read<u8>
|
impl<'d, T: Instance, RxDma> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, RxDma> {
|
||||||
for Uart<'d, T, TxDma, RxDma>
|
|
||||||
{
|
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||||
let r = self.inner.regs();
|
let r = T::regs();
|
||||||
unsafe {
|
unsafe {
|
||||||
let sr = sr(r).read();
|
let sr = sr(r).read();
|
||||||
if sr.pe() {
|
if sr.pe() {
|
||||||
|
@ -240,6 +296,25 @@ mod eh02 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, TxDma> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, TxDma> {
|
||||||
|
type Error = Error;
|
||||||
|
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
|
||||||
|
self.blocking_write(buffer)
|
||||||
|
}
|
||||||
|
fn bflush(&mut self) -> Result<(), Self::Error> {
|
||||||
|
self.blocking_flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::serial::Read<u8>
|
||||||
|
for Uart<'d, T, TxDma, RxDma>
|
||||||
|
{
|
||||||
|
type Error = Error;
|
||||||
|
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||||
|
embedded_hal_02::serial::Read::read(&mut self.rx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write<u8>
|
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write<u8>
|
||||||
for Uart<'d, T, TxDma, RxDma>
|
for Uart<'d, T, TxDma, RxDma>
|
||||||
{
|
{
|
||||||
|
@ -273,12 +348,48 @@ mod eh1 {
|
||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, TxDma> embedded_hal_1::serial::ErrorType for UartTx<'d, T, TxDma> {
|
||||||
|
type Error = Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, RxDma> embedded_hal_1::serial::ErrorType for UartRx<'d, T, RxDma> {
|
||||||
|
type Error = Error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
|
|
||||||
|
impl<'d, T: Instance, TxDma> embedded_hal_async::serial::Write for UartTx<'d, T, TxDma>
|
||||||
|
where
|
||||||
|
TxDma: crate::usart::TxDma<T>,
|
||||||
|
{
|
||||||
|
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||||
|
|
||||||
|
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
|
self.write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||||
|
|
||||||
|
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||||
|
async move { Ok(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, RxDma> embedded_hal_async::serial::Read for UartRx<'d, T, RxDma>
|
||||||
|
where
|
||||||
|
RxDma: crate::usart::RxDma<T>,
|
||||||
|
{
|
||||||
|
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||||
|
|
||||||
|
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||||
|
self.read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_async::serial::Write for Uart<'d, T, TxDma, RxDma>
|
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_async::serial::Write for Uart<'d, T, TxDma, RxDma>
|
||||||
where
|
where
|
||||||
TxDma: crate::usart::TxDma<T>,
|
TxDma: crate::usart::TxDma<T>,
|
||||||
|
@ -329,7 +440,6 @@ mod buffered {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StateInner<'d, T: Instance> {
|
struct StateInner<'d, T: Instance> {
|
||||||
uart: Uart<'d, T, NoDma, NoDma>,
|
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
|
|
||||||
rx_waker: WakerRegistration,
|
rx_waker: WakerRegistration,
|
||||||
|
@ -351,14 +461,14 @@ mod buffered {
|
||||||
impl<'d, T: Instance> BufferedUart<'d, T> {
|
impl<'d, T: Instance> BufferedUart<'d, T> {
|
||||||
pub unsafe fn new(
|
pub unsafe fn new(
|
||||||
state: &'d mut State<'d, T>,
|
state: &'d mut State<'d, T>,
|
||||||
uart: Uart<'d, T, NoDma, NoDma>,
|
_uart: Uart<'d, T, NoDma, NoDma>,
|
||||||
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
irq: impl Unborrow<Target = T::Interrupt> + 'd,
|
||||||
tx_buffer: &'d mut [u8],
|
tx_buffer: &'d mut [u8],
|
||||||
rx_buffer: &'d mut [u8],
|
rx_buffer: &'d mut [u8],
|
||||||
) -> BufferedUart<'d, T> {
|
) -> BufferedUart<'d, T> {
|
||||||
unborrow!(irq);
|
unborrow!(irq);
|
||||||
|
|
||||||
let r = uart.inner.regs();
|
let r = T::regs();
|
||||||
r.cr1().modify(|w| {
|
r.cr1().modify(|w| {
|
||||||
w.set_rxneie(true);
|
w.set_rxneie(true);
|
||||||
w.set_idleie(true);
|
w.set_idleie(true);
|
||||||
|
@ -366,7 +476,6 @@ mod buffered {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
|
inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
|
||||||
uart,
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
tx: RingBuffer::new(tx_buffer),
|
tx: RingBuffer::new(tx_buffer),
|
||||||
tx_waker: WakerRegistration::new(),
|
tx_waker: WakerRegistration::new(),
|
||||||
|
@ -383,7 +492,7 @@ mod buffered {
|
||||||
Self: 'd,
|
Self: 'd,
|
||||||
{
|
{
|
||||||
fn on_rx(&mut self) {
|
fn on_rx(&mut self) {
|
||||||
let r = self.uart.inner.regs();
|
let r = T::regs();
|
||||||
unsafe {
|
unsafe {
|
||||||
let sr = sr(r).read();
|
let sr = sr(r).read();
|
||||||
clear_interrupt_flags(r, sr);
|
clear_interrupt_flags(r, sr);
|
||||||
|
@ -425,7 +534,7 @@ mod buffered {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_tx(&mut self) {
|
fn on_tx(&mut self) {
|
||||||
let r = self.uart.inner.regs();
|
let r = T::regs();
|
||||||
unsafe {
|
unsafe {
|
||||||
if sr(r).read().txe() {
|
if sr(r).read().txe() {
|
||||||
let buf = self.tx.pop_buf();
|
let buf = self.tx.pop_buf();
|
||||||
|
@ -575,7 +684,7 @@ unsafe fn clear_interrupt_flags(r: crate::pac::usart::Usart, sr: regs::Ixr) {
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
pub trait Instance {
|
pub trait Instance {
|
||||||
fn regs(&self) -> crate::pac::usart::Usart;
|
fn regs() -> crate::pac::usart::Usart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +704,7 @@ dma_trait!(RxDma, Instance);
|
||||||
foreach_interrupt!(
|
foreach_interrupt!(
|
||||||
($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
|
($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
|
||||||
impl sealed::Instance for peripherals::$inst {
|
impl sealed::Instance for peripherals::$inst {
|
||||||
fn regs(&self) -> crate::pac::usart::Usart {
|
fn regs() -> crate::pac::usart::Usart {
|
||||||
crate::pac::$inst
|
crate::pac::$inst
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
67
examples/stm32h7/src/bin/usart_split.rs
Normal file
67
examples/stm32h7/src/bin/usart_split.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
#[path = "../example_common.rs"]
|
||||||
|
mod example_common;
|
||||||
|
use embassy::blocking_mutex::raw::NoopRawMutex;
|
||||||
|
use embassy::channel::mpsc::{self, Channel, Sender};
|
||||||
|
use embassy::executor::Spawner;
|
||||||
|
use embassy::util::Forever;
|
||||||
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::{
|
||||||
|
peripherals::{DMA1_CH1, UART7},
|
||||||
|
usart::{Config, Uart, UartRx},
|
||||||
|
Peripherals,
|
||||||
|
};
|
||||||
|
use example_common::*;
|
||||||
|
|
||||||
|
#[embassy::task]
|
||||||
|
async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
|
||||||
|
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||||
|
info!("wrote Hello, starting echo");
|
||||||
|
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
|
loop {
|
||||||
|
unwrap!(usart.blocking_read(&mut buf));
|
||||||
|
unwrap!(usart.blocking_write(&buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CHANNEL: Forever<Channel<NoopRawMutex, [u8; 8], 1>> = Forever::new();
|
||||||
|
|
||||||
|
#[embassy::main]
|
||||||
|
async fn main(spawner: Spawner, p: Peripherals) -> ! {
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let config = Config::default();
|
||||||
|
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_CH0, p.DMA1_CH1, config);
|
||||||
|
unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
|
||||||
|
|
||||||
|
let (mut tx, rx) = usart.split();
|
||||||
|
|
||||||
|
let c = CHANNEL.put(Channel::new());
|
||||||
|
let (s, mut r) = mpsc::split(c);
|
||||||
|
|
||||||
|
unwrap!(spawner.spawn(reader(rx, s)));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(buf) = r.recv().await {
|
||||||
|
info!("writing...");
|
||||||
|
unwrap!(tx.write(&buf).await);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy::task]
|
||||||
|
async fn reader(
|
||||||
|
mut rx: UartRx<'static, UART7, DMA1_CH1>,
|
||||||
|
s: Sender<'static, NoopRawMutex, [u8; 8], 1>,
|
||||||
|
) {
|
||||||
|
let mut buf = [0; 8];
|
||||||
|
loop {
|
||||||
|
info!("reading...");
|
||||||
|
unwrap!(rx.read(&mut buf).await);
|
||||||
|
unwrap!(s.send(buf).await);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue