Add Final assoctype to DMA buffers (#3923)

This commit is contained in:
Dániel Buga 2025-08-11 18:28:23 +02:00 committed by GitHub
parent 8c86bf727a
commit 30b46809c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 53 additions and 17 deletions

View File

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- A new default feature `exception-handler` was added (#3887)
- `AesBackend, AesContext`: Work-queue based AES driver (#3880)
- `aes::cipher_modes`, `aes::CipherModeState` for constructing `AesContext`s (#3895)
- `DmaTxBuffer` and `DmaRxBuffer` now have a `Final` associated type. (#3923)
### Changed
@ -31,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `Rsa::read` function has been removed. The constructor now blocks until the peripheral's memory has been cleared (#3900)
- `Rsa::enable_constant_time_acceleration` has been renamed to `Rsa::disable_constant_time` (#3900)
- `Rsa::enable_search_acceleration` has been renamed to `Rsa::search_acceleration` (#3900)
- `DmaTxBuffer::from_view` and `DmaRxBuffer::from_view` now return an object with type `DmaTx/RxBuffer::Final`. (#3923)
### Fixed

View File

@ -91,3 +91,19 @@ let _ = tx_channel.transmit(&tx_data).wait().unwrap();
let _ = rx_channel.transmit(&mut rx_data).wait().unwrap();
```
## DMA changes
DMA buffers now have a `Final` associated type parameter. For the publicly available buffer, this is `Self`,
so there is no code change necessary in user codebases. Library writes will need to add the type to their
DMA buffer implementations.
```diff
unsafe impl DmaTxBuffer for MyTxBuf {
type View = BufView<Self>;
+ type Final = Self;
// ...
}
```
If the `Final` type is not `Self`, `fn from_view()` will need to be updated to return `Self::Final`.

View File

@ -537,7 +537,7 @@ pub mod dma {
/// Waits for the transfer to finish and returns the peripheral and
/// buffers.
pub fn wait(mut self) -> (AesDma<'d>, RX, TX) {
pub fn wait(mut self) -> (AesDma<'d>, RX::Final, TX::Final) {
while !self.is_done() {}
// Stop the DMA as it doesn't know that the aes has stopped.

View File

@ -425,6 +425,11 @@ pub unsafe trait DmaTxBuffer {
/// whilst the DMA is actively using it.
type View;
/// The type returned to the user when a transfer finishes.
///
/// Some buffers don't need to be reconstructed.
type Final;
/// Prepares the buffer for an imminent transfer and returns
/// information required to use this buffer.
///
@ -435,7 +440,7 @@ pub unsafe trait DmaTxBuffer {
fn into_view(self) -> Self::View;
/// This is called after the DMA is done using the buffer.
fn from_view(view: Self::View) -> Self;
fn from_view(view: Self::View) -> Self::Final;
}
/// [DmaRxBuffer] is a DMA descriptor + memory combo that can be used for
@ -454,6 +459,11 @@ pub unsafe trait DmaRxBuffer {
/// whilst the DMA is actively using it.
type View;
/// The type returned to the user when a transfer finishes.
///
/// Some buffers don't need to be reconstructed.
type Final;
/// Prepares the buffer for an imminent transfer and returns
/// information required to use this buffer.
///
@ -464,7 +474,7 @@ pub unsafe trait DmaRxBuffer {
fn into_view(self) -> Self::View;
/// This is called after the DMA is done using the buffer.
fn from_view(view: Self::View) -> Self;
fn from_view(view: Self::View) -> Self::Final;
}
/// An in-progress view into [DmaRxBuf]/[DmaTxBuf].
@ -623,6 +633,7 @@ impl DmaTxBuf {
unsafe impl DmaTxBuffer for DmaTxBuf {
type View = BufView<DmaTxBuf>;
type Final = DmaTxBuf;
fn prepare(&mut self) -> Preparation {
cfg_if::cfg_if! {
@ -829,6 +840,7 @@ impl DmaRxBuf {
unsafe impl DmaRxBuffer for DmaRxBuf {
type View = BufView<DmaRxBuf>;
type Final = DmaRxBuf;
fn prepare(&mut self) -> Preparation {
for desc in self.descriptors.linked_iter_mut() {
@ -1009,6 +1021,7 @@ impl DmaRxTxBuf {
unsafe impl DmaTxBuffer for DmaRxTxBuf {
type View = BufView<DmaRxTxBuf>;
type Final = DmaRxTxBuf;
fn prepare(&mut self) -> Preparation {
for desc in self.tx_descriptors.linked_iter_mut() {
@ -1054,6 +1067,7 @@ unsafe impl DmaTxBuffer for DmaRxTxBuf {
unsafe impl DmaRxBuffer for DmaRxTxBuf {
type View = BufView<DmaRxTxBuf>;
type Final = DmaRxTxBuf;
fn prepare(&mut self) -> Preparation {
for desc in self.rx_descriptors.linked_iter_mut() {
@ -1202,6 +1216,7 @@ impl DmaRxStreamBuf {
unsafe impl DmaRxBuffer for DmaRxStreamBuf {
type View = DmaRxStreamBufView;
type Final = DmaRxStreamBuf;
fn prepare(&mut self) -> Preparation {
// Link up all the descriptors (but not in a circle).
@ -1419,6 +1434,7 @@ pub struct EmptyBuf;
unsafe impl DmaTxBuffer for EmptyBuf {
type View = EmptyBuf;
type Final = EmptyBuf;
fn prepare(&mut self) -> Preparation {
Preparation {
@ -1448,6 +1464,7 @@ unsafe impl DmaTxBuffer for EmptyBuf {
unsafe impl DmaRxBuffer for EmptyBuf {
type View = EmptyBuf;
type Final = EmptyBuf;
fn prepare(&mut self) -> Preparation {
Preparation {
@ -1523,7 +1540,8 @@ impl DmaLoopBuf {
}
unsafe impl DmaTxBuffer for DmaLoopBuf {
type View = Self;
type View = DmaLoopBuf;
type Final = DmaLoopBuf;
fn prepare(&mut self) -> Preparation {
Preparation {

View File

@ -196,7 +196,7 @@ impl<'d, M: DriverMode, BUF: DmaRxBuffer> Mem2MemRxTransfer<'d, M, BUF> {
}
/// Waits for the transfer to stop and returns the peripheral and buffer.
pub fn wait(self) -> (Result<(), DmaError>, Mem2MemRx<'d, M>, BUF) {
pub fn wait(self) -> (Result<(), DmaError>, Mem2MemRx<'d, M>, BUF::Final) {
while !self.is_done() {}
let (m2m, view) = self.release();
@ -211,7 +211,7 @@ impl<'d, M: DriverMode, BUF: DmaRxBuffer> Mem2MemRxTransfer<'d, M, BUF> {
}
/// Stops this transfer on the spot and returns the peripheral and buffer.
pub fn stop(self) -> (Mem2MemRx<'d, M>, BUF) {
pub fn stop(self) -> (Mem2MemRx<'d, M>, BUF::Final) {
let (mut m2m, view) = self.release();
m2m.channel.stop_transfer();
@ -324,7 +324,7 @@ impl<'d, Dm: DriverMode, BUF: DmaTxBuffer> Mem2MemTxTransfer<'d, Dm, BUF> {
}
/// Waits for the transfer to stop and returns the peripheral and buffer.
pub fn wait(self) -> (Result<(), DmaError>, Mem2MemTx<'d, Dm>, BUF) {
pub fn wait(self) -> (Result<(), DmaError>, Mem2MemTx<'d, Dm>, BUF::Final) {
while !self.is_done() {}
let (m2m, view) = self.release();
@ -339,7 +339,7 @@ impl<'d, Dm: DriverMode, BUF: DmaTxBuffer> Mem2MemTxTransfer<'d, Dm, BUF> {
}
/// Stops this transfer on the spot and returns the peripheral and buffer.
pub fn stop(self) -> (Mem2MemTx<'d, Dm>, BUF) {
pub fn stop(self) -> (Mem2MemTx<'d, Dm>, BUF::Final) {
let (mut m2m, view) = self.release();
m2m.channel.stop_transfer();

View File

@ -355,7 +355,7 @@ where
}
/// Wait for the transfer to finish
pub fn wait(mut self) -> (I2sParallel<'d, Dm>, BUF) {
pub fn wait(mut self) -> (I2sParallel<'d, Dm>, BUF::Final) {
self.i2s.instance.tx_wait_done();
let i2s = unsafe { ManuallyDrop::take(&mut self.i2s) };
let view = unsafe { ManuallyDrop::take(&mut self.buf_view) };

View File

@ -461,7 +461,7 @@ impl<'d, BUF: DmaRxBuffer> CameraTransfer<'d, BUF> {
}
/// Stops this transfer on the spot and returns the peripheral and buffer.
pub fn stop(mut self) -> (Camera<'d>, BUF) {
pub fn stop(mut self) -> (Camera<'d>, BUF::Final) {
self.stop_peripherals();
let (camera, view) = self.release();
(camera, BUF::from_view(view))
@ -472,7 +472,7 @@ impl<'d, BUF: DmaRxBuffer> CameraTransfer<'d, BUF> {
/// Note: The camera doesn't really "finish" its transfer, so what you're
/// really waiting for here is a DMA Error. You typically just want to
/// call [Self::stop] once you have the data you need.
pub fn wait(mut self) -> (Result<(), DmaError>, Camera<'d>, BUF) {
pub fn wait(mut self) -> (Result<(), DmaError>, Camera<'d>, BUF::Final) {
while !self.is_done() {}
// Stop the DMA as it doesn't know that the camera has stopped.

View File

@ -558,7 +558,7 @@ impl<'d, BUF: DmaTxBuffer, Dm: DriverMode> DpiTransfer<'d, BUF, Dm> {
}
/// Stops this transfer on the spot and returns the peripheral and buffer.
pub fn stop(mut self) -> (Dpi<'d, Dm>, BUF) {
pub fn stop(mut self) -> (Dpi<'d, Dm>, BUF::Final) {
self.stop_peripherals();
let (dpi, view) = self.release();
(dpi, BUF::from_view(view))
@ -568,7 +568,7 @@ impl<'d, BUF: DmaTxBuffer, Dm: DriverMode> DpiTransfer<'d, BUF, Dm> {
///
/// Note: If you specified `next_frame_en` as true in [Dpi::send], you're
/// just waiting for a DMA error when you call this.
pub fn wait(mut self) -> (Result<(), DmaError>, Dpi<'d, Dm>, BUF) {
pub fn wait(mut self) -> (Result<(), DmaError>, Dpi<'d, Dm>, BUF::Final) {
while !self.is_done() {
core::hint::spin_loop();
}

View File

@ -424,7 +424,7 @@ impl<'d, BUF: DmaTxBuffer, Dm: DriverMode> I8080Transfer<'d, BUF, Dm> {
}
/// Stops this transfer on the spot and returns the peripheral and buffer.
pub fn cancel(mut self) -> (I8080<'d, Dm>, BUF) {
pub fn cancel(mut self) -> (I8080<'d, Dm>, BUF::Final) {
self.stop_peripherals();
let (_, i8080, buf) = self.wait();
(i8080, buf)
@ -434,7 +434,7 @@ impl<'d, BUF: DmaTxBuffer, Dm: DriverMode> I8080Transfer<'d, BUF, Dm> {
///
/// Note: This also clears the transfer interrupt so it can be used in
/// interrupt handlers to "handle" the interrupt.
pub fn wait(mut self) -> (Result<(), DmaError>, I8080<'d, Dm>, BUF) {
pub fn wait(mut self) -> (Result<(), DmaError>, I8080<'d, Dm>, BUF::Final) {
while !self.is_done() {}
// Clear "done" interrupt.

View File

@ -1278,7 +1278,7 @@ impl<'d, BUF: DmaTxBuffer, Dm: DriverMode> ParlIoTxTransfer<'d, BUF, Dm> {
}
/// Waits for the transfer to finish and returns the peripheral and buffer.
pub fn wait(mut self) -> (Result<(), DmaError>, ParlIoTx<'d, Dm>, BUF) {
pub fn wait(mut self) -> (Result<(), DmaError>, ParlIoTx<'d, Dm>, BUF::Final) {
while !self.is_done() {}
Instance::set_tx_start(false);
@ -1446,7 +1446,7 @@ impl<'d, BUF: DmaRxBuffer, Dm: DriverMode> ParlIoRxTransfer<'d, BUF, Dm> {
}
/// Waits for the transfer to finish and returns the peripheral and buffer.
pub fn wait(mut self) -> (Result<(), DmaError>, ParlIoRx<'d, Dm>, BUF) {
pub fn wait(mut self) -> (Result<(), DmaError>, ParlIoRx<'d, Dm>, BUF::Final) {
while !self.is_done() {}
Instance::set_rx_start(false);