diff options
| author | xoviat <[email protected]> | 2020-12-29 12:33:50 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2020-12-29 12:33:50 -0600 |
| commit | 74b5d4693c91c23d0c2b75f213323ba1fc4d8bce (patch) | |
| tree | 4ffa1fb2589d2943ac4888e71727d193fc2e92cb | |
| parent | 04944b6379814560a1d3732ed76b56751023f055 (diff) | |
implement prelim draft
| -rw-r--r-- | embassy-stm32f4/Cargo.toml | 2 | ||||
| -rw-r--r-- | embassy-stm32f4/src/lib.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32f4/src/uarte.rs | 200 |
3 files changed, 49 insertions, 154 deletions
diff --git a/embassy-stm32f4/Cargo.toml b/embassy-stm32f4/Cargo.toml index 654ea69a6..1891a5596 100644 --- a/embassy-stm32f4/Cargo.toml +++ b/embassy-stm32f4/Cargo.toml | |||
| @@ -40,4 +40,4 @@ cortex-m-rt = "0.6.13" | |||
| 40 | cortex-m = { version = "0.6.4" } | 40 | cortex-m = { version = "0.6.4" } |
| 41 | embedded-hal = { version = "0.2.4" } | 41 | embedded-hal = { version = "0.2.4" } |
| 42 | embedded-dma = { version = "0.1.2" } | 42 | embedded-dma = { version = "0.1.2" } |
| 43 | stm32f4xx-hal = { version = "0.8.3", features = ["rt"], git = "https://github.com/stm32-rs/stm32f4xx-hal.git" } | 43 | stm32f4xx-hal = { version = "0.8.3", features = ["rt"], git = "https://github.com/xoviat/stm32f4xx-hal.git", branch = "dma-is-done"} |
diff --git a/embassy-stm32f4/src/lib.rs b/embassy-stm32f4/src/lib.rs index 40386085a..e6d523d21 100644 --- a/embassy-stm32f4/src/lib.rs +++ b/embassy-stm32f4/src/lib.rs | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #![feature(generic_associated_types)] | 2 | #![feature(generic_associated_types)] |
| 3 | #![feature(asm)] | 3 | #![feature(asm)] |
| 4 | #![feature(type_alias_impl_trait)] | 4 | #![feature(type_alias_impl_trait)] |
| 5 | #![feature(let_chains)] | ||
| 5 | 6 | ||
| 6 | #[cfg(not(any( | 7 | #[cfg(not(any( |
| 7 | feature = "stm32f401", | 8 | feature = "stm32f401", |
diff --git a/embassy-stm32f4/src/uarte.rs b/embassy-stm32f4/src/uarte.rs index 9e253dd9f..273c384cb 100644 --- a/embassy-stm32f4/src/uarte.rs +++ b/embassy-stm32f4/src/uarte.rs | |||
| @@ -16,11 +16,14 @@ use core::task::{Context, Poll}; | |||
| 16 | use cortex_m::singleton; | 16 | use cortex_m::singleton; |
| 17 | 17 | ||
| 18 | use embassy::util::Signal; | 18 | use embassy::util::Signal; |
| 19 | use embedded_dma::{StaticReadBuffer, StaticWriteBuffer}; | 19 | use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer}; |
| 20 | 20 | ||
| 21 | use crate::fmt::assert; | 21 | use crate::fmt::assert; |
| 22 | use crate::hal::dma::config::DmaConfig; | 22 | use crate::hal::dma::config::DmaConfig; |
| 23 | use crate::hal::dma::{Channel4, PeripheralToMemory, Stream2, StreamsTuple, Transfer}; | 23 | use crate::hal::dma::{ |
| 24 | Channel4, Channel7, MemoryToPeripheral, PeripheralToMemory, Stream2, Stream7, StreamsTuple, | ||
| 25 | Transfer, | ||
| 26 | }; | ||
| 24 | use crate::hal::gpio::gpioa::{PA10, PA9}; | 27 | use crate::hal::gpio::gpioa::{PA10, PA9}; |
| 25 | use crate::hal::gpio::{Alternate, AF10, AF7, AF9}; | 28 | use crate::hal::gpio::{Alternate, AF10, AF7, AF9}; |
| 26 | use crate::hal::gpio::{Floating, Input, Output, PushPull}; | 29 | use crate::hal::gpio::{Floating, Input, Output, PushPull}; |
| @@ -94,45 +97,15 @@ impl Uarte { | |||
| 94 | ) | 97 | ) |
| 95 | .unwrap(); | 98 | .unwrap(); |
| 96 | 99 | ||
| 97 | let isr = pins.dma.hisr;0 | 100 | // let is_set = dma.hifcr.read().tcif7.bit_is_set(); |
| 98 | 101 | ||
| 99 | Uarte { instance: serial, dma: pins.dma, usart: pins.usart } | 102 | Uarte { |
| 103 | instance: serial, | ||
| 104 | dma: pins.dma, | ||
| 105 | usart: pins.usart, | ||
| 106 | } | ||
| 100 | } | 107 | } |
| 101 | 108 | ||
| 102 | /// Sets the baudrate, parity and assigns the pins to the UARTE peripheral. | ||
| 103 | // TODO: Make it take the same `Pins` structs nrf-hal (with optional RTS/CTS). | ||
| 104 | // // TODO: #[cfg()] for smaller device variants without port register (nrf52810, ...). | ||
| 105 | // pub fn configure( | ||
| 106 | // &mut self, | ||
| 107 | // rxd: &Pin<Input<Floating>>, | ||
| 108 | // txd: &mut Pin<Output<PushPull>>, | ||
| 109 | // parity: Parity, | ||
| 110 | // baudrate: Baudrate, | ||
| 111 | // ) { | ||
| 112 | // let uarte = &self.instance; | ||
| 113 | // assert!(uarte.enable.read().enable().is_disabled()); | ||
| 114 | // | ||
| 115 | // uarte.psel.rxd.write(|w| { | ||
| 116 | // let w = unsafe { w.pin().bits(rxd.pin()) }; | ||
| 117 | // let w = w.port().bit(rxd.port().bit()); | ||
| 118 | // w.connect().connected() | ||
| 119 | // }); | ||
| 120 | // | ||
| 121 | // txd.set_high().unwrap(); | ||
| 122 | // uarte.psel.txd.write(|w| { | ||
| 123 | // let w = unsafe { w.pin().bits(txd.pin()) }; | ||
| 124 | // let w = w.port().bit(txd.port().bit()); | ||
| 125 | // w.connect().connected() | ||
| 126 | // }); | ||
| 127 | // | ||
| 128 | // uarte.baudrate.write(|w| w.baudrate().variant(baudrate)); | ||
| 129 | // uarte.config.write(|w| w.parity().variant(parity)); | ||
| 130 | // } | ||
| 131 | |||
| 132 | // fn enable(&mut self) { | ||
| 133 | // self.instance.enable.write(|w| w.enable().enabled()); | ||
| 134 | // } | ||
| 135 | |||
| 136 | /// Sends serial data. | 109 | /// Sends serial data. |
| 137 | /// | 110 | /// |
| 138 | /// `tx_buffer` is marked as static as per `embedded-dma` requirements. | 111 | /// `tx_buffer` is marked as static as per `embedded-dma` requirements. |
| @@ -140,25 +113,15 @@ impl Uarte { | |||
| 140 | /// reused until the future has finished. | 113 | /// reused until the future has finished. |
| 141 | pub fn send<'a, B>(&'a mut self, tx_buffer: B) -> SendFuture<'a, B> | 114 | pub fn send<'a, B>(&'a mut self, tx_buffer: B) -> SendFuture<'a, B> |
| 142 | where | 115 | where |
| 143 | B: StaticReadBuffer<Word = u8>, | 116 | B: WriteBuffer<Word = u8> + 'static, |
| 144 | { | 117 | { |
| 145 | // Panic if TX is running which can happen if the user has called | ||
| 146 | // `mem::forget()` on a previous future after polling it once. | ||
| 147 | assert!(!self.tx_started()); | ||
| 148 | |||
| 149 | self.enable(); | ||
| 150 | |||
| 151 | SendFuture { | 118 | SendFuture { |
| 152 | uarte: self, | 119 | uarte: self, |
| 153 | buf: tx_buffer, | 120 | buf: tx_buffer, |
| 121 | transfer: None, | ||
| 154 | } | 122 | } |
| 155 | } | 123 | } |
| 156 | 124 | ||
| 157 | fn tx_started(&self) -> bool { | ||
| 158 | // self.instance.events_txstarted.read().bits() != 0 | ||
| 159 | false | ||
| 160 | } | ||
| 161 | |||
| 162 | /// Receives serial data. | 125 | /// Receives serial data. |
| 163 | /// | 126 | /// |
| 164 | /// The future is pending until the buffer is completely filled. | 127 | /// The future is pending until the buffer is completely filled. |
| @@ -171,83 +134,45 @@ impl Uarte { | |||
| 171 | /// reused until the future has finished. | 134 | /// reused until the future has finished. |
| 172 | pub fn receive<'a, B>(&'a mut self, rx_buffer: B) -> ReceiveFuture<'a, B> | 135 | pub fn receive<'a, B>(&'a mut self, rx_buffer: B) -> ReceiveFuture<'a, B> |
| 173 | where | 136 | where |
| 174 | B: StaticWriteBuffer<Word = u8>, | 137 | B: WriteBuffer<Word = u8> + 'static, |
| 175 | { | 138 | { |
| 176 | // Panic if RX is running which can happen if the user has called | ||
| 177 | // `mem::forget()` on a previous future after polling it once. | ||
| 178 | assert!(!self.rx_started()); | ||
| 179 | |||
| 180 | self.enable(); | ||
| 181 | |||
| 182 | ReceiveFuture { | 139 | ReceiveFuture { |
| 183 | uarte: self, | 140 | uarte: self, |
| 184 | buf: Some(rx_buffer), | 141 | buf: rx_buffer, |
| 142 | transfer: None, | ||
| 185 | } | 143 | } |
| 186 | } | 144 | } |
| 187 | |||
| 188 | fn rx_started(&self) -> bool { | ||
| 189 | self.instance.events_rxstarted.read().bits() != 0 | ||
| 190 | } | ||
| 191 | } | 145 | } |
| 192 | 146 | ||
| 193 | /// Future for the [`LowPowerUarte::send()`] method. | 147 | /// Future for the [`LowPowerUarte::send()`] method. |
| 194 | pub struct SendFuture<'a, B> { | 148 | pub struct SendFuture<'a, B: WriteBuffer<Word = u8> + 'static> { |
| 195 | uarte: &'a Uarte, | 149 | uarte: &'a Uarte, |
| 150 | transfer: Option<&'a Transfer<Stream7<DMA2>, Channel4, USART1, MemoryToPeripheral, B>>, | ||
| 196 | buf: B, | 151 | buf: B, |
| 197 | } | 152 | } |
| 198 | 153 | ||
| 199 | impl<'a, B> Drop for SendFuture<'a, B> { | 154 | impl<'a, B> Drop for SendFuture<'a, B> |
| 155 | where | ||
| 156 | B: WriteBuffer<Word = u8> + 'static, | ||
| 157 | { | ||
| 200 | fn drop(self: &mut Self) { | 158 | fn drop(self: &mut Self) { |
| 201 | if self.uarte.tx_started() { | 159 | drop(self.transfer); |
| 202 | trace!("stoptx"); | ||
| 203 | |||
| 204 | // Stop the transmitter to minimize the current consumption. | ||
| 205 | self.uarte | ||
| 206 | .instance | ||
| 207 | .tasks_stoptx | ||
| 208 | .write(|w| unsafe { w.bits(1) }); | ||
| 209 | self.uarte.instance.events_txstarted.reset(); | ||
| 210 | } | ||
| 211 | } | 160 | } |
| 212 | } | 161 | } |
| 213 | 162 | ||
| 214 | impl<'a, B> Future for SendFuture<'a, B> | 163 | impl<'a, B> Future for SendFuture<'a, B> |
| 215 | where | 164 | where |
| 216 | B: StaticReadBuffer<Word = u8>, | 165 | B: WriteBuffer<Word = u8> + 'static, |
| 217 | { | 166 | { |
| 218 | type Output = (); | 167 | type Output = (); |
| 219 | 168 | ||
| 220 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { | 169 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { |
| 221 | if self.is_ready() { | 170 | if !self.transfer.is_none() && self.transfer.unwrap().is_done() { |
| 222 | Poll::Ready(()) | 171 | Poll::Ready(()) |
| 223 | } else { | 172 | } else { |
| 224 | // Start DMA transaction | 173 | self.transfer = Some(&mut Transfer::init( |
| 225 | let uarte = &self.uarte.instance; | 174 | StreamsTuple::new(self.uarte.dma).7, |
| 226 | 175 | self.uarte.usart, | |
| 227 | STATE.tx_done.reset(); | ||
| 228 | |||
| 229 | let (ptr, len) = unsafe { self.buf.read_buffer() }; | ||
| 230 | // assert!(len <= EASY_DMA_SIZE); | ||
| 231 | // TODO: panic if buffer is not in SRAM | ||
| 232 | |||
| 233 | compiler_fence(Ordering::SeqCst); | ||
| 234 | // uarte.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 235 | // uarte | ||
| 236 | // .txd | ||
| 237 | // .maxcnt | ||
| 238 | // .write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 239 | |||
| 240 | // Start the DMA transfer | ||
| 241 | // See https://github.com/mwkroening/async-stm32f1xx/blob/78c46d1bff124eae4ebc7a2f4d40e6ed74def8b5/src/serial.rs#L118-L129 | ||
| 242 | // https://github.com/stm32-rs/stm32f1xx-hal/blob/68fd3d6f282173816fd3181e795988d314cb17d0/src/serial.rs#L649-L671 | ||
| 243 | |||
| 244 | // let first_buffer = singleton!(: [u8; 128] = [0; 128]).unwrap(); | ||
| 245 | // let second_buffer = singleton!(: [u8; 128] = [0; 128]).unwrap(); | ||
| 246 | // let triple_buffer = Some(singleton!(: [u8; 128] = [0; 128]).unwrap()); | ||
| 247 | |||
| 248 | let transfer = Transfer::init( | ||
| 249 | StreamsTuple::new(self.dma).2, | ||
| 250 | self.usart, | ||
| 251 | self.buf, | 176 | self.buf, |
| 252 | // Some(second_buffer), | 177 | // Some(second_buffer), |
| 253 | None, | 178 | None, |
| @@ -255,85 +180,54 @@ where | |||
| 255 | .transfer_complete_interrupt(true) | 180 | .transfer_complete_interrupt(true) |
| 256 | .memory_increment(true) | 181 | .memory_increment(true) |
| 257 | .double_buffer(false), | 182 | .double_buffer(false), |
| 258 | ); | 183 | )); |
| 259 | 184 | ||
| 260 | waker_interrupt!(DMA2_STREAM2, cx.waker().clone()); | 185 | waker_interrupt!(DMA2_STREAM7, cx.waker().clone()); |
| 261 | Poll::Pending | 186 | Poll::Pending |
| 262 | } | 187 | } |
| 263 | } | 188 | } |
| 264 | } | 189 | } |
| 265 | 190 | ||
| 266 | /// Future for the [`Uarte::receive()`] method. | 191 | /// Future for the [`Uarte::receive()`] method. |
| 267 | pub struct ReceiveFuture<'a, B> { | 192 | pub struct ReceiveFuture<'a, B: WriteBuffer<Word = u8> + 'static> { |
| 268 | uarte: &'a Uarte, | 193 | uarte: &'a Uarte, |
| 269 | buf: Option<B>, | 194 | transfer: Option<&'a Transfer<Stream2<DMA2>, Channel4, USART1, PeripheralToMemory, B>>, |
| 195 | buf: B, | ||
| 270 | } | 196 | } |
| 271 | 197 | ||
| 272 | impl<'a, B> Drop for ReceiveFuture<'a, B> { | 198 | impl<'a, B> Drop for ReceiveFuture<'a, B> |
| 199 | where | ||
| 200 | B: WriteBuffer<Word = u8> + 'static, | ||
| 201 | { | ||
| 273 | fn drop(self: &mut Self) { | 202 | fn drop(self: &mut Self) { |
| 274 | if self.uarte.rx_started() { | 203 | drop(self.transfer); |
| 275 | trace!("stoprx"); | ||
| 276 | |||
| 277 | self.uarte | ||
| 278 | .instance | ||
| 279 | .tasks_stoprx | ||
| 280 | .write(|w| unsafe { w.bits(1) }); | ||
| 281 | self.uarte.instance.events_rxstarted.reset(); | ||
| 282 | } | ||
| 283 | } | 204 | } |
| 284 | } | 205 | } |
| 285 | 206 | ||
| 286 | impl<'a, B> Future for ReceiveFuture<'a, B> | 207 | impl<'a, B> Future for ReceiveFuture<'a, B> |
| 287 | where | 208 | where |
| 288 | B: StaticWriteBuffer<Word = u8>, | 209 | B: WriteBuffer<Word = u8> + 'static, |
| 289 | { | 210 | { |
| 290 | type Output = B; | 211 | type Output = B; |
| 291 | 212 | ||
| 292 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<B> { | 213 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<B> { |
| 293 | if self.is_ready() { | 214 | if !self.transfer.is_none() && self.transfer.unwrap().is_done() { |
| 294 | Poll::Ready(()) | 215 | Poll::Ready(self.buf.take()); |
| 295 | } else { | 216 | } else { |
| 296 | // Start DMA transaction | 217 | self.transfer = Some(&mut Transfer::init( |
| 297 | compiler_fence(Ordering::SeqCst); | 218 | StreamsTuple::new(self.uarte.dma).2, |
| 298 | // uarte.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 219 | self.uarte.usart, |
| 299 | // uarte | ||
| 300 | // .txd | ||
| 301 | // .maxcnt | ||
| 302 | // .write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 303 | |||
| 304 | // Start the DMA transfer | ||
| 305 | // See https://github.com/mwkroening/async-stm32f1xx/blob/78c46d1bff124eae4ebc7a2f4d40e6ed74def8b5/src/serial.rs#L118-L129 | ||
| 306 | // https://github.com/stm32-rs/stm32f1xx-hal/blob/68fd3d6f282173816fd3181e795988d314cb17d0/src/serial.rs#L649-L671 | ||
| 307 | |||
| 308 | // let first_buffer = singleton!(: [u8; 128] = [0; 128]).unwrap(); | ||
| 309 | // let second_buffer = singleton!(: [u8; 128] = [0; 128]).unwrap(); | ||
| 310 | // let triple_buffer = Some(singleton!(: [u8; 128] = [0; 128]).unwrap()); | ||
| 311 | |||
| 312 | let transfer = Transfer::init( | ||
| 313 | StreamsTuple::new(self.dma).7, | ||
| 314 | self.usart, | ||
| 315 | self.buf, | 220 | self.buf, |
| 316 | // Some(second_buffer), | ||
| 317 | None, | 221 | None, |
| 318 | DmaConfig::default() | 222 | DmaConfig::default() |
| 319 | .transfer_complete_interrupt(true) | 223 | .transfer_complete_interrupt(true) |
| 224 | .half_transfer_interrupt(true) | ||
| 320 | .memory_increment(true) | 225 | .memory_increment(true) |
| 321 | .double_buffer(false), | 226 | .double_buffer(false), |
| 322 | ); | 227 | )); |
| 323 | 228 | ||
| 324 | waker_interrupt!(DMA2_STREAM7, cx.waker().clone()); | 229 | waker_interrupt!(DMA2_STREAM2, cx.waker().clone()); |
| 325 | Poll::Pending | 230 | Poll::Pending |
| 326 | } | 231 | } |
| 327 | } | 232 | } |
| 328 | } | 233 | } |
| 329 | |||
| 330 | /// Future for the [`receive()`] method. | ||
| 331 | impl<'a, B> ReceiveFuture<'a, B> { | ||
| 332 | /// Stops the ongoing reception and returns the number of bytes received. | ||
| 333 | pub async fn stop(mut self) -> (B, usize) { | ||
| 334 | let buf = self.buf.take().unwrap(); | ||
| 335 | drop(self); | ||
| 336 | let len = STATE.rx_done.wait().await; | ||
| 337 | (buf, len as _) | ||
| 338 | } | ||
| 339 | } | ||
