diff options
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/v2.rs | 91 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f4/mod.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/v1.rs | 27 |
5 files changed, 107 insertions, 32 deletions
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index a8a22ce89..371741ffd 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | //#[cfg_attr(dma_v1, path = "v1.rs")] | 3 | #[cfg_attr(dma_v1, path = "v1.rs")] |
| 4 | #[cfg_attr(dma_v2, path = "v2.rs")] | 4 | #[cfg_attr(dma_v2, path = "v2.rs")] |
| 5 | mod _version; | 5 | mod _version; |
| 6 | 6 | ||
| @@ -19,4 +19,12 @@ pub trait WriteDma<T> { | |||
| 19 | T: 'a; | 19 | T: 'a; |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | pub trait ReadDma {} | 22 | pub trait ReadDma<T> { |
| 23 | type ReadDmaFuture<'a>: Future<Output = ()> + 'a | ||
| 24 | where | ||
| 25 | Self: 'a; | ||
| 26 | |||
| 27 | fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a> | ||
| 28 | where | ||
| 29 | T: 'a; | ||
| 30 | } | ||
diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs index 6c6bbde23..4cce1adfc 100644 --- a/embassy-stm32/src/dma/v2.rs +++ b/embassy-stm32/src/dma/v2.rs | |||
| @@ -40,6 +40,52 @@ impl State { | |||
| 40 | static STATE: State = State::new(); | 40 | static STATE: State = State::new(); |
| 41 | 41 | ||
| 42 | #[allow(unused)] // Used by usart/v1.rs which may or may not be enabled | 42 | #[allow(unused)] // Used by usart/v1.rs which may or may not be enabled |
| 43 | pub(crate) async unsafe fn transfer_p2m( | ||
| 44 | ch: &mut impl Channel, | ||
| 45 | ch_func: u8, | ||
| 46 | src: *const u8, | ||
| 47 | dst: &mut [u8], | ||
| 48 | ) { | ||
| 49 | let n = ch.num(); | ||
| 50 | let c = ch.regs(); | ||
| 51 | |||
| 52 | // ndtr is max 16 bits. | ||
| 53 | assert!(dst.len() <= 0xFFFF); | ||
| 54 | |||
| 55 | // Reset status | ||
| 56 | STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Relaxed); | ||
| 57 | |||
| 58 | unsafe { | ||
| 59 | c.par().write_value(src as _); | ||
| 60 | c.m0ar().write_value(dst.as_ptr() as _); | ||
| 61 | c.ndtr().write_value(regs::Ndtr(dst.len() as _)); | ||
| 62 | c.cr().write(|w| { | ||
| 63 | w.set_dir(vals::Dir::PERIPHERALTOMEMORY); | ||
| 64 | w.set_msize(vals::Size::BITS8); | ||
| 65 | w.set_psize(vals::Size::BITS8); | ||
| 66 | w.set_minc(vals::Inc::INCREMENTED); | ||
| 67 | w.set_pinc(vals::Inc::FIXED); | ||
| 68 | w.set_chsel(ch_func); | ||
| 69 | w.set_teie(true); | ||
| 70 | w.set_tcie(true); | ||
| 71 | w.set_en(true); | ||
| 72 | }); | ||
| 73 | } | ||
| 74 | |||
| 75 | let res = poll_fn(|cx| { | ||
| 76 | STATE.ch_wakers[n].register(cx.waker()); | ||
| 77 | match STATE.ch_status[n].load(Ordering::Relaxed) { | ||
| 78 | CH_STATUS_NONE => Poll::Pending, | ||
| 79 | x => Poll::Ready(x), | ||
| 80 | } | ||
| 81 | }) | ||
| 82 | .await; | ||
| 83 | |||
| 84 | // TODO handle error | ||
| 85 | assert!(res == CH_STATUS_COMPLETED); | ||
| 86 | } | ||
| 87 | |||
| 88 | #[allow(unused)] // Used by usart/v1.rs which may or may not be enabled | ||
| 43 | pub(crate) async unsafe fn transfer_m2p( | 89 | pub(crate) async unsafe fn transfer_m2p( |
| 44 | ch: &mut impl Channel, | 90 | ch: &mut impl Channel, |
| 45 | ch_func: u8, | 91 | ch_func: u8, |
| @@ -75,7 +121,10 @@ pub(crate) async unsafe fn transfer_m2p( | |||
| 75 | let res = poll_fn(|cx| { | 121 | let res = poll_fn(|cx| { |
| 76 | STATE.ch_wakers[n].register(cx.waker()); | 122 | STATE.ch_wakers[n].register(cx.waker()); |
| 77 | match STATE.ch_status[n].load(Ordering::Relaxed) { | 123 | match STATE.ch_status[n].load(Ordering::Relaxed) { |
| 78 | CH_STATUS_NONE => Poll::Pending, | 124 | CH_STATUS_NONE => { |
| 125 | let left = c.ndtr().read().ndt(); | ||
| 126 | Poll::Pending | ||
| 127 | } | ||
| 79 | x => Poll::Ready(x), | 128 | x => Poll::Ready(x), |
| 80 | } | 129 | } |
| 81 | }) | 130 | }) |
| @@ -137,14 +186,14 @@ pub(crate) mod sealed { | |||
| 137 | } | 186 | } |
| 138 | } | 187 | } |
| 139 | 188 | ||
| 140 | pub trait PeripheralChannel<PERI>: Channel { | 189 | pub trait PeripheralChannel<PERI, OP>: Channel { |
| 141 | fn request(&self) -> u8; | 190 | fn request(&self) -> u8; |
| 142 | } | 191 | } |
| 143 | } | 192 | } |
| 144 | 193 | ||
| 145 | pub trait Dma: sealed::Dma + Sized {} | 194 | pub trait Dma: sealed::Dma + Sized {} |
| 146 | pub trait Channel: sealed::Channel + Sized {} | 195 | pub trait Channel: sealed::Channel + Sized {} |
| 147 | pub trait PeripheralChannel<PERI>: sealed::PeripheralChannel<PERI> + Sized {} | 196 | pub trait PeripheralChannel<PERI, OP>: sealed::PeripheralChannel<PERI, OP> + Sized {} |
| 148 | 197 | ||
| 149 | macro_rules! impl_dma { | 198 | macro_rules! impl_dma { |
| 150 | ($peri:ident, $num:expr) => { | 199 | ($peri:ident, $num:expr) => { |
| @@ -180,7 +229,7 @@ macro_rules! impl_dma_channel { | |||
| 180 | 229 | ||
| 181 | impl<T> WriteDma<T> for peripherals::$channel_peri | 230 | impl<T> WriteDma<T> for peripherals::$channel_peri |
| 182 | where | 231 | where |
| 183 | Self: sealed::PeripheralChannel<T>, | 232 | Self: sealed::PeripheralChannel<T, M2P>, |
| 184 | T: 'static, | 233 | T: 'static, |
| 185 | { | 234 | { |
| 186 | type WriteDmaFuture<'a> = impl Future<Output = ()>; | 235 | type WriteDmaFuture<'a> = impl Future<Output = ()>; |
| @@ -189,10 +238,30 @@ macro_rules! impl_dma_channel { | |||
| 189 | where | 238 | where |
| 190 | T: 'a, | 239 | T: 'a, |
| 191 | { | 240 | { |
| 192 | let request = sealed::PeripheralChannel::<T>::request(self); | 241 | let request = sealed::PeripheralChannel::<T, M2P>::request(self); |
| 193 | unsafe { transfer_m2p(self, request, buf, dst) } | 242 | unsafe { transfer_m2p(self, request, buf, dst) } |
| 194 | } | 243 | } |
| 195 | } | 244 | } |
| 245 | |||
| 246 | impl<T> ReadDma<T> for peripherals::$channel_peri | ||
| 247 | where | ||
| 248 | Self: sealed::PeripheralChannel<T, P2M>, | ||
| 249 | T: 'static, | ||
| 250 | { | ||
| 251 | type ReadDmaFuture<'a> = impl Future<Output = ()>; | ||
| 252 | |||
| 253 | fn transfer<'a>( | ||
| 254 | &'a mut self, | ||
| 255 | src: *const u8, | ||
| 256 | buf: &'a mut [u8], | ||
| 257 | ) -> Self::ReadDmaFuture<'a> | ||
| 258 | where | ||
| 259 | T: 'a, | ||
| 260 | { | ||
| 261 | let request = sealed::PeripheralChannel::<T, P2M>::request(self); | ||
| 262 | unsafe { transfer_p2m(self, request, src, buf) } | ||
| 263 | } | ||
| 264 | } | ||
| 196 | }; | 265 | }; |
| 197 | } | 266 | } |
| 198 | 267 | ||
| @@ -217,12 +286,16 @@ peripherals! { | |||
| 217 | 286 | ||
| 218 | interrupts! { | 287 | interrupts! { |
| 219 | (DMA, $irq:ident) => { | 288 | (DMA, $irq:ident) => { |
| 289 | #[crate::interrupt] | ||
| 220 | unsafe fn $irq () { | 290 | unsafe fn $irq () { |
| 221 | on_irq() | 291 | on_irq() |
| 222 | } | 292 | } |
| 223 | }; | 293 | }; |
| 224 | } | 294 | } |
| 225 | 295 | ||
| 296 | pub struct P2M; | ||
| 297 | pub struct M2P; | ||
| 298 | |||
| 226 | #[cfg(usart)] | 299 | #[cfg(usart)] |
| 227 | use crate::usart; | 300 | use crate::usart; |
| 228 | peripheral_dma_channels! { | 301 | peripheral_dma_channels! { |
| @@ -230,25 +303,25 @@ peripheral_dma_channels! { | |||
| 230 | impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { } | 303 | impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { } |
| 231 | impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { } | 304 | impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { } |
| 232 | 305 | ||
| 233 | impl sealed::PeripheralChannel<peripherals::$peri> for peripherals::$channel_peri { | 306 | impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { |
| 234 | fn request(&self) -> u8 { | 307 | fn request(&self) -> u8 { |
| 235 | $event_num | 308 | $event_num |
| 236 | } | 309 | } |
| 237 | } | 310 | } |
| 238 | 311 | ||
| 239 | impl PeripheralChannel<peripherals::$peri> for peripherals::$channel_peri { } | 312 | impl PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { } |
| 240 | }; | 313 | }; |
| 241 | 314 | ||
| 242 | ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => { | 315 | ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => { |
| 243 | impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { } | 316 | impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { } |
| 244 | impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { } | 317 | impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { } |
| 245 | 318 | ||
| 246 | impl sealed::PeripheralChannel<peripherals::$peri> for peripherals::$channel_peri { | 319 | impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { |
| 247 | fn request(&self) -> u8 { | 320 | fn request(&self) -> u8 { |
| 248 | $event_num | 321 | $event_num |
| 249 | } | 322 | } |
| 250 | } | 323 | } |
| 251 | 324 | ||
| 252 | impl PeripheralChannel<peripherals::$peri> for peripherals::$channel_peri { } | 325 | impl PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { } |
| 253 | }; | 326 | }; |
| 254 | } | 327 | } |
diff --git a/embassy-stm32/src/rcc/f4/mod.rs b/embassy-stm32/src/rcc/f4/mod.rs index 4b17bdf40..6000192b9 100644 --- a/embassy-stm32/src/rcc/f4/mod.rs +++ b/embassy-stm32/src/rcc/f4/mod.rs | |||
| @@ -132,7 +132,7 @@ impl RccExt for RCC { | |||
| 132 | ClockSrc::HSI16 => { | 132 | ClockSrc::HSI16 => { |
| 133 | // Enable HSI16 | 133 | // Enable HSI16 |
| 134 | unsafe { | 134 | unsafe { |
| 135 | rcc.cr().write(|w| w.set_hsion(true)); | 135 | rcc.cr().modify(|w| w.set_hsion(true)); |
| 136 | while !rcc.cr().read().hsirdy() {} | 136 | while !rcc.cr().read().hsirdy() {} |
| 137 | } | 137 | } |
| 138 | 138 | ||
| @@ -141,7 +141,7 @@ impl RccExt for RCC { | |||
| 141 | ClockSrc::HSE(freq) => { | 141 | ClockSrc::HSE(freq) => { |
| 142 | // Enable HSE | 142 | // Enable HSE |
| 143 | unsafe { | 143 | unsafe { |
| 144 | rcc.cr().write(|w| w.set_hseon(true)); | 144 | rcc.cr().modify(|w| w.set_hseon(true)); |
| 145 | while !rcc.cr().read().hserdy() {} | 145 | while !rcc.cr().read().hserdy() {} |
| 146 | } | 146 | } |
| 147 | 147 | ||
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 24793b6b1..08be583c7 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -1,13 +1,14 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 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 | mod _version; | 5 | mod _version; |
| 6 | use crate::peripherals; | 6 | use crate::peripherals; |
| 7 | pub use _version::*; | 7 | pub use _version::*; |
| 8 | 8 | ||
| 9 | use crate::gpio::Pin; | 9 | use crate::gpio::Pin; |
| 10 | use crate::pac::usart::Usart; | 10 | use crate::pac::usart::Usart; |
| 11 | use crate::rcc::RccPeripheral; | ||
| 11 | 12 | ||
| 12 | /// Serial error | 13 | /// Serial error |
| 13 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | 14 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] |
| @@ -51,7 +52,7 @@ pub(crate) mod sealed { | |||
| 51 | pub trait TxDma<T: Instance>: WriteDma<T> {} | 52 | pub trait TxDma<T: Instance>: WriteDma<T> {} |
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | pub trait Instance: sealed::Instance {} | 55 | pub trait Instance: sealed::Instance + RccPeripheral {} |
| 55 | pub trait RxPin<T: Instance>: sealed::RxPin<T> {} | 56 | pub trait RxPin<T: Instance>: sealed::RxPin<T> {} |
| 56 | pub trait TxPin<T: Instance>: sealed::TxPin<T> {} | 57 | pub trait TxPin<T: Instance>: sealed::TxPin<T> {} |
| 57 | pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} | 58 | pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} |
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs index a721e89a6..1f05dc9a2 100644 --- a/embassy-stm32/src/usart/v1.rs +++ b/embassy-stm32/src/usart/v1.rs | |||
| @@ -63,14 +63,17 @@ impl<'d, T: Instance> Uart<'d, T> { | |||
| 63 | rx: impl Unborrow<Target = impl RxPin<T>>, | 63 | rx: impl Unborrow<Target = impl RxPin<T>>, |
| 64 | tx: impl Unborrow<Target = impl TxPin<T>>, | 64 | tx: impl Unborrow<Target = impl TxPin<T>>, |
| 65 | config: Config, | 65 | config: Config, |
| 66 | pclk_freq: u32, | 66 | //pclk_freq: u32, |
| 67 | ) -> Self { | 67 | ) -> Self { |
| 68 | unborrow!(inner, rx, tx); | 68 | unborrow!(inner, rx, tx); |
| 69 | 69 | ||
| 70 | let pclk_freq = T::frequency(); | ||
| 71 | //let pclk_freq = 16_000_000; | ||
| 72 | |||
| 70 | // TODO: enable in RCC | 73 | // TODO: enable in RCC |
| 71 | 74 | ||
| 72 | // TODO: better calculation, including error checking and OVER8 if possible. | 75 | // TODO: better calculation, including error checking and OVER8 if possible. |
| 73 | let div = (pclk_freq + (config.baudrate / 2)) / config.baudrate; | 76 | let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate; |
| 74 | 77 | ||
| 75 | let r = inner.regs(); | 78 | let r = inner.regs(); |
| 76 | 79 | ||
| @@ -108,25 +111,15 @@ impl<'d, T: Instance> Uart<'d, T> { | |||
| 108 | ch: &mut impl TxDma<T>, | 111 | ch: &mut impl TxDma<T>, |
| 109 | buffer: &[u8], | 112 | buffer: &[u8], |
| 110 | ) -> Result<(), Error> { | 113 | ) -> Result<(), Error> { |
| 111 | let r = self.inner.regs(); | ||
| 112 | let dst = r.dr().ptr() as *mut u8; | ||
| 113 | ch.transfer(buffer, dst).await; | ||
| 114 | Ok(()) | ||
| 115 | /* | ||
| 116 | let ch_func = 4; // USART3_TX | ||
| 117 | |||
| 118 | unsafe { | 114 | unsafe { |
| 119 | r.cr3().write(|w| { | 115 | self.inner.regs().cr3().modify(|reg| { |
| 120 | w.set_dmat(true); | 116 | reg.set_dmat(true); |
| 121 | }); | 117 | }); |
| 122 | |||
| 123 | let dst = r.dr().ptr() as *mut u8; | ||
| 124 | |||
| 125 | crate::dma::transfer_m2p(ch, ch_func, buffer, dst).await; | ||
| 126 | } | 118 | } |
| 127 | 119 | let r = self.inner.regs(); | |
| 120 | let dst = r.dr().ptr() as *mut u8; | ||
| 121 | ch.transfer(buffer, dst).await; | ||
| 128 | Ok(()) | 122 | Ok(()) |
| 129 | */ | ||
| 130 | } | 123 | } |
| 131 | 124 | ||
| 132 | pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | 125 | pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
