From 852ca5a1c5c551551265f78107994ba7c156c126 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 15 May 2021 03:52:58 +0200 Subject: [PATCH] stm32/usart_v1: implement tx --- embassy-stm32-examples/src/bin/usart.rs | 8 +- embassy-stm32/src/{usart.rs => usart/mod.rs} | 63 +++------- embassy-stm32/src/usart/usart_v1.rs | 126 +++++++++++++++++++ 3 files changed, 150 insertions(+), 47 deletions(-) rename embassy-stm32/src/{usart.rs => usart/mod.rs} (58%) create mode 100644 embassy-stm32/src/usart/usart_v1.rs diff --git a/embassy-stm32-examples/src/bin/usart.rs b/embassy-stm32-examples/src/bin/usart.rs index bf6008311..e3d323da7 100644 --- a/embassy-stm32-examples/src/bin/usart.rs +++ b/embassy-stm32-examples/src/bin/usart.rs @@ -7,6 +7,7 @@ #[path = "../example_common.rs"] mod example_common; +use cortex_m::prelude::_embedded_hal_blocking_serial_Write; use embassy::executor::Executor; use embassy::time::Clock; use embassy::util::Forever; @@ -22,9 +23,12 @@ async fn main_task() { let p = embassy_stm32::init(Default::default()); let config = Config::default(); - let usart = Uart::new(p.USART3, p.PD9, p.PD8, NoPin, NoPin, config); + let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); - // TODO make it actually do something + loop { + info!("wrote"); + usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap(); + } } struct ZeroClock; diff --git a/embassy-stm32/src/usart.rs b/embassy-stm32/src/usart/mod.rs similarity index 58% rename from embassy-stm32/src/usart.rs rename to embassy-stm32/src/usart/mod.rs index e4f77398f..cb1ebf494 100644 --- a/embassy-stm32/src/usart.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -1,58 +1,31 @@ #![macro_use] -use core::marker::PhantomData; +#[cfg_attr(feature = "_usart_v1", path = "usart_v1.rs")] +#[cfg_attr(feature = "_usart_v2", path = "usart_v2.rs")] +mod usart; -use embassy::util::Unborrow; -use embassy_extras::unborrow; +pub use usart::*; -use crate::gpio::{NoPin, Pin}; -use crate::pac::usart::{regs, vals, Usart}; -use crate::peripherals; +use crate::gpio::Pin; +use crate::pac::usart::Usart; +/// Serial error +#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[non_exhaustive] -pub struct Config { - pub baudrate: u32, - pub data_bits: u8, - pub stop_bits: u8, -} - -impl Default for Config { - fn default() -> Self { - Self { - baudrate: 115200, - data_bits: 8, - stop_bits: 1, - } - } -} - -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, - rx: impl Unborrow>, - tx: impl Unborrow>, - cts: impl Unborrow>, - rts: impl Unborrow>, - config: Config, - ) -> Self { - unborrow!(inner, rx, tx, cts, rts); - - Self { - inner, - phantom: PhantomData, - } - } +pub enum Error { + /// Framing error + Framing, + /// Noise error + Noise, + /// RX buffer overrun + Overrun, + /// Parity check error + Parity, } pub(crate) mod sealed { - use crate::gpio::{OptionalPin, Pin}; - use super::*; + pub trait Instance { fn regs(&self) -> Usart; } diff --git a/embassy-stm32/src/usart/usart_v1.rs b/embassy-stm32/src/usart/usart_v1.rs new file mode 100644 index 000000000..d8b6cabe8 --- /dev/null +++ b/embassy-stm32/src/usart/usart_v1.rs @@ -0,0 +1,126 @@ +use core::marker::PhantomData; + +use embassy::util::Unborrow; +use embassy_extras::unborrow; + +use crate::gpio::{NoPin, Pin}; +use crate::pac::usart::{regs, vals, Usart}; +use crate::peripherals; + +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>, +} + +impl<'d, T: Instance> Uart<'d, T> { + pub fn new( + inner: impl Unborrow, + rx: impl Unborrow>, + tx: impl Unborrow>, + config: Config, + pclk_freq: u32, + ) -> Self { + unborrow!(inner, rx, tx); + + // TODO: enable in RCC + + // TODO: better calculation, including error checking and OVER8 if possible. + let div = (pclk_freq + (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(vals::M::M8); + 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, + } + } +} + +impl<'d, T: Instance> embedded_hal::blocking::serial::Write 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.sr().read().txe() {} + r.dr().write_value(regs::Dr(b as u32)) + } + } + Ok(()) + } + fn bflush(&mut self) -> Result<(), Self::Error> { + unsafe { + let r = self.inner.regs(); + while !r.sr().read().tc() {} + } + Ok(()) + } +}