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) - Use the peripheral ref pattern for `OneShotTimer` and `PeriodicTimer` (#1855)
- Allow DMA to/from psram for esp32s3 (#1827) - 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 ### 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-driver = { version = "0.1.0", optional = true }
embassy-usb-synopsys-otg = { 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-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-02 = { version = "0.2.7", optional = true, features = ["unproven"], package = "embedded-hal" }
embedded-hal = { version = "1.0.0", optional = true } embedded-hal = { version = "1.0.0", optional = true }
embedded-hal-async = { 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. /// CTR, CFB8, and CFB128.
#[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
pub mod dma { pub mod dma {
use embedded_dma::{ReadBuffer, WriteBuffer};
use crate::{ use crate::{
aes::{Key, Mode}, aes::{Key, Mode},
dma::{ dma::{
@ -235,8 +233,10 @@ pub mod dma {
DmaDescriptor, DmaDescriptor,
DmaPeripheral, DmaPeripheral,
DmaTransferTxRx, DmaTransferTxRx,
ReadBuffer,
RxPrivate, RxPrivate,
TxPrivate, TxPrivate,
WriteBuffer,
}, },
}; };
@ -409,8 +409,8 @@ pub mod dma {
) -> Result<DmaTransferTxRx<Self>, crate::dma::DmaError> ) -> Result<DmaTransferTxRx<Self>, crate::dma::DmaError>
where where
K: Into<Key>, K: Into<Key>,
TXBUF: ReadBuffer<Word = u8>, TXBUF: ReadBuffer,
RXBUF: WriteBuffer<Word = u8>, RXBUF: WriteBuffer,
{ {
let (write_ptr, write_len) = unsafe { words.read_buffer() }; let (write_ptr, write_len) = unsafe { words.read_buffer() };
let (read_ptr, read_len) = unsafe { read_buffer.write_buffer() }; let (read_ptr, read_len) = unsafe { read_buffer.write_buffer() };

View File

@ -638,8 +638,6 @@ impl<'d> Dma<'d> {
pub use m2m::*; pub use m2m::*;
mod m2m { mod m2m {
use embedded_dma::{ReadBuffer, WriteBuffer};
#[cfg(esp32s3)] #[cfg(esp32s3)]
use crate::dma::DmaExtMemBKSize; use crate::dma::DmaExtMemBKSize;
use crate::dma::{ use crate::dma::{
@ -653,8 +651,10 @@ mod m2m {
DmaError, DmaError,
DmaPeripheral, DmaPeripheral,
DmaTransferRx, DmaTransferRx,
ReadBuffer,
RxPrivate, RxPrivate,
TxPrivate, TxPrivate,
WriteBuffer,
}; };
/// DMA Memory to Memory pseudo-Peripheral /// DMA Memory to Memory pseudo-Peripheral
@ -751,8 +751,8 @@ mod m2m {
rx_buffer: &'t mut RXBUF, rx_buffer: &'t mut RXBUF,
) -> Result<DmaTransferRx<Self>, DmaError> ) -> Result<DmaTransferRx<Self>, DmaError>
where where
TXBUF: ReadBuffer<Word = u8>, TXBUF: ReadBuffer,
RXBUF: WriteBuffer<Word = u8>, RXBUF: WriteBuffer,
{ {
let (tx_ptr, tx_len) = unsafe { tx_buffer.read_buffer() }; let (tx_ptr, tx_len) = unsafe { tx_buffer.read_buffer() };
let (rx_ptr, rx_len) = unsafe { rx_buffer.write_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}; 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! { bitfield::bitfield! {
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -130,7 +259,6 @@ impl DmaDescriptor {
} }
} }
use embedded_dma::{ReadBuffer, WriteBuffer};
use enumset::{EnumSet, EnumSetType}; use enumset::{EnumSet, EnumSetType};
#[cfg(gdma)] #[cfg(gdma)]
@ -1741,6 +1869,10 @@ pub(crate) mod dma_private {
} }
/// DMA transaction for TX only transfers /// DMA transaction for TX only transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive] #[non_exhaustive]
#[must_use] #[must_use]
pub struct DmaTransferTx<'a, I> pub struct DmaTransferTx<'a, I>
@ -1785,6 +1917,10 @@ where
} }
/// DMA transaction for RX only transfers /// DMA transaction for RX only transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive] #[non_exhaustive]
#[must_use] #[must_use]
pub struct DmaTransferRx<'a, I> pub struct DmaTransferRx<'a, I>
@ -1829,6 +1965,10 @@ where
} }
/// DMA transaction for TX+RX transfers /// DMA transaction for TX+RX transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive] #[non_exhaustive]
#[must_use] #[must_use]
pub struct DmaTransferTxRx<'a, I> pub struct DmaTransferTxRx<'a, I>
@ -1874,12 +2014,16 @@ where
/// DMA transaction for TX transfers with moved-in/moved-out peripheral and /// DMA transaction for TX transfers with moved-in/moved-out peripheral and
/// buffer /// buffer
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive] #[non_exhaustive]
#[must_use] #[must_use]
pub struct DmaTransferTxOwned<I, T> pub struct DmaTransferTxOwned<I, T>
where where
I: dma_private::DmaSupportTx, I: dma_private::DmaSupportTx,
T: ReadBuffer<Word = u8>, T: ReadBuffer,
{ {
instance: I, instance: I,
tx_buffer: T, tx_buffer: T,
@ -1888,7 +2032,7 @@ where
impl<I, T> DmaTransferTxOwned<I, T> impl<I, T> DmaTransferTxOwned<I, T>
where where
I: dma_private::DmaSupportTx, I: dma_private::DmaSupportTx,
T: ReadBuffer<Word = u8>, T: ReadBuffer,
{ {
pub(crate) fn new(instance: I, tx_buffer: T) -> Self { pub(crate) fn new(instance: I, tx_buffer: T) -> Self {
Self { Self {
@ -1936,7 +2080,7 @@ where
impl<I, T> Drop for DmaTransferTxOwned<I, T> impl<I, T> Drop for DmaTransferTxOwned<I, T>
where where
I: dma_private::DmaSupportTx, I: dma_private::DmaSupportTx,
T: ReadBuffer<Word = u8>, T: ReadBuffer,
{ {
fn drop(&mut self) { fn drop(&mut self) {
self.instance.peripheral_wait_dma(true, false); self.instance.peripheral_wait_dma(true, false);
@ -1945,12 +2089,16 @@ where
/// DMA transaction for RX transfers with moved-in/moved-out peripheral and /// DMA transaction for RX transfers with moved-in/moved-out peripheral and
/// buffer /// buffer
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive] #[non_exhaustive]
#[must_use] #[must_use]
pub struct DmaTransferRxOwned<I, R> pub struct DmaTransferRxOwned<I, R>
where where
I: dma_private::DmaSupportRx, I: dma_private::DmaSupportRx,
R: WriteBuffer<Word = u8>, R: WriteBuffer,
{ {
instance: I, instance: I,
rx_buffer: R, rx_buffer: R,
@ -1959,7 +2107,7 @@ where
impl<I, R> DmaTransferRxOwned<I, R> impl<I, R> DmaTransferRxOwned<I, R>
where where
I: dma_private::DmaSupportRx, I: dma_private::DmaSupportRx,
R: WriteBuffer<Word = u8>, R: WriteBuffer,
{ {
pub(crate) fn new(instance: I, rx_buffer: R) -> Self { pub(crate) fn new(instance: I, rx_buffer: R) -> Self {
Self { Self {
@ -2007,7 +2155,7 @@ where
impl<I, R> Drop for DmaTransferRxOwned<I, R> impl<I, R> Drop for DmaTransferRxOwned<I, R>
where where
I: dma_private::DmaSupportRx, I: dma_private::DmaSupportRx,
R: WriteBuffer<Word = u8>, R: WriteBuffer,
{ {
fn drop(&mut self) { fn drop(&mut self) {
self.instance.peripheral_wait_dma(false, true); 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 /// DMA transaction for TX+RX transfers with moved-in/moved-out peripheral and
/// buffers /// buffers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive] #[non_exhaustive]
#[must_use] #[must_use]
pub struct DmaTransferTxRxOwned<I, T, R> pub struct DmaTransferTxRxOwned<I, T, R>
where where
I: dma_private::DmaSupportTx + dma_private::DmaSupportRx, I: dma_private::DmaSupportTx + dma_private::DmaSupportRx,
T: ReadBuffer<Word = u8>, T: ReadBuffer,
R: WriteBuffer<Word = u8>, R: WriteBuffer,
{ {
instance: I, instance: I,
tx_buffer: T, tx_buffer: T,
@ -2032,8 +2184,8 @@ where
impl<I, T, R> DmaTransferTxRxOwned<I, T, R> impl<I, T, R> DmaTransferTxRxOwned<I, T, R>
where where
I: dma_private::DmaSupportTx + dma_private::DmaSupportRx, I: dma_private::DmaSupportTx + dma_private::DmaSupportRx,
T: ReadBuffer<Word = u8>, T: ReadBuffer,
R: WriteBuffer<Word = u8>, R: WriteBuffer,
{ {
pub(crate) fn new(instance: I, tx_buffer: T, rx_buffer: R) -> Self { pub(crate) fn new(instance: I, tx_buffer: T, rx_buffer: R) -> Self {
Self { Self {
@ -2084,8 +2236,8 @@ where
impl<I, T, R> Drop for DmaTransferTxRxOwned<I, T, R> impl<I, T, R> Drop for DmaTransferTxRxOwned<I, T, R>
where where
I: dma_private::DmaSupportTx + dma_private::DmaSupportRx, I: dma_private::DmaSupportTx + dma_private::DmaSupportRx,
T: ReadBuffer<Word = u8>, T: ReadBuffer,
R: WriteBuffer<Word = u8>, R: WriteBuffer,
{ {
fn drop(&mut self) { fn drop(&mut self) {
self.instance.peripheral_wait_dma(true, true); self.instance.peripheral_wait_dma(true, true);
@ -2093,6 +2245,10 @@ where
} }
/// DMA transaction for TX only circular transfers /// DMA transaction for TX only circular transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive] #[non_exhaustive]
#[must_use] #[must_use]
pub struct DmaTransferTxCircular<'a, I> pub struct DmaTransferTxCircular<'a, I>
@ -2157,6 +2313,10 @@ where
} }
/// DMA transaction for RX only circular transfers /// DMA transaction for RX only circular transfers
///
/// # Safety
///
/// Never use [core::mem::forget] on an in-progress transfer
#[non_exhaustive] #[non_exhaustive]
#[must_use] #[must_use]
pub struct DmaTransferRxCircular<'a, I> pub struct DmaTransferRxCircular<'a, I>

View File

@ -82,7 +82,6 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use embedded_dma::{ReadBuffer, WriteBuffer};
use enumset::{EnumSet, EnumSetType}; use enumset::{EnumSet, EnumSetType};
use private::*; use private::*;
@ -105,8 +104,10 @@ use crate::{
DmaTransferTxCircular, DmaTransferTxCircular,
I2s0Peripheral, I2s0Peripheral,
I2sPeripheral, I2sPeripheral,
ReadBuffer,
RxPrivate, RxPrivate,
TxPrivate, TxPrivate,
WriteBuffer,
}, },
gpio::OutputPin, gpio::OutputPin,
interrupt::InterruptHandler, interrupt::InterruptHandler,
@ -252,7 +253,7 @@ where
/// transfer /// transfer
fn write_dma<'t>(&'t mut self, words: &'t TXBUF) -> Result<DmaTransferTx<Self>, Error> fn write_dma<'t>(&'t mut self, words: &'t TXBUF) -> Result<DmaTransferTx<Self>, Error>
where where
TXBUF: ReadBuffer<Word = u8>; TXBUF: ReadBuffer;
/// Continuously write to I2S. Returns [DmaTransferTxCircular] which /// Continuously write to I2S. Returns [DmaTransferTxCircular] which
/// represents the in-progress DMA transfer /// represents the in-progress DMA transfer
@ -261,7 +262,7 @@ where
words: &'t TXBUF, words: &'t TXBUF,
) -> Result<DmaTransferTxCircular<Self>, Error> ) -> Result<DmaTransferTxCircular<Self>, Error>
where where
TXBUF: ReadBuffer<Word = u8>; TXBUF: ReadBuffer;
} }
/// Blocking I2S Read /// Blocking I2S Read
@ -282,7 +283,7 @@ where
/// transfer /// transfer
fn read_dma<'t>(&'t mut self, words: &'t mut RXBUF) -> Result<DmaTransferRx<Self>, Error> fn read_dma<'t>(&'t mut self, words: &'t mut RXBUF) -> Result<DmaTransferRx<Self>, Error>
where where
RXBUF: WriteBuffer<Word = u8>; RXBUF: WriteBuffer;
/// Continuously read from I2S. /// Continuously read from I2S.
/// Returns [DmaTransferRxCircular] which represents the in-progress DMA /// Returns [DmaTransferRxCircular] which represents the in-progress DMA
@ -292,7 +293,7 @@ where
words: &'t mut RXBUF, words: &'t mut RXBUF,
) -> Result<DmaTransferRxCircular<Self>, Error> ) -> Result<DmaTransferRxCircular<Self>, Error>
where where
RXBUF: WriteBuffer<Word = u8>; RXBUF: WriteBuffer;
} }
/// Instance of the I2S peripheral driver /// Instance of the I2S peripheral driver
@ -588,7 +589,7 @@ where
circular: bool, circular: bool,
) -> Result<(), Error> ) -> Result<(), Error>
where where
TXBUF: ReadBuffer<Word = u8>, TXBUF: ReadBuffer,
DmaMode: Mode, DmaMode: Mode,
{ {
let (ptr, len) = unsafe { words.read_buffer() }; 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> fn write_dma<'t>(&'t mut self, words: &'t TXBUF) -> Result<DmaTransferTx<Self>, Error>
where where
TXBUF: ReadBuffer<Word = u8>, TXBUF: ReadBuffer,
{ {
self.start_tx_transfer(words, false)?; self.start_tx_transfer(words, false)?;
Ok(DmaTransferTx::new(self)) Ok(DmaTransferTx::new(self))
@ -658,7 +659,7 @@ where
words: &'t TXBUF, words: &'t TXBUF,
) -> Result<DmaTransferTxCircular<Self>, Error> ) -> Result<DmaTransferTxCircular<Self>, Error>
where where
TXBUF: ReadBuffer<Word = u8>, TXBUF: ReadBuffer,
{ {
self.start_tx_transfer(words, true)?; self.start_tx_transfer(words, true)?;
Ok(DmaTransferTxCircular::new(self)) Ok(DmaTransferTxCircular::new(self))
@ -769,7 +770,7 @@ where
circular: bool, circular: bool,
) -> Result<(), Error> ) -> Result<(), Error>
where where
RXBUF: WriteBuffer<Word = u8>, RXBUF: WriteBuffer,
{ {
let (ptr, len) = unsafe { words.write_buffer() }; 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> fn read_dma<'t>(&'t mut self, words: &'t mut RXBUF) -> Result<DmaTransferRx<Self>, Error>
where where
RXBUF: WriteBuffer<Word = u8>, RXBUF: WriteBuffer,
{ {
self.start_rx_transfer(words, false)?; self.start_rx_transfer(words, false)?;
Ok(DmaTransferRx::new(self)) Ok(DmaTransferRx::new(self))
@ -839,7 +840,7 @@ where
words: &'t mut RXBUF, words: &'t mut RXBUF,
) -> Result<DmaTransferRxCircular<Self>, Error> ) -> Result<DmaTransferRxCircular<Self>, Error>
where where
RXBUF: WriteBuffer<Word = u8>, RXBUF: WriteBuffer,
{ {
self.start_rx_transfer(words, true)?; self.start_rx_transfer(words, true)?;
Ok(DmaTransferRxCircular::new(self)) Ok(DmaTransferRxCircular::new(self))
@ -2151,17 +2152,17 @@ mod private {
#[cfg(feature = "async")] #[cfg(feature = "async")]
pub mod asynch { pub mod asynch {
use embedded_dma::{ReadBuffer, WriteBuffer};
use super::{Error, I2sRx, I2sTx, RegisterAccess}; use super::{Error, I2sRx, I2sTx, RegisterAccess};
use crate::{ use crate::{
dma::{ dma::{
asynch::{DmaRxDoneChFuture, DmaRxFuture, DmaTxDoneChFuture, DmaTxFuture}, asynch::{DmaRxDoneChFuture, DmaRxFuture, DmaTxDoneChFuture, DmaTxFuture},
DmaChannel, DmaChannel,
ReadBuffer,
RxCircularState, RxCircularState,
RxPrivate, RxPrivate,
TxCircularState, TxCircularState,
TxPrivate, TxPrivate,
WriteBuffer,
}, },
Async, Async,
}; };
@ -2181,7 +2182,7 @@ pub mod asynch {
words: TXBUF, words: TXBUF,
) -> Result<I2sWriteDmaTransferAsync<'d, T, CH, TXBUF>, Error> ) -> Result<I2sWriteDmaTransferAsync<'d, T, CH, TXBUF>, Error>
where where
TXBUF: ReadBuffer<Word = u8>; TXBUF: ReadBuffer;
} }
impl<'d, T, CH> I2sWriteDmaAsync<'d, T, CH> for super::I2sTx<'d, T, CH, Async> impl<'d, T, CH> I2sWriteDmaAsync<'d, T, CH> for super::I2sTx<'d, T, CH, Async>
@ -2215,7 +2216,7 @@ pub mod asynch {
words: TXBUF, words: TXBUF,
) -> Result<I2sWriteDmaTransferAsync<'d, T, CH, TXBUF>, Error> ) -> Result<I2sWriteDmaTransferAsync<'d, T, CH, TXBUF>, Error>
where where
TXBUF: ReadBuffer<Word = u8>, TXBUF: ReadBuffer,
{ {
let (ptr, len) = unsafe { words.read_buffer() }; let (ptr, len) = unsafe { words.read_buffer() };
@ -2315,7 +2316,7 @@ pub mod asynch {
words: RXBUF, words: RXBUF,
) -> Result<I2sReadDmaTransferAsync<'d, T, CH, RXBUF>, Error> ) -> Result<I2sReadDmaTransferAsync<'d, T, CH, RXBUF>, Error>
where where
RXBUF: WriteBuffer<Word = u8>; RXBUF: WriteBuffer;
} }
impl<'d, T, CH> I2sReadDmaAsync<'d, T, CH> for super::I2sRx<'d, T, CH, Async> 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, mut words: RXBUF,
) -> Result<I2sReadDmaTransferAsync<'d, T, CH, RXBUF>, Error> ) -> Result<I2sReadDmaTransferAsync<'d, T, CH, RXBUF>, Error>
where where
RXBUF: WriteBuffer<Word = u8>, RXBUF: WriteBuffer,
{ {
let (ptr, len) = unsafe { words.write_buffer() }; 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 fugit::HertzU32;
use crate::{ use crate::{
@ -83,6 +80,7 @@ use crate::{
DmaTransferRxCircular, DmaTransferRxCircular,
LcdCamPeripheral, LcdCamPeripheral,
RxPrivate, RxPrivate,
WriteBuffer,
}, },
gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder}, lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder},
@ -380,11 +378,10 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
) -> Result<(), DmaError> { ) -> Result<(), DmaError> {
let (ptr, len) = unsafe { buf.write_buffer() }; let (ptr, len) = unsafe { buf.write_buffer() };
assert_eq!(self.bus_width, size_of::<RXBUF::Word>()); assert!(len % self.bus_width == 0);
unsafe { unsafe {
self.rx_chain self.rx_chain.fill_for_rx(circular, ptr as _, len)?;
.fill_for_rx(circular, ptr as _, len * size_of::<RXBUF::Word>())?;
self.rx_channel self.rx_channel
.prepare_transfer_without_start(DmaPeripheral::LcdCam, &self.rx_chain)?; .prepare_transfer_without_start(DmaPeripheral::LcdCam, &self.rx_chain)?;
} }

View File

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

View File

@ -115,6 +115,17 @@
//! dropped. Then it's possible to reuse the pin/peripheral for a different //! dropped. Then it's possible to reuse the pin/peripheral for a different
//! purpose. //! 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 //! [documentation]: https://docs.esp-rs.org/esp-hal
//! [examples]: https://github.com/esp-rs/esp-hal/tree/main/examples //! [examples]: https://github.com/esp-rs/esp-hal/tree/main/examples
//! [embedded-hal]: https://github.com/rust-embedded/embedded-hal/tree/master/embedded-hal //! [embedded-hal]: https://github.com/rust-embedded/embedded-hal/tree/master/embedded-hal

View File

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

View File

@ -6,13 +6,6 @@
//! things, particularly traits, which are used in almost every single Rust //! things, particularly traits, which are used in almost every single Rust
//! program. //! 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 fugit::{ExtU64 as _fugit_ExtU64, RateExtU32 as _fugit_RateExtU32};
pub use nb; pub use nb;

View File

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

View File

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

View File

@ -193,7 +193,12 @@ mod tests {
let tx_buffer = { let tx_buffer = {
// using `static`, not `static mut`, places the array in .rodata // using `static`, not `static mut`, places the array in .rodata
static TX_BUFFER: [u8; DMA_BUFFER_SIZE] = [42u8; DMA_BUFFER_SIZE]; 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) let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks)
@ -241,7 +246,12 @@ mod tests {
let rx_buffer = { let rx_buffer = {
// using `static`, not `static mut`, places the array in .rodata // using `static`, not `static mut`, places the array in .rodata
static RX_BUFFER: [u8; DMA_BUFFER_SIZE] = [42u8; DMA_BUFFER_SIZE]; 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) let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks)