diff options
| author | Thales Fragoso <[email protected]> | 2021-07-04 15:40:33 -0300 |
|---|---|---|
| committer | Bob McWhirter <[email protected]> | 2021-07-13 10:08:43 -0400 |
| commit | a56ddfdc04a02d9de2dc474f5cc9dbae8cff1ab1 (patch) | |
| tree | 603a7cb547663674792eb9c13907fa9c449c02df | |
| parent | f32caaeaafd77b15005612b6d8d039b101b36975 (diff) | |
STM: Add usart v2
| -rw-r--r-- | embassy-stm32/src/bdma/v1.rs | 38 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/v2.rs | 118 |
2 files changed, 143 insertions, 13 deletions
diff --git a/embassy-stm32/src/bdma/v1.rs b/embassy-stm32/src/bdma/v1.rs index 584d531f7..13caf329b 100644 --- a/embassy-stm32/src/bdma/v1.rs +++ b/embassy-stm32/src/bdma/v1.rs | |||
| @@ -35,13 +35,15 @@ impl State { | |||
| 35 | static STATE: State = State::new(); | 35 | static STATE: State = State::new(); |
| 36 | 36 | ||
| 37 | #[allow(unused)] | 37 | #[allow(unused)] |
| 38 | pub(crate) async unsafe fn transfer_p2m(ch: &mut impl Channel, src: *const u8, dst: &mut [u8]) { | 38 | pub(crate) async unsafe fn transfer_p2m( |
| 39 | regs: pac::bdma::Ch, | ||
| 40 | state_number: usize, | ||
| 41 | src: *const u8, | ||
| 42 | dst: &mut [u8], | ||
| 43 | ) { | ||
| 39 | // ndtr is max 16 bits. | 44 | // ndtr is max 16 bits. |
| 40 | assert!(dst.len() <= 0xFFFF); | 45 | assert!(dst.len() <= 0xFFFF); |
| 41 | 46 | ||
| 42 | let regs: pac::bdma::Ch = ch.regs(); | ||
| 43 | let state_number = ch.state_num(); | ||
| 44 | |||
| 45 | // Reset status | 47 | // Reset status |
| 46 | // Generate a DMB here to flush the store buffer (M7) before enabling the DMA | 48 | // Generate a DMB here to flush the store buffer (M7) before enabling the DMA |
| 47 | STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); | 49 | STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); |
| @@ -82,13 +84,15 @@ pub(crate) async unsafe fn transfer_p2m(ch: &mut impl Channel, src: *const u8, d | |||
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | #[allow(unused)] | 86 | #[allow(unused)] |
| 85 | pub(crate) async unsafe fn transfer_m2p(ch: &mut impl Channel, src: &[u8], dst: *mut u8) { | 87 | pub(crate) async unsafe fn transfer_m2p( |
| 88 | regs: pac::bdma::Ch, | ||
| 89 | state_number: usize, | ||
| 90 | src: &[u8], | ||
| 91 | dst: *mut u8, | ||
| 92 | ) { | ||
| 86 | // ndtr is max 16 bits. | 93 | // ndtr is max 16 bits. |
| 87 | assert!(src.len() <= 0xFFFF); | 94 | assert!(src.len() <= 0xFFFF); |
| 88 | 95 | ||
| 89 | let regs: pac::bdma::Ch = ch.regs(); | ||
| 90 | let state_number = ch.state_num(); | ||
| 91 | |||
| 92 | // Reset status | 96 | // Reset status |
| 93 | // Generate a DMB here to flush the store buffer (M7) before enabling the DMA | 97 | // Generate a DMB here to flush the store buffer (M7) before enabling the DMA |
| 94 | STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); | 98 | STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); |
| @@ -168,7 +172,7 @@ pub(crate) mod sealed { | |||
| 168 | } | 172 | } |
| 169 | 173 | ||
| 170 | pub trait Channel { | 174 | pub trait Channel { |
| 171 | fn dma_regs() -> &'static pac::bdma::Dma; | 175 | fn dma_regs() -> pac::bdma::Dma; |
| 172 | 176 | ||
| 173 | fn state_num(&self) -> usize; | 177 | fn state_num(&self) -> usize; |
| 174 | 178 | ||
| @@ -199,8 +203,8 @@ macro_rules! impl_dma_channel { | |||
| 199 | impl Channel for crate::peripherals::$channel_peri {} | 203 | impl Channel for crate::peripherals::$channel_peri {} |
| 200 | impl sealed::Channel for crate::peripherals::$channel_peri { | 204 | impl sealed::Channel for crate::peripherals::$channel_peri { |
| 201 | #[inline] | 205 | #[inline] |
| 202 | fn dma_regs() -> &'static pac::bdma::Dma { | 206 | fn dma_regs() -> pac::bdma::Dma { |
| 203 | &crate::pac::$dma_peri | 207 | crate::pac::$dma_peri |
| 204 | } | 208 | } |
| 205 | 209 | ||
| 206 | fn state_num(&self) -> usize { | 210 | fn state_num(&self) -> usize { |
| @@ -222,7 +226,11 @@ macro_rules! impl_dma_channel { | |||
| 222 | where | 226 | where |
| 223 | T: 'a, | 227 | T: 'a, |
| 224 | { | 228 | { |
| 225 | unsafe { transfer_m2p(self, buf, dst) } | 229 | use sealed::Channel as _Channel; |
| 230 | |||
| 231 | let state_num = self.state_num(); | ||
| 232 | let regs = self.regs(); | ||
| 233 | unsafe { transfer_m2p(regs, state_num, buf, dst) } | ||
| 226 | } | 234 | } |
| 227 | } | 235 | } |
| 228 | 236 | ||
| @@ -240,7 +248,11 @@ macro_rules! impl_dma_channel { | |||
| 240 | where | 248 | where |
| 241 | T: 'a, | 249 | T: 'a, |
| 242 | { | 250 | { |
| 243 | unsafe { transfer_p2m(self, src, buf) } | 251 | use sealed::Channel as _Channel; |
| 252 | |||
| 253 | let state_num = self.state_num(); | ||
| 254 | let regs = self.regs(); | ||
| 255 | unsafe { transfer_p2m(regs, state_num, src, buf) } | ||
| 244 | } | 256 | } |
| 245 | } | 257 | } |
| 246 | }; | 258 | }; |
diff --git a/embassy-stm32/src/usart/v2.rs b/embassy-stm32/src/usart/v2.rs index 8b1378917..271eff850 100644 --- a/embassy-stm32/src/usart/v2.rs +++ b/embassy-stm32/src/usart/v2.rs | |||
| @@ -1 +1,119 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 1 | 2 | ||
| 3 | use embassy::util::Unborrow; | ||
| 4 | use embassy_extras::unborrow; | ||
| 5 | |||
| 6 | use crate::pac::usart::{regs, vals}; | ||
| 7 | |||
| 8 | use super::*; | ||
| 9 | |||
| 10 | pub struct Uart<'d, T: Instance> { | ||
| 11 | inner: T, | ||
| 12 | phantom: PhantomData<&'d mut T>, | ||
| 13 | } | ||
| 14 | |||
| 15 | impl<'d, T: Instance> Uart<'d, T> { | ||
| 16 | pub fn new( | ||
| 17 | inner: impl Unborrow<Target = T>, | ||
| 18 | rx: impl Unborrow<Target = impl RxPin<T>>, | ||
| 19 | tx: impl Unborrow<Target = impl TxPin<T>>, | ||
| 20 | config: Config, | ||
| 21 | ) -> Self { | ||
| 22 | unborrow!(inner, rx, tx); | ||
| 23 | |||
| 24 | // Uncomment once we find all of the H7's UART clocks. | ||
| 25 | T::enable(); | ||
| 26 | let pclk_freq = T::frequency(); | ||
| 27 | |||
| 28 | // TODO: better calculation, including error checking and OVER8 if possible. | ||
| 29 | let div = pclk_freq.0 / config.baudrate; | ||
| 30 | |||
| 31 | let r = inner.regs(); | ||
| 32 | |||
| 33 | unsafe { | ||
| 34 | rx.set_as_af(rx.af_num()); | ||
| 35 | tx.set_as_af(tx.af_num()); | ||
| 36 | |||
| 37 | r.brr().write_value(regs::Brr(div)); | ||
| 38 | r.cr1().write(|w| { | ||
| 39 | w.set_ue(true); | ||
| 40 | w.set_te(true); | ||
| 41 | w.set_re(true); | ||
| 42 | w.set_m0(vals::M0::BIT8); | ||
| 43 | w.set_m1(vals::M1::M0); | ||
| 44 | w.set_pce(config.parity != Parity::ParityNone); | ||
| 45 | w.set_ps(match config.parity { | ||
| 46 | Parity::ParityOdd => vals::Ps::ODD, | ||
| 47 | Parity::ParityEven => vals::Ps::EVEN, | ||
| 48 | _ => vals::Ps::EVEN, | ||
| 49 | }); | ||
| 50 | }); | ||
| 51 | r.cr2().write(|_w| {}); | ||
| 52 | r.cr3().write(|_w| {}); | ||
| 53 | } | ||
| 54 | |||
| 55 | Self { | ||
| 56 | inner, | ||
| 57 | phantom: PhantomData, | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | #[cfg(dma)] | ||
| 62 | pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> { | ||
| 63 | unsafe { | ||
| 64 | self.inner.regs().cr3().modify(|reg| { | ||
| 65 | reg.set_dmat(true); | ||
| 66 | }); | ||
| 67 | } | ||
| 68 | let r = self.inner.regs(); | ||
| 69 | let dst = r.tdr().ptr() as *mut u8; | ||
| 70 | ch.transfer(buffer, dst).await; | ||
| 71 | Ok(()) | ||
| 72 | } | ||
| 73 | |||
| 74 | pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | ||
| 75 | unsafe { | ||
| 76 | let r = self.inner.regs(); | ||
| 77 | for b in buffer { | ||
| 78 | loop { | ||
| 79 | let sr = r.isr().read(); | ||
| 80 | if sr.pe() { | ||
| 81 | r.rdr().read(); | ||
| 82 | return Err(Error::Parity); | ||
| 83 | } else if sr.fe() { | ||
| 84 | r.rdr().read(); | ||
| 85 | return Err(Error::Framing); | ||
| 86 | } else if sr.ore() { | ||
| 87 | r.rdr().read(); | ||
| 88 | return Err(Error::Overrun); | ||
| 89 | } else if sr.rxne() { | ||
| 90 | break; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | *b = r.rdr().read().0 as u8; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | Ok(()) | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T> { | ||
| 101 | type Error = Error; | ||
| 102 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 103 | unsafe { | ||
| 104 | let r = self.inner.regs(); | ||
| 105 | for &b in buffer { | ||
| 106 | while !r.isr().read().txe() {} | ||
| 107 | r.tdr().write(|w| w.set_dr(b as u16)); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | Ok(()) | ||
| 111 | } | ||
| 112 | fn bflush(&mut self) -> Result<(), Self::Error> { | ||
| 113 | unsafe { | ||
| 114 | let r = self.inner.regs(); | ||
| 115 | while !r.isr().read().tc() {} | ||
| 116 | } | ||
| 117 | Ok(()) | ||
| 118 | } | ||
| 119 | } | ||
