mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-30 22:01:11 +00:00
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:
parent
45db1b55ec
commit
c6207c0f59
@ -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
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -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() };
|
||||
|
@ -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() };
|
||||
|
@ -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>
|
||||
|
@ -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() };
|
||||
|
||||
|
@ -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)?;
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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() };
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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() };
|
||||
|
||||
|
@ -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() };
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user