diff options
author | Bob McWhirter <bmcwhirt@redhat.com> | 2021-06-30 14:37:35 -0400 |
---|---|---|
committer | Bob McWhirter <bmcwhirt@redhat.com> | 2021-07-01 11:30:54 -0400 |
commit | 497d3aa15383c627adf3873ac151bad8826ca7c8 (patch) | |
tree | 01d4d28185b4439871284dd58a9126830301a113 /embassy-stm32 | |
parent | e55c89f890d6ca6eaf568e1f701643525c999ebc (diff) | |
download | embassy-497d3aa15383c627adf3873ac151bad8826ca7c8.zip |
Add USARTv3 support.
Diffstat (limited to 'embassy-stm32')
-rw-r--r-- | embassy-stm32/src/usart/mod.rs | 61 | ||||
-rw-r--r-- | embassy-stm32/src/usart/v1.rs | 45 | ||||
-rw-r--r-- | embassy-stm32/src/usart/v3.rs | 120 |
3 files changed, 174 insertions, 52 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index a75793f8..b957a99c 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -1,7 +1,8 @@ #![macro_use] -#[cfg_attr(usart_v1, path = "v1.rs")] -#[cfg_attr(usart_v2, path = "v2.rs")] +//#[cfg_attr(usart_v1, path = "v1.rs")] +//#[cfg_attr(usart_v2, path = "v2.rs")] +#[cfg_attr(usart_v3, path = "v3.rs")] mod _version; use crate::peripherals; pub use _version::*; @@ -10,6 +11,51 @@ use crate::gpio::Pin; use crate::pac::usart::Usart; use crate::rcc::RccPeripheral; +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum DataBits { + DataBits8, + DataBits9, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Parity { + ParityNone, + ParityEven, + ParityOdd, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum StopBits { + #[doc = "1 stop bit"] + STOP1, + #[doc = "0.5 stop bits"] + STOP0P5, + #[doc = "2 stop bits"] + STOP2, + #[doc = "1.5 stop bits"] + STOP1P5, +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct Config { + pub baudrate: u32, + pub data_bits: DataBits, + pub stop_bits: StopBits, + pub parity: Parity, +} + +impl Default for Config { + fn default() -> Self { + Self { + baudrate: 115200, + data_bits: DataBits::DataBits8, + stop_bits: StopBits::STOP1, + parity: Parity::ParityNone, + } + } +} + /// Serial error #[derive(Debug, Eq, PartialEq, Copy, Clone)] #[non_exhaustive] @@ -27,7 +73,7 @@ pub enum Error { pub(crate) mod sealed { use super::*; - #[cfg(dma)] + #[cfg(any(dma, dmamux))] use crate::dma::WriteDma; pub trait Instance { @@ -49,10 +95,10 @@ pub(crate) mod sealed { fn af_num(&self) -> u8; } - #[cfg(dma)] + #[cfg(any(dma, dmamux))] pub trait RxDma<T: Instance> {} - #[cfg(dma)] + #[cfg(any(dma, dmamux))] pub trait TxDma<T: Instance>: WriteDma<T> {} } @@ -63,9 +109,10 @@ pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {} pub trait CkPin<T: Instance>: sealed::CkPin<T> {} -#[cfg(dma)] +#[cfg(any(dma, dmamux))] pub trait RxDma<T: Instance>: sealed::RxDma<T> {} -#[cfg(dma)] + +#[cfg(any(dma, dmamux))] pub trait TxDma<T: Instance>: sealed::TxDma<T> {} crate::pac::peripherals!( diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs index 6c5a1244..16993895 100644 --- a/embassy-stm32/src/usart/v1.rs +++ b/embassy-stm32/src/usart/v1.rs @@ -7,51 +7,6 @@ use crate::pac::usart::{regs, vals}; use super::*; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum DataBits { - DataBits8, - DataBits9, -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum Parity { - ParityNone, - ParityEven, - ParityOdd, -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum StopBits { - #[doc = "1 stop bit"] - STOP1, - #[doc = "0.5 stop bits"] - STOP0P5, - #[doc = "2 stop bits"] - STOP2, - #[doc = "1.5 stop bits"] - STOP1P5, -} - -#[non_exhaustive] -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct Config { - pub baudrate: u32, - pub data_bits: DataBits, - pub stop_bits: StopBits, - pub parity: Parity, -} - -impl Default for Config { - fn default() -> Self { - Self { - baudrate: 115200, - data_bits: DataBits::DataBits8, - stop_bits: StopBits::STOP1, - parity: Parity::ParityNone, - } - } -} - pub struct Uart<'d, T: Instance> { inner: T, phantom: PhantomData<&'d mut T>, diff --git a/embassy-stm32/src/usart/v3.rs b/embassy-stm32/src/usart/v3.rs new file mode 100644 index 00000000..32850c9c --- /dev/null +++ b/embassy-stm32/src/usart/v3.rs @@ -0,0 +1,120 @@ +use core::marker::PhantomData; + +use embassy::util::Unborrow; +use embassy_extras::unborrow; + +use crate::pac::usart::{regs, vals}; + +use super::*; + +pub struct Uart<'d, T: Instance> { + inner: T, + phantom: PhantomData<&'d mut T>, +} + +impl<'d, T: Instance> Uart<'d, T> { + pub fn new( + inner: impl Unborrow<Target = T>, + rx: impl Unborrow<Target = impl RxPin<T>>, + tx: impl Unborrow<Target = impl TxPin<T>>, + config: Config, + ) -> Self { + unborrow!(inner, rx, tx); + + 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()); + tx.set_as_af(tx.af_num()); + + 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_m(0, 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, + }); + }); + r.cr2().write(|_w| {}); + r.cr3().write(|_w| {}); + } + + Self { + inner, + phantom: PhantomData, + } + } + + #[cfg(dma)] + pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> { + unsafe { + self.inner.regs().cr3().modify(|reg| { + reg.set_dmat(true); + }); + } + let r = self.inner.regs(); + let dst = r.dr().ptr() as *mut u8; + ch.transfer(buffer, dst).await; + Ok(()) + } + + pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + unsafe { + let r = self.inner.regs(); + for b in buffer { + loop { + let sr = r.isr().read(); + if sr.pe() { + r.rdr().read(); + return Err(Error::Parity); + } else if sr.fe() { + r.rdr().read(); + return Err(Error::Framing); + } else if sr.ne() { + r.rdr().read(); + return Err(Error::Noise); + } else if sr.ore() { + r.rdr().read(); + return Err(Error::Overrun); + } else if sr.rxne() { + break; + } + } + *b = r.rdr().read().0 as u8; + } + } + Ok(()) + } +} + +impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T> { + type Error = Error; + fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + unsafe { + let r = self.inner.regs(); + for &b in buffer { + while !r.isr().read().txe() {} + r.tdr().write_value(regs::Tdr(b as u32)) + } + } + Ok(()) + } + fn bflush(&mut self) -> Result<(), Self::Error> { + unsafe { + let r = self.inner.regs(); + while !r.isr().read().tc() {} + } + Ok(()) + } +} |