aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/dma/ringbuffer
diff options
context:
space:
mode:
authorelagil <[email protected]>2025-08-25 21:10:59 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-05 14:43:29 +0200
commita4d3b4b6ae3f3265ea372e446a6e7b5d3685ea3a (patch)
tree979b06f9ea1261a2fcb3a5b5c840796a5cf59998 /embassy-stm32/src/dma/ringbuffer
parent78364b966eb76c071d5450c2a13cc788d7e5be80 (diff)
feat: wip, write buffer in halves
Diffstat (limited to 'embassy-stm32/src/dma/ringbuffer')
-rw-r--r--embassy-stm32/src/dma/ringbuffer/mod.rs76
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
4use crate::dma::word::Word; 4use 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))]
9enum BufferHalf {
10 First,
11 Second,
12}
13
6pub trait DmaCtrl { 14pub 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