diff options
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/ringbuffered.rs | 84 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/ringbuffer/mod.rs | 76 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 2 |
3 files changed, 54 insertions, 108 deletions
diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 99c85a221..a5d2c700c 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs | |||
| @@ -46,29 +46,11 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { | |||
| 46 | } | 46 | } |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /// The current buffer half (e.g. for DMA or the user application). | ||
| 50 | #[derive(Debug, PartialEq, PartialOrd)] | ||
| 51 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 52 | enum BufferHalf { | ||
| 53 | First, | ||
| 54 | Second, | ||
| 55 | } | ||
| 56 | |||
| 57 | impl BufferHalf { | ||
| 58 | fn toggle(&mut self) { | ||
| 59 | *self = match *self { | ||
| 60 | Self::First => Self::Second, | ||
| 61 | Self::Second => Self::First, | ||
| 62 | }; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | /// Ringbuffer for receiving data using GPDMA linked-list mode. | 49 | /// Ringbuffer for receiving data using GPDMA linked-list mode. |
| 67 | pub struct ReadableRingBuffer<'a, W: Word> { | 50 | pub struct ReadableRingBuffer<'a, W: Word> { |
| 68 | channel: PeripheralRef<'a, AnyChannel>, | 51 | channel: PeripheralRef<'a, AnyChannel>, |
| 69 | ringbuf: ReadableDmaRingBuffer<'a, W>, | 52 | ringbuf: ReadableDmaRingBuffer<'a, W>, |
| 70 | table: Table<2>, | 53 | table: Table<2>, |
| 71 | user_buffer_half: BufferHalf, | ||
| 72 | } | 54 | } |
| 73 | 55 | ||
| 74 | impl<'a, W: Word> ReadableRingBuffer<'a, W> { | 56 | impl<'a, W: Word> ReadableRingBuffer<'a, W> { |
| @@ -99,7 +81,6 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 99 | channel, | 81 | channel, |
| 100 | ringbuf: ReadableDmaRingBuffer::new(buffer), | 82 | ringbuf: ReadableDmaRingBuffer::new(buffer), |
| 101 | table, | 83 | table, |
| 102 | user_buffer_half: BufferHalf::First, | ||
| 103 | } | 84 | } |
| 104 | } | 85 | } |
| 105 | 86 | ||
| @@ -217,7 +198,6 @@ pub struct WritableRingBuffer<'a, W: Word> { | |||
| 217 | channel: PeripheralRef<'a, AnyChannel>, | 198 | channel: PeripheralRef<'a, AnyChannel>, |
| 218 | ringbuf: WritableDmaRingBuffer<'a, W>, | 199 | ringbuf: WritableDmaRingBuffer<'a, W>, |
| 219 | table: Table<2>, | 200 | table: Table<2>, |
| 220 | user_buffer_half: BufferHalf, | ||
| 221 | } | 201 | } |
| 222 | 202 | ||
| 223 | impl<'a, W: Word> WritableRingBuffer<'a, W> { | 203 | impl<'a, W: Word> WritableRingBuffer<'a, W> { |
| @@ -246,7 +226,6 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 246 | channel, | 226 | channel, |
| 247 | ringbuf: WritableDmaRingBuffer::new(buffer), | 227 | ringbuf: WritableDmaRingBuffer::new(buffer), |
| 248 | table, | 228 | table, |
| 249 | user_buffer_half: BufferHalf::First, | ||
| 250 | }; | 229 | }; |
| 251 | 230 | ||
| 252 | this | 231 | this |
| @@ -280,62 +259,21 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 280 | 259 | ||
| 281 | /// Write an exact number of elements to the ringbuffer. | 260 | /// Write an exact number of elements to the ringbuffer. |
| 282 | pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, Error> { | 261 | pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, Error> { |
| 283 | return self | 262 | // return self |
| 284 | .ringbuf | 263 | // .ringbuf |
| 285 | .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) | 264 | // .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) |
| 286 | .await; | 265 | // .await; |
| 287 | 266 | ||
| 267 | let mut remaining_cap = 0; | ||
| 288 | let mut written_len = 0; | 268 | let mut written_len = 0; |
| 289 | let len = buffer.len(); | ||
| 290 | 269 | ||
| 291 | let mut remaining_cap = 0; | 270 | while written_len < buffer.len() { |
| 292 | let cap = self.ringbuf.cap(); | 271 | (written_len, remaining_cap) = self |
| 293 | 272 | .ringbuf | |
| 294 | let dma = &mut DmaCtrlImpl(self.channel.reborrow()); | 273 | .write_half(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) |
| 295 | let user_buffer_half = &mut self.user_buffer_half; | 274 | .await?; |
| 296 | let ringbuf = &mut self.ringbuf; | 275 | // info!("Written: {}/{}", written_len, buffer.len()); |
| 297 | let table = &mut self.table; | ||
| 298 | |||
| 299 | while written_len != len { | ||
| 300 | // info!( | ||
| 301 | // "read {}, write {}, cap {}", | ||
| 302 | // ringbuf.read_index(0), | ||
| 303 | // ringbuf.write_index(0), | ||
| 304 | // ringbuf.cap() | ||
| 305 | // ); | ||
| 306 | |||
| 307 | let dma_buffer_half = if ringbuf.read_index(0) < ringbuf.cap() / 2 { | ||
| 308 | BufferHalf::First | ||
| 309 | } else { | ||
| 310 | BufferHalf::Second | ||
| 311 | }; | ||
| 312 | |||
| 313 | // if dma_buffer_half == *user_buffer_half { | ||
| 314 | // info!("swap user from {}", user_buffer_half); | ||
| 315 | // table.unlink(); | ||
| 316 | |||
| 317 | // match user_buffer_half { | ||
| 318 | // BufferHalf::First => table.link_indices(1, 0), | ||
| 319 | // BufferHalf::Second => table.link_indices(0, 1), | ||
| 320 | // } | ||
| 321 | |||
| 322 | // user_buffer_half.toggle(); | ||
| 323 | // } | ||
| 324 | |||
| 325 | let index = match dma_buffer_half { | ||
| 326 | BufferHalf::First => { | ||
| 327 | // Fill up second buffer half when DMA reads the first. | ||
| 328 | cap - 1 | ||
| 329 | } | ||
| 330 | BufferHalf::Second => { | ||
| 331 | // Fill up first buffer half when DMA reads the second. | ||
| 332 | cap / 2 - 1 | ||
| 333 | } | ||
| 334 | }; | ||
| 335 | |||
| 336 | (written_len, remaining_cap) = ringbuf.write_until(dma, &buffer, index).await?; | ||
| 337 | } | 276 | } |
| 338 | info!("done"); | ||
| 339 | 277 | ||
| 340 | Ok(remaining_cap) | 278 | Ok(remaining_cap) |
| 341 | } | 279 | } |
diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs index c4bf4dd60..8d00d822d 100644 --- a/embassy-stm32/src/dma/ringbuffer/mod.rs +++ b/embassy-stm32/src/dma/ringbuffer/mod.rs | |||
| @@ -3,6 +3,14 @@ use core::task::{Poll, Waker}; | |||
| 3 | 3 | ||
| 4 | use crate::dma::word::Word; | 4 | use crate::dma::word::Word; |
| 5 | 5 | ||
| 6 | /// The current buffer half (e.g. for DMA or the user application). | ||
| 7 | #[derive(Debug, PartialEq, PartialOrd)] | ||
| 8 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 9 | enum BufferHalf { | ||
| 10 | First, | ||
| 11 | Second, | ||
| 12 | } | ||
| 13 | |||
| 6 | pub trait DmaCtrl { | 14 | pub trait DmaCtrl { |
| 7 | /// Get the NDTR register value, i.e. the space left in the underlying | 15 | /// Get the NDTR register value, i.e. the space left in the underlying |
| 8 | /// buffer until the dma writer wraps. | 16 | /// buffer until the dma writer wraps. |
| @@ -92,16 +100,6 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> { | |||
| 92 | } | 100 | } |
| 93 | } | 101 | } |
| 94 | 102 | ||
| 95 | /// The current ring-buffer read index. | ||
| 96 | pub fn read_index(&self, offset: usize) -> usize { | ||
| 97 | self.read_index.as_index(self.cap(), offset) | ||
| 98 | } | ||
| 99 | |||
| 100 | /// The current ring-buffer write index. | ||
| 101 | pub fn write_index(&self, offset: usize) -> usize { | ||
| 102 | self.write_index.as_index(self.cap(), offset) | ||
| 103 | } | ||
| 104 | |||
| 105 | /// Reset the ring buffer to its initial state. | 103 | /// Reset the ring buffer to its initial state. |
| 106 | pub fn reset(&mut self, dma: &mut impl DmaCtrl) { | 104 | pub fn reset(&mut self, dma: &mut impl DmaCtrl) { |
| 107 | dma.reset_complete_count(); | 105 | dma.reset_complete_count(); |
| @@ -218,14 +216,13 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { | |||
| 218 | } | 216 | } |
| 219 | } | 217 | } |
| 220 | 218 | ||
| 221 | /// The current ring-buffer read index. | 219 | /// The buffer half that is in use by the DMA. |
| 222 | pub fn read_index(&self, offset: usize) -> usize { | 220 | fn dma_half(&self) -> BufferHalf { |
| 223 | self.read_index.as_index(self.cap(), offset) | 221 | if self.read_index.as_index(self.cap(), 0) < self.cap() / 2 { |
| 224 | } | 222 | BufferHalf::First |
| 225 | 223 | } else { | |
| 226 | /// The current ring-buffer write index. | 224 | BufferHalf::Second |
| 227 | pub fn write_index(&self, offset: usize) -> usize { | 225 | } |
| 228 | self.write_index.as_index(self.cap(), offset) | ||
| 229 | } | 226 | } |
| 230 | 227 | ||
| 231 | /// Reset the ring buffer to its initial state. The buffer after the reset will be full. | 228 | /// Reset the ring buffer to its initial state. The buffer after the reset will be full. |
| @@ -305,6 +302,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { | |||
| 305 | /// Write an exact number of elements to the ringbuffer. | 302 | /// Write an exact number of elements to the ringbuffer. |
| 306 | /// | 303 | /// |
| 307 | /// Returns the remaining write capacity in the buffer. | 304 | /// Returns the remaining write capacity in the buffer. |
| 305 | #[allow(dead_code)] | ||
| 308 | pub async fn write_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<usize, Error> { | 306 | pub async fn write_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<usize, Error> { |
| 309 | let mut written_len = 0; | 307 | let mut written_len = 0; |
| 310 | let buffer_len = buffer.len(); | 308 | let buffer_len = buffer.len(); |
| @@ -327,31 +325,41 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { | |||
| 327 | .await | 325 | .await |
| 328 | } | 326 | } |
| 329 | 327 | ||
| 330 | /// Write until a given write index. | 328 | /// Write the user's current buffer half - not used by the DMA. |
| 331 | /// | 329 | /// |
| 332 | /// Returns a tuple of the written length, and the remaining write capacity in the buffer. | 330 | /// Returns a tuple of the written length, and the remaining write capacity in the buffer. |
| 333 | pub async fn write_until( | 331 | #[allow(dead_code)] |
| 334 | &mut self, | 332 | pub async fn write_half(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<(usize, usize), Error> { |
| 335 | dma: &mut impl DmaCtrl, | ||
| 336 | buffer: &[W], | ||
| 337 | index: usize, | ||
| 338 | ) -> Result<(usize, usize), Error> { | ||
| 339 | let mut written_len = 0; | 333 | let mut written_len = 0; |
| 340 | let write_len = index | 334 | let buffer_len = buffer.len(); |
| 341 | .saturating_sub(self.write_index.as_index(self.cap(), 0)) | ||
| 342 | .min(buffer.len()); | ||
| 343 | |||
| 344 | if write_len == 0 { | ||
| 345 | return Err(Error::Overrun); | ||
| 346 | } | ||
| 347 | 335 | ||
| 348 | poll_fn(|cx| { | 336 | poll_fn(|cx| { |
| 349 | dma.set_waker(cx.waker()); | 337 | dma.set_waker(cx.waker()); |
| 350 | 338 | ||
| 351 | match self.write(dma, &buffer[written_len..write_len]) { | 339 | let dma_half = self.dma_half(); |
| 340 | // let user_half = self.user_half(); | ||
| 341 | |||
| 342 | // if dma_half == user_half { | ||
| 343 | // info!("ups"); | ||
| 344 | // return Poll::Ready(Err(Error::Overrun)); | ||
| 345 | // } | ||
| 346 | |||
| 347 | let write_index = self.write_index.as_index(self.cap(), 0); | ||
| 348 | let target_write_len = match dma_half { | ||
| 349 | BufferHalf::First => self.cap().saturating_sub(write_index), | ||
| 350 | BufferHalf::Second => (self.cap() / 2).saturating_sub(write_index), | ||
| 351 | }; | ||
| 352 | let write_end_index = (target_write_len + written_len).min(buffer_len); | ||
| 353 | |||
| 354 | // info!( | ||
| 355 | // "buf_len: {}, write_len: {}, write_index: {}", | ||
| 356 | // buffer_len, target_write_len, write_index | ||
| 357 | // ); | ||
| 358 | |||
| 359 | match self.write(dma, &buffer[written_len..write_end_index]) { | ||
| 352 | Ok((len, remaining)) => { | 360 | Ok((len, remaining)) => { |
| 353 | written_len += len; | 361 | written_len += len; |
| 354 | if written_len == write_len { | 362 | if written_len == write_end_index { |
| 355 | Poll::Ready(Ok((written_len, remaining))) | 363 | Poll::Ready(Ok((written_len, remaining))) |
| 356 | } else { | 364 | } else { |
| 357 | Poll::Pending | 365 | Poll::Pending |
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 1d4a44896..5f4e87834 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -381,7 +381,7 @@ impl ReadReady for RingBufferedUartRx<'_> { | |||
| 381 | crate::dma::ringbuffer::Error::Overrun => Self::Error::Overrun, | 381 | crate::dma::ringbuffer::Error::Overrun => Self::Error::Overrun, |
| 382 | crate::dma::ringbuffer::Error::DmaUnsynced => { | 382 | crate::dma::ringbuffer::Error::DmaUnsynced => { |
| 383 | error!( | 383 | error!( |
| 384 | "Ringbuffer error: DmaUNsynced, driver implementation is | 384 | "Ringbuffer error: DmaUNsynced, driver implementation is |
| 385 | probably bugged please open an issue" | 385 | probably bugged please open an issue" |
| 386 | ); | 386 | ); |
| 387 | // we report this as overrun since its recoverable in the same way | 387 | // we report this as overrun since its recoverable in the same way |
