diff options
| author | etiennecollin <[email protected]> | 2025-08-25 21:10:59 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2025-09-05 14:43:29 +0200 |
| commit | 50e2e2ec60ca32a2da53b91f4a30c3a71d4e9f30 (patch) | |
| tree | ffaed485eb5b2300b938d8093b3ea03efe4e6e81 /embassy-stm32/src/dma/gpdma/ringbuffered.rs | |
| parent | 4291a092bedb0f45d236a1847a9b85fd093d3af9 (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.rs | 112 |
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 | ||
| 9 | use embassy_hal_internal::Peri; | 9 | use embassy_hal_internal::Peri; |
| 10 | 10 | ||
| 11 | use super::{AnyChannel, RegisterUpdaters, TransferOptions, STATE}; | 11 | use super::{AnyChannel, TransferOptions, STATE}; |
| 12 | use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; | 12 | use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; |
| 13 | use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; | 13 | use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; |
| 14 | use crate::dma::word::Word; | 14 | use 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. |
| 51 | pub struct ReadableRingBuffer<'a, W: Word> { | 51 | pub 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 | ||
| 58 | impl<'a, W: Word> ReadableRingBuffer<'a, W> { | 58 | impl<'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 = [ | 81 | impl<'a, W: Word, const L: usize> ReadableRingBuffer<'a, W, L> { |
| 77 | LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], ®ister_updaters), | 82 | /// Create a new ring buffer with a provided linked-list table. |
| 78 | LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], ®ister_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 | ||
| 193 | impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { | 219 | impl<'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. |
| 204 | pub struct WritableRingBuffer<'a, W: Word> { | 230 | pub 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 | ||
| 211 | impl<'a, W: Word> WritableRingBuffer<'a, W> { | 237 | impl<'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 = [ | 260 | impl<'a, W: Word, const L: usize> WritableRingBuffer<'a, W, L> { |
| 228 | LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, ®ister_updaters), | 261 | /// Create a new ring buffer with a provided linked-list table. |
| 229 | LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, ®ister_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 | ||
| 346 | impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { | 398 | impl<'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() {} |
