aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/dma/gpdma/ringbuffered.rs
diff options
context:
space:
mode:
authoretiennecollin <[email protected]>2025-08-25 21:10:59 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-05 14:43:29 +0200
commit50e2e2ec60ca32a2da53b91f4a30c3a71d4e9f30 (patch)
treeffaed485eb5b2300b938d8093b3ea03efe4e6e81 /embassy-stm32/src/dma/gpdma/ringbuffered.rs
parent4291a092bedb0f45d236a1847a9b85fd093d3af9 (diff)
feat: add new_with_table() initializer for ring-buffers and removal of RegisterUpdaters
- It is now possible to pass a linked-list table to the ring-buffer with the `new_with_table()` function or use the `new()` function for a basic ring-buffer setup. - A `simple_ring_buffer_table()` function was added to the read and write ring-buffers to generate the same table as the one created by `new()` in case the user only wants to customize the default table options. - RegisterUpdaters have been removed as the user now has direct access to the table and its items if needed. See: https://github.com/elagil/embassy/pull/1#issuecomment-2891997294
Diffstat (limited to 'embassy-stm32/src/dma/gpdma/ringbuffered.rs')
-rw-r--r--embassy-stm32/src/dma/gpdma/ringbuffered.rs112
1 files changed, 82 insertions, 30 deletions
diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs
index 359bc83b3..d7451285e 100644
--- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs
+++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs
@@ -8,7 +8,7 @@ use core::task::Waker;
8 8
9use embassy_hal_internal::Peri; 9use embassy_hal_internal::Peri;
10 10
11use super::{AnyChannel, RegisterUpdaters, TransferOptions, STATE}; 11use super::{AnyChannel, TransferOptions, STATE};
12use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; 12use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table};
13use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; 13use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer};
14use crate::dma::word::Word; 14use crate::dma::word::Word;
@@ -48,14 +48,14 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> {
48} 48}
49 49
50/// Ringbuffer for receiving data using GPDMA linked-list mode. 50/// Ringbuffer for receiving data using GPDMA linked-list mode.
51pub struct ReadableRingBuffer<'a, W: Word> { 51pub struct ReadableRingBuffer<'a, W: Word, const L: usize> {
52 channel: Peri<'a, AnyChannel>, 52 channel: Peri<'a, AnyChannel>,
53 ringbuf: ReadableDmaRingBuffer<'a, W>, 53 ringbuf: ReadableDmaRingBuffer<'a, W>,
54 table: Table<2>, 54 table: Table<L>,
55 options: TransferOptions, 55 options: TransferOptions,
56} 56}
57 57
58impl<'a, W: Word> ReadableRingBuffer<'a, W> { 58impl<'a, W: Word> ReadableRingBuffer<'a, W, 2> {
59 /// Create a new ring buffer. 59 /// Create a new ring buffer.
60 /// 60 ///
61 /// Transfer options are applied to the individual linked list items. 61 /// Transfer options are applied to the individual linked list items.
@@ -65,19 +65,30 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
65 peri_addr: *mut W, 65 peri_addr: *mut W,
66 buffer: &'a mut [W], 66 buffer: &'a mut [W],
67 options: TransferOptions, 67 options: TransferOptions,
68 register_updaters: RegisterUpdaters,
69 ) -> Self { 68 ) -> Self {
70 let channel: Peri<'a, AnyChannel> = channel.into(); 69 let channel: Peri<'a, AnyChannel> = channel.into();
70 let table = Self::simple_ring_buffer_table(request, peri_addr, buffer);
71 71
72 // Buffer halves should be the same length. 72 Self {
73 let half_len = buffer.len() / 2; 73 channel,
74 assert_eq!(half_len * 2, buffer.len()); 74 ringbuf: ReadableDmaRingBuffer::new(buffer),
75 table,
76 options,
77 }
78 }
79}
75 80
76 let items = [ 81impl<'a, W: Word, const L: usize> ReadableRingBuffer<'a, W, L> {
77 LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], &register_updaters), 82 /// Create a new ring buffer with a provided linked-list table.
78 LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], &register_updaters), 83 ///
79 ]; 84 /// Transfer options are applied to the individual linked list items.
80 let table = Table::new(items); 85 pub fn new_with_table(
86 channel: Peri<'a, impl Channel>,
87 buffer: &'a mut [W],
88 options: TransferOptions,
89 table: Table<L>,
90 ) -> Self {
91 let channel: Peri<'a, AnyChannel> = channel.into();
81 92
82 Self { 93 Self {
83 channel, 94 channel,
@@ -87,6 +98,21 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
87 } 98 }
88 } 99 }
89 100
101 /// Create a new simple linked-list table.
102 ///
103 /// This uses two linked-list items, one for each half of the buffer.
104 pub unsafe fn simple_ring_buffer_table(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> {
105 // Buffer halves should be the same length.
106 let half_len = buffer.len() / 2;
107 assert_eq!(half_len * 2, buffer.len());
108
109 let items = [
110 LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]),
111 LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]),
112 ];
113 Table::new(items)
114 }
115
90 /// Start the ring buffer operation. 116 /// Start the ring buffer operation.
91 pub fn start(&mut self) { 117 pub fn start(&mut self) {
92 // Apply the default configuration to the channel. 118 // Apply the default configuration to the channel.
@@ -190,7 +216,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
190 } 216 }
191} 217}
192 218
193impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { 219impl<'a, W: Word, const L: usize> Drop for ReadableRingBuffer<'a, W, L> {
194 fn drop(&mut self) { 220 fn drop(&mut self) {
195 self.request_suspend(); 221 self.request_suspend();
196 while self.is_running() {} 222 while self.is_running() {}
@@ -201,43 +227,69 @@ impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> {
201} 227}
202 228
203/// Ringbuffer for writing data using GPDMA linked-list mode. 229/// Ringbuffer for writing data using GPDMA linked-list mode.
204pub struct WritableRingBuffer<'a, W: Word> { 230pub struct WritableRingBuffer<'a, W: Word, const L: usize> {
205 channel: Peri<'a, AnyChannel>, 231 channel: Peri<'a, AnyChannel>,
206 ringbuf: WritableDmaRingBuffer<'a, W>, 232 ringbuf: WritableDmaRingBuffer<'a, W>,
207 table: Table<2>, 233 table: Table<L>,
208 options: TransferOptions, 234 options: TransferOptions,
209} 235}
210 236
211impl<'a, W: Word> WritableRingBuffer<'a, W> { 237impl<'a, W: Word> WritableRingBuffer<'a, W, 2> {
212 /// Create a new ring buffer. 238 /// Create a new ring buffer.
239 ///
240 /// Transfer options are applied to the individual linked list items.
213 pub unsafe fn new( 241 pub unsafe fn new(
214 channel: Peri<'a, impl Channel>, 242 channel: Peri<'a, impl Channel>,
215 request: Request, 243 request: Request,
216 peri_addr: *mut W, 244 peri_addr: *mut W,
217 buffer: &'a mut [W], 245 buffer: &'a mut [W],
218 options: TransferOptions, 246 options: TransferOptions,
219 register_updaters: RegisterUpdaters,
220 ) -> Self { 247 ) -> Self {
221 let channel: Peri<'a, AnyChannel> = channel.into(); 248 let channel: Peri<'a, AnyChannel> = channel.into();
249 let table = Self::simple_ring_buffer_table(request, peri_addr, buffer);
222 250
223 // Buffer halves should be the same length. 251 Self {
224 let half_len = buffer.len() / 2; 252 channel,
225 assert_eq!(half_len * 2, buffer.len()); 253 ringbuf: WritableDmaRingBuffer::new(buffer),
254 table,
255 options,
256 }
257 }
258}
226 259
227 let items = [ 260impl<'a, W: Word, const L: usize> WritableRingBuffer<'a, W, L> {
228 LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, &register_updaters), 261 /// Create a new ring buffer with a provided linked-list table.
229 LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, &register_updaters), 262 ///
230 ]; 263 /// Transfer options are applied to the individual linked list items.
231 let table = Table::new(items); 264 pub fn new_with_table(
265 channel: Peri<'a, impl Channel>,
266 buffer: &'a mut [W],
267 options: TransferOptions,
268 table: Table<L>,
269 ) -> Self {
270 let channel: Peri<'a, AnyChannel> = channel.into();
232 271
233 let this = Self { 272 Self {
234 channel, 273 channel,
235 ringbuf: WritableDmaRingBuffer::new(buffer), 274 ringbuf: WritableDmaRingBuffer::new(buffer),
236 table, 275 table,
237 options, 276 options,
238 }; 277 }
278 }
239 279
240 this 280 /// Create a new simple linked-list table.
281 ///
282 /// This uses two linked-list items, one for each half of the buffer.
283 pub unsafe fn simple_ring_buffer_table(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> {
284 // Buffer halves should be the same length.
285 let half_len = buffer.len() / 2;
286 assert_eq!(half_len * 2, buffer.len());
287
288 let items = [
289 LinearItem::new_write(request, &mut buffer[..half_len], peri_addr),
290 LinearItem::new_write(request, &mut buffer[half_len..], peri_addr),
291 ];
292 Table::new(items)
241 } 293 }
242 294
243 /// Start the ring buffer operation. 295 /// Start the ring buffer operation.
@@ -343,7 +395,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
343 } 395 }
344} 396}
345 397
346impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { 398impl<'a, W: Word, const L: usize> Drop for WritableRingBuffer<'a, W, L> {
347 fn drop(&mut self) { 399 fn drop(&mut self) {
348 self.request_suspend(); 400 self.request_suspend();
349 while self.is_running() {} 401 while self.is_running() {}