mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-29 05:10:55 +00:00
Add Final assoctype to DMA buffers (#3923)
This commit is contained in:
parent
8c86bf727a
commit
30b46809c6
@ -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
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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) };
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user