diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-07-15 00:48:41 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-07-15 00:52:37 +0200 |
| commit | 4361cb15f18730b5b73171267e5d44fb244c8ec0 (patch) | |
| tree | 690a49d9e7cac2c07946fc2bdee5f69bb7e1b7b8 | |
| parent | 71c8d7aa7d84175810b6495c72d3767179d6b341 (diff) | |
stm32/usart: merge v2 and v3 (they're identical)
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/v2.rs | 51 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/v3.rs | 149 | ||||
| m--------- | stm32-data | 0 |
4 files changed, 42 insertions, 159 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index ddaed5bb9..c3ac8bc59 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | 2 | ||
| 3 | #[cfg_attr(usart_v1, path = "v1.rs")] | 3 | #[cfg_attr(usart_v1, path = "v1.rs")] |
| 4 | #[cfg_attr(usart_v2, path = "v2.rs")] | 4 | #[cfg_attr(usart_v2, path = "v2.rs")] |
| 5 | #[cfg_attr(usart_v3, path = "v3.rs")] | ||
| 6 | mod _version; | 5 | mod _version; |
| 7 | use crate::peripherals; | 6 | use crate::peripherals; |
| 8 | pub use _version::*; | 7 | pub use _version::*; |
diff --git a/embassy-stm32/src/usart/v2.rs b/embassy-stm32/src/usart/v2.rs index 22041b4aa..b958c0a0c 100644 --- a/embassy-stm32/src/usart/v2.rs +++ b/embassy-stm32/src/usart/v2.rs | |||
| @@ -3,29 +3,38 @@ use core::marker::PhantomData; | |||
| 3 | use embassy::util::Unborrow; | 3 | use embassy::util::Unborrow; |
| 4 | use embassy_extras::unborrow; | 4 | use embassy_extras::unborrow; |
| 5 | 5 | ||
| 6 | use crate::pac::usart::vals; | 6 | use crate::pac::usart::{regs, vals}; |
| 7 | 7 | ||
| 8 | use super::*; | 8 | use super::*; |
| 9 | use core::future::Future; | ||
| 10 | use futures::TryFutureExt; | ||
| 9 | 11 | ||
| 10 | pub struct Uart<'d, T: Instance> { | 12 | use crate::dma_traits::NoDma; |
| 13 | |||
| 14 | #[allow(dead_code)] | ||
| 15 | pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { | ||
| 11 | inner: T, | 16 | inner: T, |
| 12 | phantom: PhantomData<&'d mut T>, | 17 | phantom: PhantomData<&'d mut T>, |
| 18 | tx_dma: TxDma, | ||
| 19 | rx_dma: RxDma, | ||
| 13 | } | 20 | } |
| 14 | 21 | ||
| 15 | impl<'d, T: Instance> Uart<'d, T> { | 22 | impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { |
| 16 | pub fn new( | 23 | pub fn new( |
| 17 | inner: impl Unborrow<Target = T>, | 24 | inner: impl Unborrow<Target = T>, |
| 18 | rx: impl Unborrow<Target = impl RxPin<T>>, | 25 | rx: impl Unborrow<Target = impl RxPin<T>>, |
| 19 | tx: impl Unborrow<Target = impl TxPin<T>>, | 26 | tx: impl Unborrow<Target = impl TxPin<T>>, |
| 27 | tx_dma: impl Unborrow<Target = TxDma>, | ||
| 28 | rx_dma: impl Unborrow<Target = RxDma>, | ||
| 20 | config: Config, | 29 | config: Config, |
| 21 | ) -> Self { | 30 | ) -> Self { |
| 22 | unborrow!(inner, rx, tx); | 31 | unborrow!(inner, rx, tx, tx_dma, rx_dma); |
| 23 | 32 | ||
| 24 | T::enable(); | 33 | T::enable(); |
| 25 | let pclk_freq = T::frequency(); | 34 | let pclk_freq = T::frequency(); |
| 26 | 35 | ||
| 27 | // TODO: better calculation, including error checking and OVER8 if possible. | 36 | // TODO: better calculation, including error checking and OVER8 if possible. |
| 28 | let div = pclk_freq.0 / config.baudrate; | 37 | let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate; |
| 29 | 38 | ||
| 30 | let r = inner.regs(); | 39 | let r = inner.regs(); |
| 31 | 40 | ||
| @@ -50,16 +59,23 @@ impl<'d, T: Instance> Uart<'d, T> { | |||
| 50 | _ => vals::Ps::EVEN, | 59 | _ => vals::Ps::EVEN, |
| 51 | }); | 60 | }); |
| 52 | }); | 61 | }); |
| 62 | r.cr2().write(|_w| {}); | ||
| 63 | r.cr3().write(|_w| {}); | ||
| 53 | } | 64 | } |
| 54 | 65 | ||
| 55 | Self { | 66 | Self { |
| 56 | inner, | 67 | inner, |
| 57 | phantom: PhantomData, | 68 | phantom: PhantomData, |
| 69 | tx_dma, | ||
| 70 | rx_dma, | ||
| 58 | } | 71 | } |
| 59 | } | 72 | } |
| 60 | 73 | ||
| 61 | #[cfg(bdma)] | 74 | async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error> |
| 62 | pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> { | 75 | where |
| 76 | TxDma: crate::usart::TxDma<T>, | ||
| 77 | { | ||
| 78 | let ch = &mut self.tx_dma; | ||
| 63 | unsafe { | 79 | unsafe { |
| 64 | self.inner.regs().cr3().modify(|reg| { | 80 | self.inner.regs().cr3().modify(|reg| { |
| 65 | reg.set_dmat(true); | 81 | reg.set_dmat(true); |
| @@ -83,6 +99,9 @@ impl<'d, T: Instance> Uart<'d, T> { | |||
| 83 | } else if sr.fe() { | 99 | } else if sr.fe() { |
| 84 | r.rdr().read(); | 100 | r.rdr().read(); |
| 85 | return Err(Error::Framing); | 101 | return Err(Error::Framing); |
| 102 | } else if sr.nf() { | ||
| 103 | r.rdr().read(); | ||
| 104 | return Err(Error::Noise); | ||
| 86 | } else if sr.ore() { | 105 | } else if sr.ore() { |
| 87 | r.rdr().read(); | 106 | r.rdr().read(); |
| 88 | return Err(Error::Overrun); | 107 | return Err(Error::Overrun); |
| @@ -97,14 +116,16 @@ impl<'d, T: Instance> Uart<'d, T> { | |||
| 97 | } | 116 | } |
| 98 | } | 117 | } |
| 99 | 118 | ||
| 100 | impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T> { | 119 | impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write<u8> |
| 120 | for Uart<'d, T, NoDma, RxDma> | ||
| 121 | { | ||
| 101 | type Error = Error; | 122 | type Error = Error; |
| 102 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 123 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| 103 | unsafe { | 124 | unsafe { |
| 104 | let r = self.inner.regs(); | 125 | let r = self.inner.regs(); |
| 105 | for &b in buffer { | 126 | for &b in buffer { |
| 106 | while !r.isr().read().txe() {} | 127 | while !r.isr().read().txe() {} |
| 107 | r.tdr().write(|w| w.set_dr(b as u16)); | 128 | r.tdr().write_value(regs::Dr(b as u32)) |
| 108 | } | 129 | } |
| 109 | } | 130 | } |
| 110 | Ok(()) | 131 | Ok(()) |
| @@ -117,3 +138,15 @@ impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T> | |||
| 117 | Ok(()) | 138 | Ok(()) |
| 118 | } | 139 | } |
| 119 | } | 140 | } |
| 141 | |||
| 142 | // rustfmt::skip because intellij removes the 'where' claus on the associated type. | ||
| 143 | #[rustfmt::skip] | ||
| 144 | impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma> | ||
| 145 | where TxDma: crate::usart::TxDma<T> | ||
| 146 | { | ||
| 147 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>>; | ||
| 148 | |||
| 149 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 150 | self.write_dma(buf).map_err(|_| embassy_traits::uart::Error::Other) | ||
| 151 | } | ||
| 152 | } | ||
diff --git a/embassy-stm32/src/usart/v3.rs b/embassy-stm32/src/usart/v3.rs deleted file mode 100644 index 4d78abb24..000000000 --- a/embassy-stm32/src/usart/v3.rs +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | |||
| 3 | use embassy::util::Unborrow; | ||
| 4 | use embassy_extras::unborrow; | ||
| 5 | |||
| 6 | use crate::pac::usart::{regs, vals}; | ||
| 7 | |||
| 8 | use super::*; | ||
| 9 | use core::future::Future; | ||
| 10 | use futures::TryFutureExt; | ||
| 11 | |||
| 12 | use crate::dma_traits::NoDma; | ||
| 13 | |||
| 14 | #[allow(dead_code)] | ||
| 15 | pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { | ||
| 16 | inner: T, | ||
| 17 | phantom: PhantomData<&'d mut T>, | ||
| 18 | tx_dma: TxDma, | ||
| 19 | rx_dma: RxDma, | ||
| 20 | } | ||
| 21 | |||
| 22 | impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | ||
| 23 | pub fn new( | ||
| 24 | inner: impl Unborrow<Target = T>, | ||
| 25 | rx: impl Unborrow<Target = impl RxPin<T>>, | ||
| 26 | tx: impl Unborrow<Target = impl TxPin<T>>, | ||
| 27 | tx_dma: impl Unborrow<Target = TxDma>, | ||
| 28 | rx_dma: impl Unborrow<Target = RxDma>, | ||
| 29 | config: Config, | ||
| 30 | ) -> Self { | ||
| 31 | unborrow!(inner, rx, tx, tx_dma, rx_dma); | ||
| 32 | |||
| 33 | // Uncomment once we find all of the H7's UART clocks. | ||
| 34 | T::enable(); | ||
| 35 | let pclk_freq = T::frequency(); | ||
| 36 | |||
| 37 | // TODO: better calculation, including error checking and OVER8 if possible. | ||
| 38 | let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate; | ||
| 39 | |||
| 40 | let r = inner.regs(); | ||
| 41 | |||
| 42 | unsafe { | ||
| 43 | rx.set_as_af(rx.af_num()); | ||
| 44 | tx.set_as_af(tx.af_num()); | ||
| 45 | |||
| 46 | r.brr().write_value(regs::Brr(div)); | ||
| 47 | r.cr1().write(|w| { | ||
| 48 | w.set_ue(true); | ||
| 49 | w.set_te(true); | ||
| 50 | w.set_re(true); | ||
| 51 | w.set_m(0, vals::M0::BIT8); | ||
| 52 | w.set_pce(config.parity != Parity::ParityNone); | ||
| 53 | w.set_ps(match config.parity { | ||
| 54 | Parity::ParityOdd => vals::Ps::ODD, | ||
| 55 | Parity::ParityEven => vals::Ps::EVEN, | ||
| 56 | _ => vals::Ps::EVEN, | ||
| 57 | }); | ||
| 58 | }); | ||
| 59 | r.cr2().write(|_w| {}); | ||
| 60 | r.cr3().write(|_w| {}); | ||
| 61 | } | ||
| 62 | |||
| 63 | Self { | ||
| 64 | inner, | ||
| 65 | phantom: PhantomData, | ||
| 66 | tx_dma, | ||
| 67 | rx_dma, | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error> | ||
| 72 | where | ||
| 73 | TxDma: crate::usart::TxDma<T>, | ||
| 74 | { | ||
| 75 | let ch = &mut self.tx_dma; | ||
| 76 | unsafe { | ||
| 77 | self.inner.regs().cr3().modify(|reg| { | ||
| 78 | reg.set_dmat(true); | ||
| 79 | }); | ||
| 80 | } | ||
| 81 | let r = self.inner.regs(); | ||
| 82 | let dst = r.tdr().ptr() as *mut u8; | ||
| 83 | ch.transfer(buffer, dst).await; | ||
| 84 | Ok(()) | ||
| 85 | } | ||
| 86 | |||
| 87 | pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | ||
| 88 | unsafe { | ||
| 89 | let r = self.inner.regs(); | ||
| 90 | for b in buffer { | ||
| 91 | loop { | ||
| 92 | let sr = r.isr().read(); | ||
| 93 | if sr.pe() { | ||
| 94 | r.rdr().read(); | ||
| 95 | return Err(Error::Parity); | ||
| 96 | } else if sr.fe() { | ||
| 97 | r.rdr().read(); | ||
| 98 | return Err(Error::Framing); | ||
| 99 | } else if sr.ne() { | ||
| 100 | r.rdr().read(); | ||
| 101 | return Err(Error::Noise); | ||
| 102 | } else if sr.ore() { | ||
| 103 | r.rdr().read(); | ||
| 104 | return Err(Error::Overrun); | ||
| 105 | } else if sr.rxne() { | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | *b = r.rdr().read().0 as u8; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | Ok(()) | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write<u8> | ||
| 117 | for Uart<'d, T, NoDma, RxDma> | ||
| 118 | { | ||
| 119 | type Error = Error; | ||
| 120 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 121 | unsafe { | ||
| 122 | let r = self.inner.regs(); | ||
| 123 | for &b in buffer { | ||
| 124 | while !r.isr().read().txe() {} | ||
| 125 | r.tdr().write_value(regs::Tdr(b as u32)) | ||
| 126 | } | ||
| 127 | } | ||
| 128 | Ok(()) | ||
| 129 | } | ||
| 130 | fn bflush(&mut self) -> Result<(), Self::Error> { | ||
| 131 | unsafe { | ||
| 132 | let r = self.inner.regs(); | ||
| 133 | while !r.isr().read().tc() {} | ||
| 134 | } | ||
| 135 | Ok(()) | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | // rustfmt::skip because intellij removes the 'where' claus on the associated type. | ||
| 140 | #[rustfmt::skip] | ||
| 141 | impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma> | ||
| 142 | where TxDma: crate::usart::TxDma<T> | ||
| 143 | { | ||
| 144 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>>; | ||
| 145 | |||
| 146 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 147 | self.write_dma(buf).map_err(|_| embassy_traits::uart::Error::Other) | ||
| 148 | } | ||
| 149 | } | ||
diff --git a/stm32-data b/stm32-data | |||
| Subproject 964bf38532aca5b8ecb274a38659b272db3d4d5 | Subproject b10a0dd9101038d9f93402565e9b9675f15c087 | ||
