Lift static requirement on DMA buffers (#1837)

* Lift `static` requirement on DMA buffers

* Seal `Word`, use `size_of_val`

* Fix

* CHANGELOG.md

* Use Clippy's safety comment style

* Top-level docs regarding mem::forget
This commit is contained in:
Björn Quentin 2024-07-25 15:55:02 +02:00 committed by GitHub
parent 45db1b55ec
commit c6207c0f59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 255 additions and 82 deletions

View File

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Use the peripheral ref pattern for `OneShotTimer` and `PeriodicTimer` (#1855)
- Allow DMA to/from psram for esp32s3 (#1827)
- DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837)
### Fixed

View File

@ -28,7 +28,6 @@ embassy-sync = { version = "0.6.0", optional = true }
embassy-usb-driver = { version = "0.1.0", optional = true }
embassy-usb-synopsys-otg = { version = "0.1.0", optional = true }
embedded-can = { version = "0.4.1", optional = true }
embedded-dma = "0.2.0"
embedded-hal-02 = { version = "0.2.7", optional = true, features = ["unproven"], package = "embedded-hal" }
embedded-hal = { version = "1.0.0", optional = true }
embedded-hal-async = { version = "1.0.0", optional = true }

View File

@ -220,8 +220,6 @@ pub enum Endianness {
/// CTR, CFB8, and CFB128.
#[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
pub mod dma {
use embedded_dma::{ReadBuffer, WriteBuffer};
use crate::{
aes::{Key, Mode},
dma::{
@ -235,8 +233,10 @@ pub mod dma {
DmaDescriptor,
DmaPeripheral,
DmaTransferTxRx,
ReadBuffer,
RxPrivate,
TxPrivate,
WriteBuffer,
},
};
@ -409,8 +409,8 @@ pub mod dma {
) -> Result<DmaTransferTxRx<Self>, crate::dma::DmaError>
where
K: Into<Key>,
TXBUF: ReadBuffer<Word = u8>,
RXBUF: WriteBuffer<Word = u8>,
TXBUF: ReadBuffer,
RXBUF: WriteBuffer,
{
let (write_ptr, write_len) = unsafe { words.read_buffer() };
let (read_ptr, read_len) = unsafe { read_buffer.write_buffer() };

View File

@ -638,8 +638,6 @@ impl<'d> Dma<'d> {
pub use m2m::*;
mod m2m {
use embedded_dma::{ReadBuffer, WriteBuffer};
#[cfg(esp32s3)]
use crate::dma::DmaExtMemBKSize;
use crate::dma::{
@ -653,8 +651,10 @@ mod m2m {
DmaError,
DmaPeripheral,
DmaTransferRx,
ReadBuffer,
RxPrivate,
TxPrivate,
WriteBuffer,
};
/// DMA Memory to Memory pseudo-Peripheral
@ -751,8 +751,8 @@ mod m2m {
rx_buffer: &'t mut RXBUF,
) -> Result<DmaTransferRx<Self>, DmaError>
where
TXBUF: ReadBuffer<Word = u8>,
RXBUF: WriteBuffer<Word = u8>,
TXBUF: ReadBuffer,
RXBUF: WriteBuffer,
{
let (tx_ptr, tx_len) = unsafe { tx_buffer.read_buffer() };
let (rx_ptr, rx_len) = unsafe { rx_buffer.write_buffer() };

View File

@ -54,6 +54,135 @@
use core::{fmt::Debug, marker::PhantomData, ptr::addr_of_mut, sync::atomic::compiler_fence};
trait Word: crate::private::Sealed {}
macro_rules! impl_word {
($w:ty) => {
impl $crate::private::Sealed for $w {}
impl Word for $w {}
};
}
impl_word!(u8);
impl_word!(u16);
impl_word!(u32);
impl_word!(i8);
impl_word!(i16);
impl_word!(i32);
impl<W, const S: usize> crate::private::Sealed for [W; S] where W: Word {}
impl<W, const S: usize> crate::private::Sealed for &[W; S] where W: Word {}
impl<W> crate::private::Sealed for &[W] where W: Word {}
impl<W> crate::private::Sealed for &mut [W] where W: Word {}
/// Trait for buffers that can be given to DMA for reading.
pub trait ReadBuffer: crate::private::Sealed {
/// Provide a buffer usable for DMA reads.
///
/// The return value is:
///
/// - pointer to the start of the buffer
/// - buffer size in bytes
///
/// # Safety
///
/// Once this method has been called, it is unsafe to call any `&mut self`
/// methods on this object as long as the returned value is in use (by DMA).
unsafe fn read_buffer(&self) -> (*const u8, usize);
}
impl<W, const S: usize> ReadBuffer for [W; S]
where
W: Word,
{
unsafe fn read_buffer(&self) -> (*const u8, usize) {
(self.as_ptr() as *const u8, core::mem::size_of_val(self))
}
}
impl<W, const S: usize> ReadBuffer for &[W; S]
where
W: Word,
{
unsafe fn read_buffer(&self) -> (*const u8, usize) {
(self.as_ptr() as *const u8, core::mem::size_of_val(*self))
}
}
impl<W, const S: usize> ReadBuffer for &mut [W; S]
where
W: Word,
{
unsafe fn read_buffer(&self) -> (*const u8, usize) {
(self.as_ptr() as *const u8, core::mem::size_of_val(*self))
}
}
impl<W> ReadBuffer for &[W]
where
W: Word,
{
unsafe fn read_buffer(&self) -> (*const u8, usize) {
(self.as_ptr() as *const u8, core::mem::size_of_val(*self))
}
}
impl<W> ReadBuffer for &mut [W]
where
W: Word,
{
unsafe fn read_buffer(&self) -> (*const u8, usize) {
(self.as_ptr() as *const u8, core::mem::size_of_val(*self))
}
}
/// Trait for buffers that can be given to DMA for writing.
pub trait WriteBuffer: crate::private::Sealed {
/// Provide a buffer usable for DMA writes.
///
/// The return value is:
///
/// - pointer to the start of the buffer
/// - buffer size in bytes
///
/// # Safety
///
/// Once this method has been called, it is unsafe to call any `&mut self`
/// methods, except for `write_buffer`, on this object as long as the
/// returned value is in use (by DMA).
unsafe fn write_buffer(&mut self) -> (*mut u8, usize);
}
impl<W, const S: usize> WriteBuffer for [W; S]
where
W: Word,
{
unsafe fn write_buffer(&mut self) -> (*mut u8, usize) {
(self.as_mut_ptr() as *mut u8, core::mem::size_of_val(self))
}
}
impl<W, const S: usize> WriteBuffer for &mut [W; S]
where
W: Word,
{
unsafe fn write_buffer(&mut self) -> (*mut u8, usize) {
(self.as_mut_ptr() as *mut u8, core::mem::size_of_val(*self))
}
}
impl<W> WriteBuffer for &mut [W]
where
W: Word,
{
unsafe fn write_buffer(&mut self) -> (*mut u8, usize) {
(self.as_mut_ptr() as *mut u8, core::mem::size_of_val(*self))
}
}
bitfield::bitfield! {
#[doc(hidden)]
#[derive(Clone, Copy)]
@ -130,7 +259,6 @@ impl DmaDescriptor {
}
}
use embedded_dma::{ReadBuffer, WriteBuffer};
use enumset::{EnumSet, EnumSetType};
#[cfg(gdma)]
@ -1741,6 +1869,10 @@ pub(crate) mod dma_private {
}
/// DMA transaction for TX only transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive]
#[must_use]
pub struct DmaTransferTx<'a, I>
@ -1785,6 +1917,10 @@ where
}
/// DMA transaction for RX only transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive]
#[must_use]
pub struct DmaTransferRx<'a, I>
@ -1829,6 +1965,10 @@ where
}
/// DMA transaction for TX+RX transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive]
#[must_use]
pub struct DmaTransferTxRx<'a, I>
@ -1874,12 +2014,16 @@ where
/// DMA transaction for TX transfers with moved-in/moved-out peripheral and
/// buffer
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive]
#[must_use]
pub struct DmaTransferTxOwned<I, T>
where
I: dma_private::DmaSupportTx,
T: ReadBuffer<Word = u8>,
T: ReadBuffer,
{
instance: I,
tx_buffer: T,
@ -1888,7 +2032,7 @@ where
impl<I, T> DmaTransferTxOwned<I, T>
where
I: dma_private::DmaSupportTx,
T: ReadBuffer<Word = u8>,
T: ReadBuffer,
{
pub(crate) fn new(instance: I, tx_buffer: T) -> Self {
Self {
@ -1936,7 +2080,7 @@ where
impl<I, T> Drop for DmaTransferTxOwned<I, T>
where
I: dma_private::DmaSupportTx,
T: ReadBuffer<Word = u8>,
T: ReadBuffer,
{
fn drop(&mut self) {
self.instance.peripheral_wait_dma(true, false);
@ -1945,12 +2089,16 @@ where
/// DMA transaction for RX transfers with moved-in/moved-out peripheral and
/// buffer
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive]
#[must_use]
pub struct DmaTransferRxOwned<I, R>
where
I: dma_private::DmaSupportRx,
R: WriteBuffer<Word = u8>,
R: WriteBuffer,
{
instance: I,
rx_buffer: R,
@ -1959,7 +2107,7 @@ where
impl<I, R> DmaTransferRxOwned<I, R>
where
I: dma_private::DmaSupportRx,
R: WriteBuffer<Word = u8>,
R: WriteBuffer,
{
pub(crate) fn new(instance: I, rx_buffer: R) -> Self {
Self {
@ -2007,7 +2155,7 @@ where
impl<I, R> Drop for DmaTransferRxOwned<I, R>
where
I: dma_private::DmaSupportRx,
R: WriteBuffer<Word = u8>,
R: WriteBuffer,
{
fn drop(&mut self) {
self.instance.peripheral_wait_dma(false, true);
@ -2016,13 +2164,17 @@ where
/// DMA transaction for TX+RX transfers with moved-in/moved-out peripheral and
/// buffers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive]
#[must_use]
pub struct DmaTransferTxRxOwned<I, T, R>
where
I: dma_private::DmaSupportTx + dma_private::DmaSupportRx,
T: ReadBuffer<Word = u8>,
R: WriteBuffer<Word = u8>,
T: ReadBuffer,
R: WriteBuffer,
{
instance: I,
tx_buffer: T,
@ -2032,8 +2184,8 @@ where
impl<I, T, R> DmaTransferTxRxOwned<I, T, R>
where
I: dma_private::DmaSupportTx + dma_private::DmaSupportRx,
T: ReadBuffer<Word = u8>,
R: WriteBuffer<Word = u8>,
T: ReadBuffer,
R: WriteBuffer,
{
pub(crate) fn new(instance: I, tx_buffer: T, rx_buffer: R) -> Self {
Self {
@ -2084,8 +2236,8 @@ where
impl<I, T, R> Drop for DmaTransferTxRxOwned<I, T, R>
where
I: dma_private::DmaSupportTx + dma_private::DmaSupportRx,
T: ReadBuffer<Word = u8>,
R: WriteBuffer<Word = u8>,
T: ReadBuffer,
R: WriteBuffer,
{
fn drop(&mut self) {
self.instance.peripheral_wait_dma(true, true);
@ -2093,6 +2245,10 @@ where
}
/// DMA transaction for TX only circular transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive]
#[must_use]
pub struct DmaTransferTxCircular<'a, I>
@ -2157,6 +2313,10 @@ where
}
/// DMA transaction for RX only circular transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive]
#[must_use]
pub struct DmaTransferRxCircular<'a, I>

View File

@ -82,7 +82,6 @@
use core::marker::PhantomData;
use embedded_dma::{ReadBuffer, WriteBuffer};
use enumset::{EnumSet, EnumSetType};
use private::*;
@ -105,8 +104,10 @@ use crate::{
DmaTransferTxCircular,
I2s0Peripheral,
I2sPeripheral,
ReadBuffer,
RxPrivate,
TxPrivate,
WriteBuffer,
},
gpio::OutputPin,
interrupt::InterruptHandler,
@ -252,7 +253,7 @@ where
/// transfer
fn write_dma<'t>(&'t mut self, words: &'t TXBUF) -> Result<DmaTransferTx<Self>, Error>
where
TXBUF: ReadBuffer<Word = u8>;
TXBUF: ReadBuffer;
/// Continuously write to I2S. Returns [DmaTransferTxCircular] which
/// represents the in-progress DMA transfer
@ -261,7 +262,7 @@ where
words: &'t TXBUF,
) -> Result<DmaTransferTxCircular<Self>, Error>
where
TXBUF: ReadBuffer<Word = u8>;
TXBUF: ReadBuffer;
}
/// Blocking I2S Read
@ -282,7 +283,7 @@ where
/// transfer
fn read_dma<'t>(&'t mut self, words: &'t mut RXBUF) -> Result<DmaTransferRx<Self>, Error>
where
RXBUF: WriteBuffer<Word = u8>;
RXBUF: WriteBuffer;
/// Continuously read from I2S.
/// Returns [DmaTransferRxCircular] which represents the in-progress DMA
@ -292,7 +293,7 @@ where
words: &'t mut RXBUF,
) -> Result<DmaTransferRxCircular<Self>, Error>
where
RXBUF: WriteBuffer<Word = u8>;
RXBUF: WriteBuffer;
}
/// Instance of the I2S peripheral driver
@ -588,7 +589,7 @@ where
circular: bool,
) -> Result<(), Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
DmaMode: Mode,
{
let (ptr, len) = unsafe { words.read_buffer() };
@ -647,7 +648,7 @@ where
{
fn write_dma<'t>(&'t mut self, words: &'t TXBUF) -> Result<DmaTransferTx<Self>, Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
self.start_tx_transfer(words, false)?;
Ok(DmaTransferTx::new(self))
@ -658,7 +659,7 @@ where
words: &'t TXBUF,
) -> Result<DmaTransferTxCircular<Self>, Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
self.start_tx_transfer(words, true)?;
Ok(DmaTransferTxCircular::new(self))
@ -769,7 +770,7 @@ where
circular: bool,
) -> Result<(), Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
let (ptr, len) = unsafe { words.write_buffer() };
@ -828,7 +829,7 @@ where
{
fn read_dma<'t>(&'t mut self, words: &'t mut RXBUF) -> Result<DmaTransferRx<Self>, Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
self.start_rx_transfer(words, false)?;
Ok(DmaTransferRx::new(self))
@ -839,7 +840,7 @@ where
words: &'t mut RXBUF,
) -> Result<DmaTransferRxCircular<Self>, Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
self.start_rx_transfer(words, true)?;
Ok(DmaTransferRxCircular::new(self))
@ -2151,17 +2152,17 @@ mod private {
#[cfg(feature = "async")]
pub mod asynch {
use embedded_dma::{ReadBuffer, WriteBuffer};
use super::{Error, I2sRx, I2sTx, RegisterAccess};
use crate::{
dma::{
asynch::{DmaRxDoneChFuture, DmaRxFuture, DmaTxDoneChFuture, DmaTxFuture},
DmaChannel,
ReadBuffer,
RxCircularState,
RxPrivate,
TxCircularState,
TxPrivate,
WriteBuffer,
},
Async,
};
@ -2181,7 +2182,7 @@ pub mod asynch {
words: TXBUF,
) -> Result<I2sWriteDmaTransferAsync<'d, T, CH, TXBUF>, Error>
where
TXBUF: ReadBuffer<Word = u8>;
TXBUF: ReadBuffer;
}
impl<'d, T, CH> I2sWriteDmaAsync<'d, T, CH> for super::I2sTx<'d, T, CH, Async>
@ -2215,7 +2216,7 @@ pub mod asynch {
words: TXBUF,
) -> Result<I2sWriteDmaTransferAsync<'d, T, CH, TXBUF>, Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
let (ptr, len) = unsafe { words.read_buffer() };
@ -2315,7 +2316,7 @@ pub mod asynch {
words: RXBUF,
) -> Result<I2sReadDmaTransferAsync<'d, T, CH, RXBUF>, Error>
where
RXBUF: WriteBuffer<Word = u8>;
RXBUF: WriteBuffer;
}
impl<'d, T, CH> I2sReadDmaAsync<'d, T, CH> for super::I2sRx<'d, T, CH, Async>
@ -2363,7 +2364,7 @@ pub mod asynch {
mut words: RXBUF,
) -> Result<I2sReadDmaTransferAsync<'d, T, CH, RXBUF>, Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
let (ptr, len) = unsafe { words.write_buffer() };

View File

@ -64,9 +64,6 @@
//! # }
//! ```
use core::mem::size_of;
use embedded_dma::WriteBuffer;
use fugit::HertzU32;
use crate::{
@ -83,6 +80,7 @@ use crate::{
DmaTransferRxCircular,
LcdCamPeripheral,
RxPrivate,
WriteBuffer,
},
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder},
@ -380,11 +378,10 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
) -> Result<(), DmaError> {
let (ptr, len) = unsafe { buf.write_buffer() };
assert_eq!(self.bus_width, size_of::<RXBUF::Word>());
assert!(len % self.bus_width == 0);
unsafe {
self.rx_chain
.fill_for_rx(circular, ptr as _, len * size_of::<RXBUF::Word>())?;
self.rx_chain.fill_for_rx(circular, ptr as _, len)?;
self.rx_channel
.prepare_transfer_without_start(DmaPeripheral::LcdCam, &self.rx_chain)?;
}

View File

@ -59,7 +59,6 @@
use core::{fmt::Formatter, mem::size_of};
use embedded_dma::ReadBuffer;
use fugit::HertzU32;
use crate::{
@ -74,6 +73,7 @@ use crate::{
DmaPeripheral,
DmaTransferTx,
LcdCamPeripheral,
ReadBuffer,
TxPrivate,
},
gpio::{OutputPin, OutputSignal},
@ -352,12 +352,12 @@ where
data: &'t TXBUF,
) -> Result<DmaTransferTx<Self>, DmaError>
where
TXBUF: ReadBuffer<Word = P::Word>,
TXBUF: ReadBuffer,
{
let (ptr, len) = unsafe { data.read_buffer() };
self.setup_send(cmd.into(), dummy);
self.start_write_bytes_dma(ptr as _, len * size_of::<P::Word>())?;
self.start_write_bytes_dma(ptr as _, len)?;
self.start_send();
Ok(DmaTransferTx::new(self))

View File

@ -115,6 +115,17 @@
//! dropped. Then it's possible to reuse the pin/peripheral for a different
//! purpose.
//!
//! ## Don't use [core::mem::forget]
//!
//! In general drivers are _NOT_ safe to use with [core::mem::forget]
//!
//! You should never use [core::mem::forget] on any type defined in the HAL.
//!
//! Some types heavily rely on their [Drop] implementation to not leave the
//! hardware in undefined state and causing UB.
//!
//! You might want to consider using [`#[deny(clippy::mem_forget)`](https://rust-lang.github.io/rust-clippy/v0.0.212/index.html#mem_forget) in your project.
//!
//! [documentation]: https://docs.esp-rs.org/esp-hal
//! [examples]: https://github.com/esp-rs/esp-hal/tree/main/examples
//! [embedded-hal]: https://github.com/rust-embedded/embedded-hal/tree/master/embedded-hal

View File

@ -27,7 +27,6 @@
use core::marker::PhantomData;
use embedded_dma::{ReadBuffer, WriteBuffer};
use enumset::{EnumSet, EnumSetType};
use fugit::HertzU32;
use peripheral::PeripheralRef;
@ -48,8 +47,10 @@ use crate::{
DmaTransferRx,
DmaTransferTx,
ParlIoPeripheral,
ReadBuffer,
RxPrivate,
TxPrivate,
WriteBuffer,
},
gpio::{InputPin, OutputPin},
interrupt::InterruptHandler,
@ -1431,7 +1432,7 @@ where
words: &'t TXBUF,
) -> Result<DmaTransferTx<Self>, Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
let (ptr, len) = unsafe { words.read_buffer() };
@ -1527,7 +1528,7 @@ where
words: &'t mut RXBUF,
) -> Result<DmaTransferRx<Self>, Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
let (ptr, len) = unsafe { words.write_buffer() };

View File

@ -6,13 +6,6 @@
//! things, particularly traits, which are used in almost every single Rust
//! program.
pub use embedded_dma::{
ReadBuffer as _embedded_dma_ReadBuffer,
ReadTarget as _embedded_dma_ReadTarget,
Word as _embedded_dma_Word,
WriteBuffer as _embedded_dma_WriteBuffer,
WriteTarget as _embedded_dma_WriteTarget,
};
pub use fugit::{ExtU64 as _fugit_ExtU64, RateExtU32 as _fugit_RateExtU32};
pub use nb;

View File

@ -839,8 +839,6 @@ where
}
pub mod dma {
use embedded_dma::{ReadBuffer, WriteBuffer};
use super::*;
#[cfg(spi3)]
use crate::dma::Spi3Peripheral;
@ -859,9 +857,11 @@ pub mod dma {
DmaTransferTxOwned,
DmaTransferTxRx,
DmaTransferTxRxOwned,
ReadBuffer,
Spi2Peripheral,
SpiPeripheral,
TxPrivate,
WriteBuffer,
},
InterruptConfigurable,
Mode,
@ -1125,7 +1125,7 @@ pub mod dma {
words: &'t TXBUF,
) -> Result<DmaTransferTx<Self>, super::Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
self.dma_write_start(words)?;
Ok(DmaTransferTx::new(self))
@ -1142,7 +1142,7 @@ pub mod dma {
words: TXBUF,
) -> Result<DmaTransferTxOwned<Self, TXBUF>, super::Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
self.dma_write_start(&words)?;
Ok(DmaTransferTxOwned::new(self, words))
@ -1151,7 +1151,7 @@ pub mod dma {
#[cfg_attr(feature = "place-spi-driver-in-ram", ram)]
fn dma_write_start<'t, TXBUF>(&'t mut self, words: &'t TXBUF) -> Result<(), super::Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
let (ptr, len) = unsafe { words.read_buffer() };
@ -1180,7 +1180,7 @@ pub mod dma {
words: &'t mut RXBUF,
) -> Result<DmaTransferRx<Self>, super::Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
self.dma_read_start(words)?;
Ok(DmaTransferRx::new(self))
@ -1197,7 +1197,7 @@ pub mod dma {
mut words: RXBUF,
) -> Result<DmaTransferRxOwned<Self, RXBUF>, super::Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
self.dma_read_start(&mut words)?;
Ok(DmaTransferRxOwned::new(self, words))
@ -1206,7 +1206,7 @@ pub mod dma {
#[cfg_attr(feature = "place-spi-driver-in-ram", ram)]
fn dma_read_start<'t, RXBUF>(&'t mut self, words: &'t mut RXBUF) -> Result<(), super::Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
let (ptr, len) = unsafe { words.write_buffer() };
@ -1236,8 +1236,8 @@ pub mod dma {
read_buffer: &'t mut RXBUF,
) -> Result<DmaTransferTxRx<Self>, super::Error>
where
TXBUF: ReadBuffer<Word = u8>,
RXBUF: WriteBuffer<Word = u8>,
TXBUF: ReadBuffer,
RXBUF: WriteBuffer,
{
self.dma_transfer_start(words, read_buffer)?;
Ok(DmaTransferTxRx::new(self))
@ -1254,8 +1254,8 @@ pub mod dma {
mut read_buffer: RXBUF,
) -> Result<DmaTransferTxRxOwned<Self, TXBUF, RXBUF>, super::Error>
where
TXBUF: ReadBuffer<Word = u8>,
RXBUF: WriteBuffer<Word = u8>,
TXBUF: ReadBuffer,
RXBUF: WriteBuffer,
{
self.dma_transfer_start(&words, &mut read_buffer)?;
Ok(DmaTransferTxRxOwned::new(self, words, read_buffer))
@ -1267,8 +1267,8 @@ pub mod dma {
read_buffer: &'t mut RXBUF,
) -> Result<(), super::Error>
where
TXBUF: ReadBuffer<Word = u8>,
RXBUF: WriteBuffer<Word = u8>,
TXBUF: ReadBuffer,
RXBUF: WriteBuffer,
{
let (write_ptr, write_len) = unsafe { words.read_buffer() };
let (read_ptr, read_len) = unsafe { read_buffer.write_buffer() };
@ -1312,7 +1312,7 @@ pub mod dma {
buffer: &'t mut RXBUF,
) -> Result<DmaTransferRx<Self>, super::Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
let (ptr, len) = unsafe { buffer.write_buffer() };
@ -1391,7 +1391,7 @@ pub mod dma {
buffer: &'t TXBUF,
) -> Result<DmaTransferTx<Self>, super::Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
let (ptr, len) = unsafe { buffer.read_buffer() };

View File

@ -144,8 +144,6 @@ where
}
pub mod dma {
use embedded_dma::{ReadBuffer, WriteBuffer};
use super::*;
#[cfg(spi3)]
use crate::dma::Spi3Peripheral;
@ -161,10 +159,12 @@ pub mod dma {
DmaTransferRx,
DmaTransferTx,
DmaTransferTxRx,
ReadBuffer,
RxPrivate,
Spi2Peripheral,
SpiPeripheral,
TxPrivate,
WriteBuffer,
},
Mode,
};
@ -346,7 +346,7 @@ pub mod dma {
words: &'t TXBUF,
) -> Result<DmaTransferTx<Self>, Error>
where
TXBUF: ReadBuffer<Word = u8>,
TXBUF: ReadBuffer,
{
let (ptr, len) = unsafe { words.read_buffer() };
@ -372,7 +372,7 @@ pub mod dma {
words: &'t mut RXBUF,
) -> Result<DmaTransferRx<Self>, Error>
where
RXBUF: WriteBuffer<Word = u8>,
RXBUF: WriteBuffer,
{
let (ptr, len) = unsafe { words.write_buffer() };
@ -400,8 +400,8 @@ pub mod dma {
read_buffer: &'t mut RXBUF,
) -> Result<DmaTransferTxRx<Self>, Error>
where
TXBUF: ReadBuffer<Word = u8>,
RXBUF: WriteBuffer<Word = u8>,
TXBUF: ReadBuffer,
RXBUF: WriteBuffer,
{
let (write_ptr, write_len) = unsafe { words.read_buffer() };
let (read_ptr, read_len) = unsafe { read_buffer.write_buffer() };

View File

@ -193,7 +193,12 @@ mod tests {
let tx_buffer = {
// using `static`, not `static mut`, places the array in .rodata
static TX_BUFFER: [u8; DMA_BUFFER_SIZE] = [42u8; DMA_BUFFER_SIZE];
unsafe { &mut *(core::ptr::addr_of!(TX_BUFFER) as *mut u8) }
unsafe {
core::slice::from_raw_parts(
&mut *(core::ptr::addr_of!(TX_BUFFER) as *mut u8),
DMA_BUFFER_SIZE,
)
}
};
let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks)
@ -241,7 +246,12 @@ mod tests {
let rx_buffer = {
// using `static`, not `static mut`, places the array in .rodata
static RX_BUFFER: [u8; DMA_BUFFER_SIZE] = [42u8; DMA_BUFFER_SIZE];
unsafe { &mut *(core::ptr::addr_of!(RX_BUFFER) as *mut u8) }
unsafe {
core::slice::from_raw_parts_mut(
&mut *(core::ptr::addr_of!(RX_BUFFER) as *mut u8),
DMA_BUFFER_SIZE,
)
}
};
let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks)