summaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorBob McWhirter <bmcwhirt@redhat.com>2021-06-30 14:37:35 -0400
committerBob McWhirter <bmcwhirt@redhat.com>2021-07-01 11:30:54 -0400
commit497d3aa15383c627adf3873ac151bad8826ca7c8 (patch)
tree01d4d28185b4439871284dd58a9126830301a113 /embassy-stm32
parente55c89f890d6ca6eaf568e1f701643525c999ebc (diff)
downloadembassy-497d3aa15383c627adf3873ac151bad8826ca7c8.zip
Add USARTv3 support.
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/usart/mod.rs61
-rw-r--r--embassy-stm32/src/usart/v1.rs45
-rw-r--r--embassy-stm32/src/usart/v3.rs120
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(())
+ }
+}