Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions esp-hal/src/aes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ pub mod dma {
Channel,
ChannelRx,
ChannelTx,
CompatibleWith,
DescriptorChain,
DmaChannelConvert,
DmaChannelFor,
DmaDescriptor,
DmaPeripheral,
Expand Down Expand Up @@ -295,7 +295,7 @@ pub mod dma {
tx_descriptors: &'static mut [DmaDescriptor],
) -> AesDma<'d>
where
CH: DmaChannelConvert<DmaChannelFor<AES>>,
CH: CompatibleWith<AES>,
{
let channel = Channel::new(channel.map(|ch| ch.degrade()));
channel.runtime_ensure_compatible(&self.aes);
Expand Down
12 changes: 12 additions & 0 deletions esp-hal/src/dma/gdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ impl Peripheral for AnyGdmaRxChannel {
}
}

impl DmaChannelConvert<AnyGdmaRxChannel> for AnyGdmaRxChannel {
fn degrade(self) -> AnyGdmaRxChannel {
self
}
}

/// An arbitrary GDMA TX channel
pub struct AnyGdmaTxChannel(u8);

Expand All @@ -71,6 +77,12 @@ impl Peripheral for AnyGdmaTxChannel {
}
}

impl DmaChannelConvert<AnyGdmaTxChannel> for AnyGdmaTxChannel {
fn degrade(self) -> AnyGdmaTxChannel {
self
}
}

use embassy_sync::waitqueue::AtomicWaker;

static TX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];
Expand Down
65 changes: 64 additions & 1 deletion esp-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1647,7 +1647,7 @@ pub trait DmaChannelExt: DmaChannel {
note = "Not all channels are useable with all peripherals"
)]
#[doc(hidden)]
pub trait DmaChannelConvert<DEG>: DmaChannel {
pub trait DmaChannelConvert<DEG> {
fn degrade(self) -> DEG;
}

Expand All @@ -1657,6 +1657,69 @@ impl<DEG: DmaChannel> DmaChannelConvert<DEG> for DEG {
}
}

/// Trait implemented for DMA channels that are compatible with a particular
/// peripheral.
#[cfg_attr(pdma, doc = "")]
#[cfg_attr(
pdma,
doc = "Note that using mismatching channels (e.g. trying to use `spi2channel` with SPI3) may compile, but will panic in runtime."
)]
#[cfg_attr(pdma, doc = "")]
/// ## Example
///
/// The following example demonstrates how this trait can be used to only accept
/// types compatible with a specific peripheral.
///
/// ```rust,no_run
#[doc = crate::before_snippet!()]
/// use esp_hal::spi::master::{Spi, Config, Instance as SpiInstance};
/// use esp_hal::dma::CompatibleWith;
/// use esp_hal::Blocking;
/// use esp_hal::dma::Dma;
///
/// fn takes_spi<S: SpiInstance>(spi: Spi<'_, Blocking, S>, channel: impl
/// CompatibleWith<S>) {}
///
/// let dma = Dma::new(peripherals.DMA);
#[cfg_attr(pdma, doc = "let dma_channel = dma.spi2channel;")]
#[cfg_attr(gdma, doc = "let dma_channel = dma.channel0;")]
#[doc = ""]
/// let spi = Spi::new_with_config(
/// peripherals.SPI2,
/// Config::default(),
/// );
///
/// takes_spi(spi, dma_channel);
/// # }
/// ```
pub trait CompatibleWith<P: DmaEligible>: DmaChannel + DmaChannelConvert<DmaChannelFor<P>> {}
impl<P, CH> CompatibleWith<P> for CH
where
P: DmaEligible,
CH: DmaChannel + DmaChannelConvert<DmaChannelFor<P>>,
{
}

/// Trait implemented for the RX half of split DMA channels that are compatible
/// with a particular peripheral.
pub trait RxCompatibleWith<P: DmaEligible>: DmaChannelConvert<RxChannelFor<P>> {}
impl<P, RX> RxCompatibleWith<P> for RX
where
P: DmaEligible,
RX: DmaChannelConvert<RxChannelFor<P>>,
{
}

/// Trait implemented for the TX half of split DMA channels that are compatible
/// with a particular peripheral.
pub trait TxCompatibleWith<PER: DmaEligible>: DmaChannelConvert<TxChannelFor<PER>> {}
impl<P, TX> TxCompatibleWith<P> for TX
where
P: DmaEligible,
TX: DmaChannelConvert<TxChannelFor<P>>,
{
}

/// The functions here are not meant to be used outside the HAL
#[doc(hidden)]
pub trait Rx: crate::private::Sealed {
Expand Down
6 changes: 3 additions & 3 deletions esp-hal/src/i2s/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ use crate::{
Channel,
ChannelRx,
ChannelTx,
CompatibleWith,
DescriptorChain,
DmaChannelConvert,
DmaChannelFor,
DmaDescriptor,
DmaEligible,
Expand Down Expand Up @@ -377,7 +377,7 @@ impl<'d> I2s<'d, Blocking> {
tx_descriptors: &'static mut [DmaDescriptor],
) -> Self
where
CH: DmaChannelConvert<DmaChannelFor<AnyI2s>>,
CH: CompatibleWith<AnyI2s>,
{
Self::new_typed(
i2s.map_into(),
Expand Down Expand Up @@ -408,7 +408,7 @@ where
tx_descriptors: &'static mut [DmaDescriptor],
) -> Self
where
CH: DmaChannelConvert<DmaChannelFor<T>>,
CH: CompatibleWith<T>,
{
crate::into_ref!(i2s);
Self::new_internal(
Expand Down
7 changes: 3 additions & 4 deletions esp-hal/src/i2s/parallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ use crate::{
asynch::DmaTxFuture,
Channel,
ChannelTx,
DmaChannelConvert,
DmaChannelFor,
CompatibleWith,
DmaEligible,
DmaError,
DmaPeripheral,
Expand Down Expand Up @@ -193,7 +192,7 @@ impl<'d> I2sParallel<'d, Blocking> {
clock_pin: impl Peripheral<P = impl PeripheralOutput> + 'd,
) -> Self
where
CH: DmaChannelConvert<DmaChannelFor<AnyI2s>>,
CH: CompatibleWith<AnyI2s>,
{
Self::new_typed(i2s.map_into(), channel, frequency, pins, clock_pin)
}
Expand All @@ -212,7 +211,7 @@ where
clock_pin: impl Peripheral<P = impl PeripheralOutput> + 'd,
) -> Self
where
CH: DmaChannelConvert<DmaChannelFor<I>>,
CH: CompatibleWith<I>,
{
crate::into_ref!(i2s);
crate::into_mapped_ref!(clock_pin);
Expand Down
4 changes: 2 additions & 2 deletions esp-hal/src/lcd_cam/cam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use fugit::HertzU32;

use crate::{
clock::Clocks,
dma::{ChannelRx, DmaChannelConvert, DmaError, DmaPeripheral, DmaRxBuffer, Rx, RxChannelFor},
dma::{ChannelRx, DmaError, DmaPeripheral, DmaRxBuffer, Rx, RxChannelFor, RxCompatibleWith},
gpio::{
interconnect::{PeripheralInput, PeripheralOutput},
InputSignal,
Expand Down Expand Up @@ -136,7 +136,7 @@ impl<'d> Camera<'d> {
frequency: HertzU32,
) -> Self
where
CH: DmaChannelConvert<RxChannelFor<LCD_CAM>>,
CH: RxCompatibleWith<LCD_CAM>,
P: RxPins,
{
let rx_channel = ChannelRx::new(channel.map(|ch| ch.degrade()));
Expand Down
4 changes: 2 additions & 2 deletions esp-hal/src/lcd_cam/lcd/dpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ use fugit::HertzU32;

use crate::{
clock::Clocks,
dma::{ChannelTx, DmaChannelConvert, DmaError, DmaPeripheral, DmaTxBuffer, Tx, TxChannelFor},
dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, Tx, TxChannelFor, TxCompatibleWith},
gpio::{interconnect::PeripheralOutput, Level, OutputSignal},
lcd_cam::{
calculate_clkm,
Expand Down Expand Up @@ -139,7 +139,7 @@ where
config: Config,
) -> Self
where
CH: DmaChannelConvert<TxChannelFor<LCD_CAM>>,
CH: TxCompatibleWith<LCD_CAM>,
{
let tx_channel = ChannelTx::new(channel.map(|ch| ch.degrade()));
let lcd_cam = lcd.lcd_cam;
Expand Down
4 changes: 2 additions & 2 deletions esp-hal/src/lcd_cam/lcd/i8080.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ use fugit::HertzU32;

use crate::{
clock::Clocks,
dma::{ChannelTx, DmaChannelConvert, DmaError, DmaPeripheral, DmaTxBuffer, Tx, TxChannelFor},
dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, Tx, TxChannelFor, TxCompatibleWith},
gpio::{
interconnect::{OutputConnection, PeripheralOutput},
OutputSignal,
Expand Down Expand Up @@ -102,7 +102,7 @@ where
config: Config,
) -> Self
where
CH: DmaChannelConvert<TxChannelFor<LCD_CAM>>,
CH: TxCompatibleWith<LCD_CAM>,
P: TxPins,
{
let tx_channel = ChannelTx::new(channel.map(|ch| ch.degrade()));
Expand Down
11 changes: 6 additions & 5 deletions esp-hal/src/parl_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ use crate::{
Channel,
ChannelRx,
ChannelTx,
CompatibleWith,
DescriptorChain,
DmaChannelConvert,
DmaChannelFor,
DmaDescriptor,
DmaError,
DmaPeripheral,
Expand All @@ -45,8 +44,10 @@ use crate::{
ReadBuffer,
Rx,
RxChannelFor,
RxCompatibleWith,
Tx,
TxChannelFor,
TxCompatibleWith,
WriteBuffer,
},
gpio::{
Expand Down Expand Up @@ -1013,7 +1014,7 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> {
frequency: HertzU32,
) -> Result<Self, Error>
where
CH: DmaChannelConvert<DmaChannelFor<PARL_IO>>,
CH: CompatibleWith<PARL_IO>,
{
let tx_guard = GenericPeripheralGuard::new();
let rx_guard = GenericPeripheralGuard::new();
Expand Down Expand Up @@ -1135,7 +1136,7 @@ impl<'d> ParlIoTxOnly<'d, Blocking> {
frequency: HertzU32,
) -> Result<Self, Error>
where
CH: DmaChannelConvert<TxChannelFor<PARL_IO>>,
CH: TxCompatibleWith<PARL_IO>,
{
let guard = GenericPeripheralGuard::new();
let tx_channel = ChannelTx::new(dma_channel.map(|ch| ch.degrade()));
Expand Down Expand Up @@ -1241,7 +1242,7 @@ impl<'d> ParlIoRxOnly<'d, Blocking> {
frequency: HertzU32,
) -> Result<Self, Error>
where
CH: DmaChannelConvert<RxChannelFor<PARL_IO>>,
CH: RxCompatibleWith<PARL_IO>,
{
let guard = GenericPeripheralGuard::new();
let rx_channel = ChannelRx::new(dma_channel.map(|ch| ch.degrade()));
Expand Down
4 changes: 2 additions & 2 deletions esp-hal/src/spi/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ use procmacros::ram;
use super::{DmaError, Error, SpiBitOrder, SpiDataMode, SpiMode};
use crate::{
clock::Clocks,
dma::{DmaChannelConvert, DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer, Rx, Tx},
dma::{CompatibleWith, DmaEligible, DmaRxBuffer, DmaTxBuffer, Rx, Tx},
gpio::{interconnect::PeripheralOutput, InputSignal, NoPin, OutputSignal},
interrupt::InterruptHandler,
peripheral::{Peripheral, PeripheralRef},
Expand Down Expand Up @@ -540,7 +540,7 @@ where
/// operations.
pub fn with_dma<CH>(self, channel: impl Peripheral<P = CH> + 'd) -> SpiDma<'d, Blocking, T>
where
CH: DmaChannelConvert<DmaChannelFor<T>>,
CH: CompatibleWith<T>,
{
SpiDma::new(self.spi, channel.map(|ch| ch.degrade()).into_ref())
}
Expand Down
5 changes: 3 additions & 2 deletions esp-hal/src/spi/slave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ use core::marker::PhantomData;

use super::{Error, SpiMode};
use crate::{
dma::{DmaChannelConvert, DmaEligible},
dma::DmaEligible,
gpio::{
interconnect::{PeripheralInput, PeripheralOutput},
InputSignal,
Expand Down Expand Up @@ -176,6 +176,7 @@ pub mod dma {
Channel,
ChannelRx,
ChannelTx,
CompatibleWith,
DescriptorChain,
DmaChannelFor,
DmaDescriptor,
Expand Down Expand Up @@ -206,7 +207,7 @@ pub mod dma {
tx_descriptors: &'static mut [DmaDescriptor],
) -> SpiDma<'d, Blocking, T>
where
CH: DmaChannelConvert<DmaChannelFor<T>>,
CH: CompatibleWith<T>,
{
self.spi.info().set_data_mode(self.data_mode, true);
SpiDma::new(
Expand Down
6 changes: 2 additions & 4 deletions hil-test/tests/lcd_cam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#![no_main]

use esp_hal::{
dma::{Dma, DmaRxBuf, DmaTxBuf},
dma::{Dma, DmaChannel, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::Level,
lcd_cam::{
Expand Down Expand Up @@ -58,9 +58,7 @@ mod tests {
let dma = Dma::new(peripherals.DMA);
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);

// TODO: use split channels once supported
let tx_channel = dma.channel2;
let rx_channel = dma.channel3;
let (rx_channel, tx_channel) = dma.channel2.split();

let (vsync_in, vsync_out) = peripherals.GPIO6.split();
let (hsync_in, hsync_out) = peripherals.GPIO7.split();
Expand Down
Loading