diff options
| author | elagil <[email protected]> | 2025-08-25 21:10:59 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2025-09-05 14:43:29 +0200 |
| commit | a4d3b4b6ae3f3265ea372e446a6e7b5d3685ea3a (patch) | |
| tree | 979b06f9ea1261a2fcb3a5b5c840796a5cf59998 /embassy-stm32/src/dma/ringbuffer | |
| parent | 78364b966eb76c071d5450c2a13cc788d7e5be80 (diff) | |
feat: wip, write buffer in halves
Diffstat (limited to 'embassy-stm32/src/dma/ringbuffer')
| -rw-r--r-- | embassy-stm32/src/dma/ringbuffer/mod.rs | 76 |
1 files changed, 42 insertions, 34 deletions
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 |
