[DMA 1/N] Add mode to DMA channel drivers (#2519)
* Add mode to DMA channel drivers * Swap dma Channel CH and DM * Fix copy-paste mistake
This commit is contained in:
parent
959631ee55
commit
38dde2ebbd
@ -65,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- `I2c` SCL timeout is now defined in bus clock cycles. (#2477)
|
- `I2c` SCL timeout is now defined in bus clock cycles. (#2477)
|
||||||
- Trying to send a single-shot RMT transmission will result in an error now, `RMT` deals with `u32` now, `PulseCode` is a convenience trait now (#2463)
|
- Trying to send a single-shot RMT transmission will result in an error now, `RMT` deals with `u32` now, `PulseCode` is a convenience trait now (#2463)
|
||||||
- Removed `get_` prefixes from functions (#2528)
|
- Removed `get_` prefixes from functions (#2528)
|
||||||
|
- The `Camera` and `I8080` drivers' constructors now only accepts blocking-mode DMA channels. (#2519)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@ -180,6 +181,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- The DMA channel types have been removed from peripherals (#2261)
|
- The DMA channel types have been removed from peripherals (#2261)
|
||||||
- `I2C` driver renamed to `I2c` (#2320)
|
- `I2C` driver renamed to `I2c` (#2320)
|
||||||
- The GPIO pins are now accessible via `Peripherals` and are no longer part of the `Io` struct (#2508)
|
- The GPIO pins are now accessible via `Peripherals` and are no longer part of the `Io` struct (#2508)
|
||||||
|
- `dma::{ChannelRx, ChannelTx}` now have a `Mode` type parameter (#2519)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@ -276,7 +276,9 @@ For example:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Circular DMA transfer's `available` returns `Result<usize, DmaError>` now
|
## DMA related changes
|
||||||
|
|
||||||
|
### Circular DMA transfer's `available` returns `Result<usize, DmaError>` now
|
||||||
|
|
||||||
In case of any error you should drop the transfer and restart it.
|
In case of any error you should drop the transfer and restart it.
|
||||||
|
|
||||||
@ -293,6 +295,22 @@ In case of any error you should drop the transfer and restart it.
|
|||||||
+ };
|
+ };
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Channel, ChannelRx and ChannelTx types have changed
|
||||||
|
|
||||||
|
- `Channel`'s `Async`/`Blocking` mode has been moved before the channel instance parameter.
|
||||||
|
- `ChannelRx` and `ChannelTx` have gained a new `Async`/`Blocking` mode parameter.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
-Channel<'d, DmaChannel0, Async>
|
||||||
|
+Channel<'d, Async, DmaChannel0>
|
||||||
|
|
||||||
|
-ChannelRx<'d, DmaChannel0>
|
||||||
|
+ChannelRx<'d, Async, DmaChannel0>
|
||||||
|
|
||||||
|
-ChannelTx<'d, DmaChannel0>
|
||||||
|
+ChannelTx<'d, Async, DmaChannel0>
|
||||||
|
```
|
||||||
|
|
||||||
## Removed `peripheral_input` and `into_peripheral_output` from GPIO pin types
|
## Removed `peripheral_input` and `into_peripheral_output` from GPIO pin types
|
||||||
|
|
||||||
Creating peripheral interconnect signals now consume the GPIO pin used for the connection.
|
Creating peripheral interconnect signals now consume the GPIO pin used for the connection.
|
||||||
@ -357,7 +375,9 @@ refer to the `Config` struct as `uart::Config`.
|
|||||||
+)
|
+)
|
||||||
```
|
```
|
||||||
|
|
||||||
## I8080 driver split `set_byte_order()` into `set_8bits_order()` and `set_byte_order()`.
|
## LCD_CAM changes
|
||||||
|
|
||||||
|
### I8080 driver split `set_byte_order()` into `set_8bits_order()` and `set_byte_order()`.
|
||||||
|
|
||||||
If you were using an 8-bit bus.
|
If you were using an 8-bit bus.
|
||||||
|
|
||||||
@ -371,6 +391,29 @@ If you were using an 16-bit bus, you don't need to change anything, `set_byte_or
|
|||||||
If you were sharing the bus between an 8-bit and 16-bit device, you will have to call the corresponding method when
|
If you were sharing the bus between an 8-bit and 16-bit device, you will have to call the corresponding method when
|
||||||
you switch between devices. Be sure to read the documentation of the new methods.
|
you switch between devices. Be sure to read the documentation of the new methods.
|
||||||
|
|
||||||
|
### Mixed mode constructors
|
||||||
|
|
||||||
|
It is no longer possible to construct `I8080` or `Camera` with an async-mode DMA channel.
|
||||||
|
Convert the DMA channel into blocking before passing it to these constructors.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
||||||
|
let channel = ctx
|
||||||
|
.dma
|
||||||
|
.channel0
|
||||||
|
- .configure(false, DmaPriority::Priority0)
|
||||||
|
- .into_async();
|
||||||
|
+ .configure(false, DmaPriority::Priority0);
|
||||||
|
|
||||||
|
let i8080 = I8080::new(
|
||||||
|
lcd_cam.lcd,
|
||||||
|
channel.tx,
|
||||||
|
pins,
|
||||||
|
20.MHz(),
|
||||||
|
Config::default(),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
## `rmt::Channel::transmit` now returns `Result`, `PulseCode` is now `u32`
|
## `rmt::Channel::transmit` now returns `Result`, `PulseCode` is now `u32`
|
||||||
|
|
||||||
When trying to send a one-shot transmission will fail if it doesn't end with an end-marker.
|
When trying to send a one-shot transmission will fail if it doesn't end with an end-marker.
|
||||||
|
|||||||
@ -276,21 +276,21 @@ pub mod dma {
|
|||||||
/// The underlying [`Aes`](super::Aes) driver
|
/// The underlying [`Aes`](super::Aes) driver
|
||||||
pub aes: super::Aes<'d>,
|
pub aes: super::Aes<'d>,
|
||||||
|
|
||||||
channel: Channel<'d, <AES as DmaEligible>::Dma, Blocking>,
|
channel: Channel<'d, Blocking, <AES as DmaEligible>::Dma>,
|
||||||
rx_chain: DescriptorChain,
|
rx_chain: DescriptorChain,
|
||||||
tx_chain: DescriptorChain,
|
tx_chain: DescriptorChain,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> crate::aes::Aes<'d> {
|
impl<'d> crate::aes::Aes<'d> {
|
||||||
/// Enable DMA for the current instance of the AES driver
|
/// Enable DMA for the current instance of the AES driver
|
||||||
pub fn with_dma<C>(
|
pub fn with_dma<CH>(
|
||||||
self,
|
self,
|
||||||
channel: Channel<'d, C, Blocking>,
|
channel: Channel<'d, Blocking, CH>,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
) -> AesDma<'d>
|
) -> AesDma<'d>
|
||||||
where
|
where
|
||||||
C: DmaChannelConvert<<AES as DmaEligible>::Dma>,
|
CH: DmaChannelConvert<<AES as DmaEligible>::Dma>,
|
||||||
{
|
{
|
||||||
AesDma {
|
AesDma {
|
||||||
aes: self,
|
aes: self,
|
||||||
@ -324,7 +324,7 @@ pub mod dma {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> DmaSupportTx for AesDma<'d> {
|
impl<'d> DmaSupportTx for AesDma<'d> {
|
||||||
type TX = ChannelTx<'d, <AES as DmaEligible>::Dma>;
|
type TX = ChannelTx<'d, Blocking, <AES as DmaEligible>::Dma>;
|
||||||
|
|
||||||
fn tx(&mut self) -> &mut Self::TX {
|
fn tx(&mut self) -> &mut Self::TX {
|
||||||
&mut self.channel.tx
|
&mut self.channel.tx
|
||||||
@ -336,7 +336,7 @@ pub mod dma {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> DmaSupportRx for AesDma<'d> {
|
impl<'d> DmaSupportRx for AesDma<'d> {
|
||||||
type RX = ChannelRx<'d, <AES as DmaEligible>::Dma>;
|
type RX = ChannelRx<'d, Blocking, <AES as DmaEligible>::Dma>;
|
||||||
|
|
||||||
fn rx(&mut self) -> &mut Self::RX {
|
fn rx(&mut self) -> &mut Self::RX {
|
||||||
&mut self.channel.rx
|
&mut self.channel.rx
|
||||||
|
|||||||
@ -25,6 +25,66 @@ use crate::{
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub trait GdmaChannel {
|
pub trait GdmaChannel {
|
||||||
fn number(&self) -> u8;
|
fn number(&self) -> u8;
|
||||||
|
|
||||||
|
fn async_handler_out(&self) -> Option<InterruptHandler> {
|
||||||
|
match self.number() {
|
||||||
|
0 => DmaChannel0::handler_out(),
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
1 => DmaChannel1::handler_out(),
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
2 => DmaChannel2::handler_out(),
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
3 => DmaChannel3::handler_out(),
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
4 => DmaChannel4::handler_out(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peripheral_interrupt_out(&self) -> Option<Interrupt> {
|
||||||
|
match self.number() {
|
||||||
|
0 => DmaChannel0::isr_out(),
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
1 => DmaChannel1::isr_out(),
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
2 => DmaChannel2::isr_out(),
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
3 => DmaChannel3::isr_out(),
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
4 => DmaChannel4::isr_out(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_handler_in(&self) -> Option<InterruptHandler> {
|
||||||
|
match self.number() {
|
||||||
|
0 => DmaChannel0::handler_in(),
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
1 => DmaChannel1::handler_in(),
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
2 => DmaChannel2::handler_in(),
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
3 => DmaChannel3::handler_in(),
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
4 => DmaChannel4::handler_in(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peripheral_interrupt_in(&self) -> Option<Interrupt> {
|
||||||
|
match self.number() {
|
||||||
|
0 => DmaChannel0::isr_in(),
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
1 => DmaChannel1::isr_in(),
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
2 => DmaChannel2::isr_in(),
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
3 => DmaChannel3::isr_in(),
|
||||||
|
#[cfg(esp32s3)]
|
||||||
|
4 => DmaChannel4::isr_in(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An arbitrary GDMA channel
|
/// An arbitrary GDMA channel
|
||||||
@ -35,36 +95,6 @@ impl crate::private::Sealed for AnyGdmaChannel {}
|
|||||||
impl DmaChannel for AnyGdmaChannel {
|
impl DmaChannel for AnyGdmaChannel {
|
||||||
type Rx = ChannelRxImpl<Self>;
|
type Rx = ChannelRxImpl<Self>;
|
||||||
type Tx = ChannelTxImpl<Self>;
|
type Tx = ChannelTxImpl<Self>;
|
||||||
|
|
||||||
fn async_handler<M: Mode>(ch: &Channel<'_, Self, M>) -> InterruptHandler {
|
|
||||||
match ch.tx.tx_impl.0.number() {
|
|
||||||
0 => DmaChannel0::handler(),
|
|
||||||
#[cfg(not(esp32c2))]
|
|
||||||
1 => DmaChannel1::handler(),
|
|
||||||
#[cfg(not(esp32c2))]
|
|
||||||
2 => DmaChannel2::handler(),
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
3 => DmaChannel3::handler(),
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
4 => DmaChannel4::handler(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn interrupts<M: Mode>(ch: &Channel<'_, Self, M>) -> &'static [Interrupt] {
|
|
||||||
match ch.tx.tx_impl.0.number() {
|
|
||||||
0 => DmaChannel0::isrs(),
|
|
||||||
#[cfg(not(esp32c2))]
|
|
||||||
1 => DmaChannel1::isrs(),
|
|
||||||
#[cfg(not(esp32c2))]
|
|
||||||
2 => DmaChannel2::isrs(),
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
3 => DmaChannel3::isrs(),
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
4 => DmaChannel4::isrs(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@ -202,6 +232,14 @@ impl<C: GdmaChannel> TxRegisterAccess for ChannelTxImpl<C> {
|
|||||||
.out_eof_des_addr()
|
.out_eof_des_addr()
|
||||||
.bits() as _
|
.bits() as _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn async_handler(&self) -> Option<InterruptHandler> {
|
||||||
|
self.0.async_handler_out()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Option<Interrupt> {
|
||||||
|
self.0.peripheral_interrupt_out()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: GdmaChannel> InterruptAccess<DmaTxInterrupt> for ChannelTxImpl<C> {
|
impl<C: GdmaChannel> InterruptAccess<DmaTxInterrupt> for ChannelTxImpl<C> {
|
||||||
@ -385,6 +423,14 @@ impl<C: GdmaChannel> RxRegisterAccess for ChannelRxImpl<C> {
|
|||||||
.in_conf0()
|
.in_conf0()
|
||||||
.modify(|_, w| w.mem_trans_en().bit(value));
|
.modify(|_, w| w.mem_trans_en().bit(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn async_handler(&self) -> Option<InterruptHandler> {
|
||||||
|
self.0.async_handler_in()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Option<Interrupt> {
|
||||||
|
self.0.peripheral_interrupt_in()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: GdmaChannel> InterruptAccess<DmaRxInterrupt> for ChannelRxImpl<C> {
|
impl<C: GdmaChannel> InterruptAccess<DmaRxInterrupt> for ChannelRxImpl<C> {
|
||||||
@ -473,7 +519,7 @@ impl<C: GdmaChannel> InterruptAccess<DmaRxInterrupt> for ChannelRxImpl<C> {
|
|||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct ChannelCreator<const N: u8> {}
|
pub struct ChannelCreator<const N: u8> {}
|
||||||
|
|
||||||
impl<CH: DmaChannel, M: Mode> Channel<'_, CH, M> {
|
impl<CH: DmaChannel, M: Mode> Channel<'_, M, CH> {
|
||||||
/// Asserts that the channel is compatible with the given peripheral.
|
/// Asserts that the channel is compatible with the given peripheral.
|
||||||
pub fn runtime_ensure_compatible<P: DmaEligible>(&self, _peripheral: &PeripheralRef<'_, P>) {
|
pub fn runtime_ensure_compatible<P: DmaEligible>(&self, _peripheral: &PeripheralRef<'_, P>) {
|
||||||
// No runtime checks; GDMA channels are compatible with any peripheral
|
// No runtime checks; GDMA channels are compatible with any peripheral
|
||||||
@ -481,7 +527,7 @@ impl<CH: DmaChannel, M: Mode> Channel<'_, CH, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_channel {
|
macro_rules! impl_channel {
|
||||||
($num: literal, $async_handler: path, $($interrupt: ident),* ) => {
|
($num:literal, $interrupt_in:ident, $async_handler:path $(, $interrupt_out:ident , $async_handler_out:path)? ) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
/// A description of a specific GDMA channel
|
/// A description of a specific GDMA channel
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@ -490,26 +536,26 @@ macro_rules! impl_channel {
|
|||||||
impl crate::private::Sealed for [<DmaChannel $num>] {}
|
impl crate::private::Sealed for [<DmaChannel $num>] {}
|
||||||
|
|
||||||
impl [<DmaChannel $num>] {
|
impl [<DmaChannel $num>] {
|
||||||
fn handler() -> InterruptHandler {
|
fn handler_in() -> Option<InterruptHandler> {
|
||||||
$async_handler
|
Some($async_handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isrs() -> &'static [Interrupt] {
|
fn isr_in() -> Option<Interrupt> {
|
||||||
&[$(Interrupt::$interrupt),*]
|
Some(Interrupt::$interrupt_in)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handler_out() -> Option<InterruptHandler> {
|
||||||
|
$crate::if_set! { $(Some($async_handler_out))?, None }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn isr_out() -> Option<Interrupt> {
|
||||||
|
$crate::if_set! { $(Some(Interrupt::$interrupt_out))?, None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmaChannel for [<DmaChannel $num>] {
|
impl DmaChannel for [<DmaChannel $num>] {
|
||||||
type Rx = ChannelRxImpl<SpecificGdmaChannel<$num>>;
|
type Rx = ChannelRxImpl<SpecificGdmaChannel<$num>>;
|
||||||
type Tx = ChannelTxImpl<SpecificGdmaChannel<$num>>;
|
type Tx = ChannelTxImpl<SpecificGdmaChannel<$num>>;
|
||||||
|
|
||||||
fn async_handler<M: Mode>(_ch: &Channel<'_, Self, M>) -> InterruptHandler {
|
|
||||||
Self::handler()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn interrupts<M: Mode>(_ch: &Channel<'_, Self, M>,) -> &'static [Interrupt] {
|
|
||||||
Self::isrs()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmaChannelConvert<AnyGdmaChannel> for [<DmaChannel $num>] {
|
impl DmaChannelConvert<AnyGdmaChannel> for [<DmaChannel $num>] {
|
||||||
@ -537,11 +583,10 @@ macro_rules! impl_channel {
|
|||||||
self,
|
self,
|
||||||
burst_mode: bool,
|
burst_mode: bool,
|
||||||
priority: DmaPriority,
|
priority: DmaPriority,
|
||||||
) -> Channel<'a, [<DmaChannel $num>], Blocking> {
|
) -> Channel<'a, Blocking, [<DmaChannel $num>]> {
|
||||||
let mut this = Channel {
|
let mut this = Channel {
|
||||||
tx: ChannelTx::new(ChannelTxImpl(SpecificGdmaChannel::<$num> {})),
|
tx: ChannelTx::new(ChannelTxImpl(SpecificGdmaChannel::<$num> {})),
|
||||||
rx: ChannelRx::new(ChannelRxImpl(SpecificGdmaChannel::<$num> {})),
|
rx: ChannelRx::new(ChannelRxImpl(SpecificGdmaChannel::<$num> {})),
|
||||||
phantom: PhantomData,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.configure(burst_mode, priority);
|
this.configure(burst_mode, priority);
|
||||||
@ -553,27 +598,29 @@ macro_rules! impl_channel {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use super::asynch::interrupt as asynch_handler;
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(esp32c2)] {
|
if #[cfg(esp32c2)] {
|
||||||
const CHANNEL_COUNT: usize = 1;
|
const CHANNEL_COUNT: usize = 1;
|
||||||
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_CH0);
|
impl_channel!(0, DMA_CH0, asynch_handler::interrupt_handler_ch0);
|
||||||
} else if #[cfg(esp32c3)] {
|
} else if #[cfg(esp32c3)] {
|
||||||
const CHANNEL_COUNT: usize = 3;
|
const CHANNEL_COUNT: usize = 3;
|
||||||
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_CH0);
|
impl_channel!(0, DMA_CH0, asynch_handler::interrupt_handler_ch0);
|
||||||
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_CH1);
|
impl_channel!(1, DMA_CH1, asynch_handler::interrupt_handler_ch1);
|
||||||
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_CH2);
|
impl_channel!(2, DMA_CH2, asynch_handler::interrupt_handler_ch2);
|
||||||
} else if #[cfg(any(esp32c6, esp32h2))] {
|
} else if #[cfg(any(esp32c6, esp32h2))] {
|
||||||
const CHANNEL_COUNT: usize = 3;
|
const CHANNEL_COUNT: usize = 3;
|
||||||
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_IN_CH0, DMA_OUT_CH0);
|
impl_channel!(0, DMA_IN_CH0, asynch_handler::interrupt_handler_ch0, DMA_OUT_CH0, asynch_handler::interrupt_handler_ch0);
|
||||||
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_IN_CH1, DMA_OUT_CH1);
|
impl_channel!(1, DMA_IN_CH1, asynch_handler::interrupt_handler_ch1, DMA_OUT_CH1, asynch_handler::interrupt_handler_ch1);
|
||||||
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_IN_CH2, DMA_OUT_CH2);
|
impl_channel!(2, DMA_IN_CH2, asynch_handler::interrupt_handler_ch2, DMA_OUT_CH2, asynch_handler::interrupt_handler_ch2);
|
||||||
} else if #[cfg(esp32s3)] {
|
} else if #[cfg(esp32s3)] {
|
||||||
const CHANNEL_COUNT: usize = 5;
|
const CHANNEL_COUNT: usize = 5;
|
||||||
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_IN_CH0, DMA_OUT_CH0);
|
impl_channel!(0, DMA_IN_CH0, asynch_handler::interrupt_handler_ch0, DMA_OUT_CH0, asynch_handler::interrupt_handler_ch0);
|
||||||
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_IN_CH1, DMA_OUT_CH1);
|
impl_channel!(1, DMA_IN_CH1, asynch_handler::interrupt_handler_ch1, DMA_OUT_CH1, asynch_handler::interrupt_handler_ch1);
|
||||||
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_IN_CH2, DMA_OUT_CH2);
|
impl_channel!(2, DMA_IN_CH2, asynch_handler::interrupt_handler_ch2, DMA_OUT_CH2, asynch_handler::interrupt_handler_ch2);
|
||||||
impl_channel!(3, super::asynch::interrupt::interrupt_handler_ch3, DMA_IN_CH3, DMA_OUT_CH3);
|
impl_channel!(3, DMA_IN_CH3, asynch_handler::interrupt_handler_ch3, DMA_OUT_CH3, asynch_handler::interrupt_handler_ch3);
|
||||||
impl_channel!(4, super::asynch::interrupt::interrupt_handler_ch4, DMA_IN_CH4, DMA_OUT_CH4);
|
impl_channel!(4, DMA_IN_CH4, asynch_handler::interrupt_handler_ch4, DMA_OUT_CH4, asynch_handler::interrupt_handler_ch4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ pub struct Mem2Mem<'d, M>
|
|||||||
where
|
where
|
||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
channel: Channel<'d, AnyGdmaChannel, M>,
|
channel: Channel<'d, M, AnyGdmaChannel>,
|
||||||
rx_chain: DescriptorChain,
|
rx_chain: DescriptorChain,
|
||||||
tx_chain: DescriptorChain,
|
tx_chain: DescriptorChain,
|
||||||
peripheral: DmaPeripheral,
|
peripheral: DmaPeripheral,
|
||||||
@ -41,7 +41,7 @@ where
|
|||||||
impl<'d> Mem2Mem<'d, Blocking> {
|
impl<'d> Mem2Mem<'d, Blocking> {
|
||||||
/// Create a new Mem2Mem instance.
|
/// Create a new Mem2Mem instance.
|
||||||
pub fn new<CH, DM>(
|
pub fn new<CH, DM>(
|
||||||
channel: Channel<'d, CH, DM>,
|
channel: Channel<'d, DM, CH>,
|
||||||
peripheral: impl DmaEligible,
|
peripheral: impl DmaEligible,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
@ -49,7 +49,7 @@ impl<'d> Mem2Mem<'d, Blocking> {
|
|||||||
where
|
where
|
||||||
CH: DmaChannelConvert<AnyGdmaChannel>,
|
CH: DmaChannelConvert<AnyGdmaChannel>,
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
|
Channel<'d, Blocking, CH>: From<Channel<'d, DM, CH>>,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
Self::new_unsafe(
|
Self::new_unsafe(
|
||||||
@ -64,7 +64,7 @@ impl<'d> Mem2Mem<'d, Blocking> {
|
|||||||
|
|
||||||
/// Create a new Mem2Mem instance with specific chunk size.
|
/// Create a new Mem2Mem instance with specific chunk size.
|
||||||
pub fn new_with_chunk_size<CH, DM>(
|
pub fn new_with_chunk_size<CH, DM>(
|
||||||
channel: Channel<'d, CH, DM>,
|
channel: Channel<'d, DM, CH>,
|
||||||
peripheral: impl DmaEligible,
|
peripheral: impl DmaEligible,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
@ -73,7 +73,7 @@ impl<'d> Mem2Mem<'d, Blocking> {
|
|||||||
where
|
where
|
||||||
CH: DmaChannelConvert<AnyGdmaChannel>,
|
CH: DmaChannelConvert<AnyGdmaChannel>,
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
|
Channel<'d, Blocking, CH>: From<Channel<'d, DM, CH>>,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
Self::new_unsafe(
|
Self::new_unsafe(
|
||||||
@ -93,7 +93,7 @@ impl<'d> Mem2Mem<'d, Blocking> {
|
|||||||
/// You must ensure that your not using DMA for the same peripheral and
|
/// You must ensure that your not using DMA for the same peripheral and
|
||||||
/// that your the only one using the DmaPeripheral.
|
/// that your the only one using the DmaPeripheral.
|
||||||
pub unsafe fn new_unsafe<CH, DM>(
|
pub unsafe fn new_unsafe<CH, DM>(
|
||||||
channel: Channel<'d, CH, DM>,
|
channel: Channel<'d, DM, CH>,
|
||||||
peripheral: DmaPeripheral,
|
peripheral: DmaPeripheral,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
@ -102,7 +102,7 @@ impl<'d> Mem2Mem<'d, Blocking> {
|
|||||||
where
|
where
|
||||||
CH: DmaChannelConvert<AnyGdmaChannel>,
|
CH: DmaChannelConvert<AnyGdmaChannel>,
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
|
Channel<'d, Blocking, CH>: From<Channel<'d, DM, CH>>,
|
||||||
{
|
{
|
||||||
if !(1..=4092).contains(&chunk_size) {
|
if !(1..=4092).contains(&chunk_size) {
|
||||||
return Err(DmaError::InvalidChunkSize);
|
return Err(DmaError::InvalidChunkSize);
|
||||||
@ -111,7 +111,7 @@ impl<'d> Mem2Mem<'d, Blocking> {
|
|||||||
return Err(DmaError::OutOfDescriptors);
|
return Err(DmaError::OutOfDescriptors);
|
||||||
}
|
}
|
||||||
Ok(Mem2Mem {
|
Ok(Mem2Mem {
|
||||||
channel: Channel::<_, Blocking>::from(channel).degrade(),
|
channel: Channel::<Blocking, _>::from(channel).degrade(),
|
||||||
peripheral,
|
peripheral,
|
||||||
rx_chain: DescriptorChain::new_with_chunk_size(rx_descriptors, chunk_size),
|
rx_chain: DescriptorChain::new_with_chunk_size(rx_descriptors, chunk_size),
|
||||||
tx_chain: DescriptorChain::new_with_chunk_size(tx_descriptors, chunk_size),
|
tx_chain: DescriptorChain::new_with_chunk_size(tx_descriptors, chunk_size),
|
||||||
@ -190,11 +190,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, MODE> DmaSupportRx for Mem2Mem<'d, MODE>
|
impl<'d, M> DmaSupportRx for Mem2Mem<'d, M>
|
||||||
where
|
where
|
||||||
MODE: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
type RX = ChannelRx<'d, AnyGdmaChannel>;
|
type RX = ChannelRx<'d, M, AnyGdmaChannel>;
|
||||||
|
|
||||||
fn rx(&mut self) -> &mut Self::RX {
|
fn rx(&mut self) -> &mut Self::RX {
|
||||||
&mut self.channel.rx
|
&mut self.channel.rx
|
||||||
|
|||||||
@ -1571,12 +1571,6 @@ pub trait DmaChannel: crate::private::Sealed + Sized {
|
|||||||
|
|
||||||
/// A description of the TX half of a DMA Channel.
|
/// A description of the TX half of a DMA Channel.
|
||||||
type Tx: TxRegisterAccess + InterruptAccess<DmaTxInterrupt>;
|
type Tx: TxRegisterAccess + InterruptAccess<DmaTxInterrupt>;
|
||||||
|
|
||||||
/// Returns the async interrupt handler.
|
|
||||||
fn async_handler<M: Mode>(ch: &Channel<'_, Self, M>) -> InterruptHandler;
|
|
||||||
|
|
||||||
/// Returns the interrupt.
|
|
||||||
fn interrupts<M: Mode>(ch: &Channel<'_, Self, M>) -> &'static [Interrupt];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -1666,16 +1660,16 @@ pub trait Rx: crate::private::Sealed {
|
|||||||
// DMA receive channel
|
// DMA receive channel
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct ChannelRx<'a, CH>
|
pub struct ChannelRx<'a, M, CH>
|
||||||
where
|
where
|
||||||
CH: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
pub(crate) burst_mode: bool,
|
pub(crate) burst_mode: bool,
|
||||||
pub(crate) rx_impl: CH::Rx,
|
pub(crate) rx_impl: CH::Rx,
|
||||||
pub(crate) _phantom: PhantomData<(&'a (), CH)>,
|
pub(crate) _phantom: PhantomData<(&'a (), CH, M)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, CH> ChannelRx<'a, CH>
|
impl<'a, CH> ChannelRx<'a, Blocking, CH>
|
||||||
where
|
where
|
||||||
CH: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
@ -1692,9 +1686,60 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts a blocking channel to an async channel.
|
||||||
|
pub(crate) fn into_async(mut self) -> ChannelRx<'a, Async, CH> {
|
||||||
|
if let Some(handler) = self.rx_impl.async_handler() {
|
||||||
|
self.set_interrupt_handler(handler);
|
||||||
|
}
|
||||||
|
ChannelRx {
|
||||||
|
burst_mode: self.burst_mode,
|
||||||
|
rx_impl: self.rx_impl,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_interrupt_handler(&mut self, handler: InterruptHandler)
|
||||||
|
where
|
||||||
|
CH: DmaChannel,
|
||||||
|
{
|
||||||
|
self.unlisten_in(EnumSet::all());
|
||||||
|
self.clear_in(EnumSet::all());
|
||||||
|
|
||||||
|
if let Some(interrupt) = self.rx_impl.peripheral_interrupt() {
|
||||||
|
for core in crate::Cpu::other() {
|
||||||
|
crate::interrupt::disable(core, interrupt);
|
||||||
|
}
|
||||||
|
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
||||||
|
unwrap!(crate::interrupt::enable(interrupt, handler.priority()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, CH> ChannelRx<'a, Async, CH>
|
||||||
|
where
|
||||||
|
CH: DmaChannel,
|
||||||
|
{
|
||||||
|
/// Converts an async channel into a blocking channel.
|
||||||
|
pub(crate) fn into_blocking(self) -> ChannelRx<'a, Blocking, CH> {
|
||||||
|
if let Some(interrupt) = self.rx_impl.peripheral_interrupt() {
|
||||||
|
crate::interrupt::disable(Cpu::current(), interrupt);
|
||||||
|
}
|
||||||
|
ChannelRx {
|
||||||
|
burst_mode: self.burst_mode,
|
||||||
|
rx_impl: self.rx_impl,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, M, CH> ChannelRx<'a, M, CH>
|
||||||
|
where
|
||||||
|
M: Mode,
|
||||||
|
CH: DmaChannel,
|
||||||
|
{
|
||||||
/// Return a less specific (degraded) version of this channel.
|
/// Return a less specific (degraded) version of this channel.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn degrade<DEG: DmaChannel>(self) -> ChannelRx<'a, DEG>
|
pub fn degrade<DEG: DmaChannel>(self) -> ChannelRx<'a, M, DEG>
|
||||||
where
|
where
|
||||||
CH: DmaChannelConvert<DEG>,
|
CH: DmaChannelConvert<DEG>,
|
||||||
{
|
{
|
||||||
@ -1712,10 +1757,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CH> crate::private::Sealed for ChannelRx<'_, CH> where CH: DmaChannel {}
|
impl<M, CH> crate::private::Sealed for ChannelRx<'_, M, CH>
|
||||||
|
|
||||||
impl<CH> Rx for ChannelRx<'_, CH>
|
|
||||||
where
|
where
|
||||||
|
M: Mode,
|
||||||
|
CH: DmaChannel,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M, CH> Rx for ChannelRx<'_, M, CH>
|
||||||
|
where
|
||||||
|
M: Mode,
|
||||||
CH: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
unsafe fn prepare_transfer_without_start(
|
unsafe fn prepare_transfer_without_start(
|
||||||
@ -1894,17 +1945,17 @@ pub trait Tx: crate::private::Sealed {
|
|||||||
|
|
||||||
/// DMA transmit channel
|
/// DMA transmit channel
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct ChannelTx<'a, CH>
|
pub struct ChannelTx<'a, M, CH>
|
||||||
where
|
where
|
||||||
CH: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub(crate) burst_mode: bool,
|
pub(crate) burst_mode: bool,
|
||||||
pub(crate) tx_impl: CH::Tx,
|
pub(crate) tx_impl: CH::Tx,
|
||||||
pub(crate) _phantom: PhantomData<(&'a (), CH)>,
|
pub(crate) _phantom: PhantomData<(&'a (), CH, M)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, CH> ChannelTx<'a, CH>
|
impl<'a, CH> ChannelTx<'a, Blocking, CH>
|
||||||
where
|
where
|
||||||
CH: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
@ -1916,9 +1967,60 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts a blocking channel to an async channel.
|
||||||
|
pub(crate) fn into_async(mut self) -> ChannelTx<'a, Async, CH> {
|
||||||
|
if let Some(handler) = self.tx_impl.async_handler() {
|
||||||
|
self.set_interrupt_handler(handler);
|
||||||
|
}
|
||||||
|
ChannelTx {
|
||||||
|
burst_mode: self.burst_mode,
|
||||||
|
tx_impl: self.tx_impl,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_interrupt_handler(&mut self, handler: InterruptHandler)
|
||||||
|
where
|
||||||
|
CH: DmaChannel,
|
||||||
|
{
|
||||||
|
self.unlisten_out(EnumSet::all());
|
||||||
|
self.clear_out(EnumSet::all());
|
||||||
|
|
||||||
|
if let Some(interrupt) = self.tx_impl.peripheral_interrupt() {
|
||||||
|
for core in crate::Cpu::other() {
|
||||||
|
crate::interrupt::disable(core, interrupt);
|
||||||
|
}
|
||||||
|
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
||||||
|
unwrap!(crate::interrupt::enable(interrupt, handler.priority()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, CH> ChannelTx<'a, Async, CH>
|
||||||
|
where
|
||||||
|
CH: DmaChannel,
|
||||||
|
{
|
||||||
|
/// Converts an async channel into a blocking channel.
|
||||||
|
pub(crate) fn into_blocking(self) -> ChannelTx<'a, Blocking, CH> {
|
||||||
|
if let Some(interrupt) = self.tx_impl.peripheral_interrupt() {
|
||||||
|
crate::interrupt::disable(Cpu::current(), interrupt);
|
||||||
|
}
|
||||||
|
ChannelTx {
|
||||||
|
burst_mode: self.burst_mode,
|
||||||
|
tx_impl: self.tx_impl,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, M, CH> ChannelTx<'a, M, CH>
|
||||||
|
where
|
||||||
|
M: Mode,
|
||||||
|
CH: DmaChannel,
|
||||||
|
{
|
||||||
/// Return a less specific (degraded) version of this channel.
|
/// Return a less specific (degraded) version of this channel.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn degrade<DEG: DmaChannel>(self) -> ChannelTx<'a, DEG>
|
pub fn degrade<DEG: DmaChannel>(self) -> ChannelTx<'a, M, DEG>
|
||||||
where
|
where
|
||||||
CH: DmaChannelConvert<DEG>,
|
CH: DmaChannelConvert<DEG>,
|
||||||
{
|
{
|
||||||
@ -1936,10 +2038,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CH> crate::private::Sealed for ChannelTx<'_, CH> where CH: DmaChannel {}
|
impl<M, CH> crate::private::Sealed for ChannelTx<'_, M, CH>
|
||||||
|
|
||||||
impl<CH> Tx for ChannelTx<'_, CH>
|
|
||||||
where
|
where
|
||||||
|
M: Mode,
|
||||||
|
CH: DmaChannel,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M, CH> Tx for ChannelTx<'_, M, CH>
|
||||||
|
where
|
||||||
|
M: Mode,
|
||||||
CH: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
unsafe fn prepare_transfer_without_start(
|
unsafe fn prepare_transfer_without_start(
|
||||||
@ -2116,6 +2224,9 @@ pub trait RegisterAccess: crate::private::Sealed {
|
|||||||
pub trait RxRegisterAccess: RegisterAccess {
|
pub trait RxRegisterAccess: RegisterAccess {
|
||||||
#[cfg(gdma)]
|
#[cfg(gdma)]
|
||||||
fn set_mem2mem_mode(&self, value: bool);
|
fn set_mem2mem_mode(&self, value: bool);
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Option<Interrupt>;
|
||||||
|
fn async_handler(&self) -> Option<InterruptHandler>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -2125,6 +2236,9 @@ pub trait TxRegisterAccess: RegisterAccess {
|
|||||||
|
|
||||||
/// Outlink descriptor address when EOF occurs of Tx channel.
|
/// Outlink descriptor address when EOF occurs of Tx channel.
|
||||||
fn last_dscr_address(&self) -> usize;
|
fn last_dscr_address(&self) -> usize;
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Option<Interrupt>;
|
||||||
|
fn async_handler(&self) -> Option<InterruptHandler>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -2148,38 +2262,30 @@ pub trait InterruptAccess<T: EnumSetType>: crate::private::Sealed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// DMA Channel
|
/// DMA Channel
|
||||||
pub struct Channel<'d, CH, M>
|
pub struct Channel<'d, M, CH>
|
||||||
where
|
where
|
||||||
CH: DmaChannel,
|
|
||||||
M: Mode,
|
M: Mode,
|
||||||
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
/// RX half of the channel
|
/// RX half of the channel
|
||||||
pub rx: ChannelRx<'d, CH>,
|
pub rx: ChannelRx<'d, M, CH>,
|
||||||
/// TX half of the channel
|
/// TX half of the channel
|
||||||
pub tx: ChannelTx<'d, CH>,
|
pub tx: ChannelTx<'d, M, CH>,
|
||||||
pub(crate) phantom: PhantomData<M>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, C> Channel<'d, C, Blocking>
|
impl<'d, CH> Channel<'d, Blocking, CH>
|
||||||
where
|
where
|
||||||
C: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
/// Sets the interrupt handler for RX and TX interrupts.
|
/// Sets the interrupt handler for RX and TX interrupts.
|
||||||
///
|
///
|
||||||
/// Interrupts are not enabled at the peripheral level here.
|
/// Interrupts are not enabled at the peripheral level here.
|
||||||
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler)
|
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler)
|
||||||
where
|
where
|
||||||
C: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
self.unlisten(EnumSet::all());
|
self.rx.set_interrupt_handler(handler);
|
||||||
self.clear_interrupts(EnumSet::all());
|
self.tx.set_interrupt_handler(handler);
|
||||||
for interrupt in C::interrupts(self).iter().copied() {
|
|
||||||
for core in crate::Cpu::other() {
|
|
||||||
crate::interrupt::disable(core, interrupt);
|
|
||||||
}
|
|
||||||
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
|
||||||
unwrap!(crate::interrupt::enable(interrupt, handler.priority()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listen for the given interrupts
|
/// Listen for the given interrupts
|
||||||
@ -2226,67 +2332,59 @@ where
|
|||||||
|
|
||||||
/// Configure the channel.
|
/// Configure the channel.
|
||||||
pub fn configure(&mut self, burst_mode: bool, priority: DmaPriority) {
|
pub fn configure(&mut self, burst_mode: bool, priority: DmaPriority) {
|
||||||
self.tx.configure(burst_mode, priority);
|
|
||||||
self.rx.configure(burst_mode, priority);
|
self.rx.configure(burst_mode, priority);
|
||||||
|
self.tx.configure(burst_mode, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a blocking channel to an async channel.
|
/// Converts a blocking channel to an async channel.
|
||||||
pub fn into_async(mut self) -> Channel<'d, C, Async> {
|
pub fn into_async(self) -> Channel<'d, Async, CH> {
|
||||||
self.set_interrupt_handler(C::async_handler(&self));
|
|
||||||
|
|
||||||
Channel {
|
Channel {
|
||||||
tx: self.tx,
|
rx: self.rx.into_async(),
|
||||||
rx: self.rx,
|
tx: self.tx.into_async(),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, C> Channel<'d, C, Async>
|
impl<'d, CH> Channel<'d, Async, CH>
|
||||||
where
|
where
|
||||||
C: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
/// Converts an async channel to a blocking channel.
|
/// Converts an async channel to a blocking channel.
|
||||||
pub fn into_blocking(self) -> Channel<'d, C, Blocking> {
|
pub fn into_blocking(self) -> Channel<'d, Blocking, CH> {
|
||||||
for interrupt in C::interrupts(&self).iter().copied() {
|
|
||||||
crate::interrupt::disable(Cpu::current(), interrupt);
|
|
||||||
}
|
|
||||||
|
|
||||||
Channel {
|
Channel {
|
||||||
tx: self.tx,
|
rx: self.rx.into_blocking(),
|
||||||
rx: self.rx,
|
tx: self.tx.into_blocking(),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, C: DmaChannel> From<Channel<'d, C, Blocking>> for Channel<'d, C, Async> {
|
impl<'d, CH: DmaChannel> From<Channel<'d, Blocking, CH>> for Channel<'d, Async, CH> {
|
||||||
fn from(channel: Channel<'d, C, Blocking>) -> Self {
|
fn from(channel: Channel<'d, Blocking, CH>) -> Self {
|
||||||
channel.into_async()
|
channel.into_async()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, C: DmaChannel> From<Channel<'d, C, Async>> for Channel<'d, C, Blocking> {
|
impl<'d, CH: DmaChannel> From<Channel<'d, Async, CH>> for Channel<'d, Blocking, CH> {
|
||||||
fn from(channel: Channel<'d, C, Async>) -> Self {
|
fn from(channel: Channel<'d, Async, CH>) -> Self {
|
||||||
channel.into_blocking()
|
channel.into_blocking()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, CH, M: Mode> Channel<'d, CH, M>
|
impl<'d, M, CH> Channel<'d, M, CH>
|
||||||
where
|
where
|
||||||
|
M: Mode,
|
||||||
CH: DmaChannel,
|
CH: DmaChannel,
|
||||||
{
|
{
|
||||||
/// Return a less specific (degraded) version of this channel (both rx and
|
/// Return a less specific (degraded) version of this channel (both rx and
|
||||||
/// tx).
|
/// tx).
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn degrade<DEG: DmaChannel>(self) -> Channel<'d, DEG, M>
|
pub fn degrade<DEG: DmaChannel>(self) -> Channel<'d, M, DEG>
|
||||||
where
|
where
|
||||||
CH: DmaChannelConvert<DEG>,
|
CH: DmaChannelConvert<DEG>,
|
||||||
{
|
{
|
||||||
Channel {
|
Channel {
|
||||||
rx: self.rx.degrade(),
|
rx: self.rx.degrade(),
|
||||||
tx: self.tx.degrade(),
|
tx: self.tx.degrade(),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,9 @@ pub trait PdmaChannel: crate::private::Sealed {
|
|||||||
fn tx_waker(&self) -> &'static AtomicWaker;
|
fn tx_waker(&self) -> &'static AtomicWaker;
|
||||||
fn rx_waker(&self) -> &'static AtomicWaker;
|
fn rx_waker(&self) -> &'static AtomicWaker;
|
||||||
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
|
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Interrupt;
|
||||||
|
fn async_handler(&self) -> InterruptHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -107,6 +110,14 @@ impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> TxRegisterAccess for SpiD
|
|||||||
let spi = self.0.register_block();
|
let spi = self.0.register_block();
|
||||||
spi.out_eof_des_addr().read().dma_out_eof_des_addr().bits() as usize
|
spi.out_eof_des_addr().read().dma_out_eof_des_addr().bits() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Option<Interrupt> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_handler(&self) -> Option<InterruptHandler> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> InterruptAccess<DmaTxInterrupt>
|
impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> InterruptAccess<DmaTxInterrupt>
|
||||||
@ -241,7 +252,15 @@ impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> RegisterAccess for SpiDma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> RxRegisterAccess for SpiDmaRxChannelImpl<C> {}
|
impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> RxRegisterAccess for SpiDmaRxChannelImpl<C> {
|
||||||
|
fn peripheral_interrupt(&self) -> Option<Interrupt> {
|
||||||
|
Some(self.0.peripheral_interrupt())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_handler(&self) -> Option<InterruptHandler> {
|
||||||
|
Some(self.0.async_handler())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> InterruptAccess<DmaRxInterrupt>
|
impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> InterruptAccess<DmaRxInterrupt>
|
||||||
for SpiDmaRxChannelImpl<C>
|
for SpiDmaRxChannelImpl<C>
|
||||||
@ -343,27 +362,9 @@ macro_rules! ImplSpiChannel {
|
|||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct [<Spi $num DmaChannel>] {}
|
pub struct [<Spi $num DmaChannel>] {}
|
||||||
|
|
||||||
impl [<Spi $num DmaChannel>] {
|
|
||||||
fn handler() -> InterruptHandler {
|
|
||||||
super::asynch::interrupt::[< interrupt_handler_spi $num _dma >]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isrs() -> &'static [Interrupt] {
|
|
||||||
&[Interrupt::[< SPI $num _DMA >]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DmaChannel for [<Spi $num DmaChannel>] {
|
impl DmaChannel for [<Spi $num DmaChannel>] {
|
||||||
type Rx = SpiDmaRxChannelImpl<Self>;
|
type Rx = SpiDmaRxChannelImpl<Self>;
|
||||||
type Tx = SpiDmaTxChannelImpl<Self>;
|
type Tx = SpiDmaTxChannelImpl<Self>;
|
||||||
|
|
||||||
fn async_handler<M: Mode>(_ch: &Channel<'_, Self, M>) -> InterruptHandler {
|
|
||||||
Self::handler()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn interrupts<M: Mode>(_ch: &Channel<'_, Self, M>) -> &'static [Interrupt] {
|
|
||||||
Self::isrs()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmaChannelExt for [<Spi $num DmaChannel>] {
|
impl DmaChannelExt for [<Spi $num DmaChannel>] {
|
||||||
@ -393,6 +394,14 @@ macro_rules! ImplSpiChannel {
|
|||||||
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
|
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
|
||||||
peripheral == DmaPeripheral::[<Spi $num>]
|
peripheral == DmaPeripheral::[<Spi $num>]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Interrupt {
|
||||||
|
Interrupt::[< SPI $num _DMA >]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_handler(&self) -> InterruptHandler {
|
||||||
|
super::asynch::interrupt::[< interrupt_handler_spi $num _dma >]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmaChannelConvert<AnySpiDmaChannel> for [<Spi $num DmaChannel>] {
|
impl DmaChannelConvert<AnySpiDmaChannel> for [<Spi $num DmaChannel>] {
|
||||||
@ -416,11 +425,10 @@ macro_rules! ImplSpiChannel {
|
|||||||
self,
|
self,
|
||||||
burst_mode: bool,
|
burst_mode: bool,
|
||||||
priority: DmaPriority,
|
priority: DmaPriority,
|
||||||
) -> Channel<'a, [<Spi $num DmaChannel>], Blocking> {
|
) -> Channel<'a, Blocking, [<Spi $num DmaChannel>]> {
|
||||||
let mut this = Channel {
|
let mut this = Channel {
|
||||||
tx: ChannelTx::new(SpiDmaTxChannelImpl([<Spi $num DmaChannel>] {})),
|
tx: ChannelTx::new(SpiDmaTxChannelImpl([<Spi $num DmaChannel>] {})),
|
||||||
rx: ChannelRx::new(SpiDmaRxChannelImpl([<Spi $num DmaChannel>] {})),
|
rx: ChannelRx::new(SpiDmaRxChannelImpl([<Spi $num DmaChannel>] {})),
|
||||||
phantom: PhantomData,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.configure(burst_mode, priority);
|
this.configure(burst_mode, priority);
|
||||||
@ -518,6 +526,14 @@ impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> TxRegisterAccess for I2sD
|
|||||||
.out_eof_des_addr()
|
.out_eof_des_addr()
|
||||||
.bits() as usize
|
.bits() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Option<Interrupt> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_handler(&self) -> Option<InterruptHandler> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> InterruptAccess<DmaTxInterrupt>
|
impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> InterruptAccess<DmaTxInterrupt>
|
||||||
@ -658,7 +674,15 @@ impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> RegisterAccess for I2sDma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> RxRegisterAccess for I2sDmaRxChannelImpl<C> {}
|
impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> RxRegisterAccess for I2sDmaRxChannelImpl<C> {
|
||||||
|
fn peripheral_interrupt(&self) -> Option<Interrupt> {
|
||||||
|
Some(self.0.peripheral_interrupt())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_handler(&self) -> Option<InterruptHandler> {
|
||||||
|
Some(self.0.async_handler())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> InterruptAccess<DmaRxInterrupt>
|
impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> InterruptAccess<DmaRxInterrupt>
|
||||||
for I2sDmaRxChannelImpl<C>
|
for I2sDmaRxChannelImpl<C>
|
||||||
@ -756,27 +780,9 @@ macro_rules! ImplI2sChannel {
|
|||||||
|
|
||||||
impl $crate::private::Sealed for [<I2s $num DmaChannel>] {}
|
impl $crate::private::Sealed for [<I2s $num DmaChannel>] {}
|
||||||
|
|
||||||
impl [<I2s $num DmaChannel>] {
|
|
||||||
fn handler() -> InterruptHandler {
|
|
||||||
super::asynch::interrupt::[< interrupt_handler_i2s $num _dma >]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isrs() -> &'static [Interrupt] {
|
|
||||||
&[Interrupt::[< I2S $num >]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DmaChannel for [<I2s $num DmaChannel>] {
|
impl DmaChannel for [<I2s $num DmaChannel>] {
|
||||||
type Rx = I2sDmaRxChannelImpl<Self>;
|
type Rx = I2sDmaRxChannelImpl<Self>;
|
||||||
type Tx = I2sDmaTxChannelImpl<Self>;
|
type Tx = I2sDmaTxChannelImpl<Self>;
|
||||||
|
|
||||||
fn async_handler<M: Mode>(_ch: &Channel<'_, Self, M>) -> InterruptHandler {
|
|
||||||
Self::handler()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn interrupts<M: Mode>(_ch: &Channel<'_, Self, M>) -> &'static [Interrupt] {
|
|
||||||
Self::isrs()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmaChannelExt for [<I2s $num DmaChannel>] {
|
impl DmaChannelExt for [<I2s $num DmaChannel>] {
|
||||||
@ -805,6 +811,14 @@ macro_rules! ImplI2sChannel {
|
|||||||
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
|
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
|
||||||
peripheral == DmaPeripheral::[<I2s $num>]
|
peripheral == DmaPeripheral::[<I2s $num>]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn peripheral_interrupt(&self) -> Interrupt {
|
||||||
|
Interrupt::[< I2S $num >]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_handler(&self) -> InterruptHandler {
|
||||||
|
super::asynch::interrupt::[< interrupt_handler_i2s $num _dma >]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmaChannelConvert<AnyI2sDmaChannel> for [<I2s $num DmaChannel>] {
|
impl DmaChannelConvert<AnyI2sDmaChannel> for [<I2s $num DmaChannel>] {
|
||||||
@ -825,11 +839,10 @@ macro_rules! ImplI2sChannel {
|
|||||||
self,
|
self,
|
||||||
burst_mode: bool,
|
burst_mode: bool,
|
||||||
priority: DmaPriority,
|
priority: DmaPriority,
|
||||||
) -> Channel<'a, [<I2s $num DmaChannel>], Blocking> {
|
) -> Channel<'a, Blocking, [<I2s $num DmaChannel>]> {
|
||||||
let mut this = Channel {
|
let mut this = Channel {
|
||||||
tx: ChannelTx::new(I2sDmaTxChannelImpl([<I2s $num DmaChannel>] {})),
|
tx: ChannelTx::new(I2sDmaTxChannelImpl([<I2s $num DmaChannel>] {})),
|
||||||
rx: ChannelRx::new(I2sDmaRxChannelImpl([<I2s $num DmaChannel>] {})),
|
rx: ChannelRx::new(I2sDmaRxChannelImpl([<I2s $num DmaChannel>] {})),
|
||||||
phantom: PhantomData,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.configure(burst_mode, priority);
|
this.configure(burst_mode, priority);
|
||||||
@ -904,9 +917,10 @@ impl<'d> Dma<'d> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, C, M: Mode> Channel<'d, C, M>
|
impl<'d, CH, M> Channel<'d, M, CH>
|
||||||
where
|
where
|
||||||
C: DmaChannel,
|
CH: DmaChannel,
|
||||||
|
M: Mode,
|
||||||
{
|
{
|
||||||
/// Asserts that the channel is compatible with the given peripheral.
|
/// Asserts that the channel is compatible with the given peripheral.
|
||||||
pub fn runtime_ensure_compatible(&self, peripheral: &PeripheralRef<'_, impl DmaEligible>) {
|
pub fn runtime_ensure_compatible(&self, peripheral: &PeripheralRef<'_, impl DmaEligible>) {
|
||||||
@ -928,20 +942,6 @@ impl crate::private::Sealed for AnySpiDmaChannel {}
|
|||||||
impl DmaChannel for AnySpiDmaChannel {
|
impl DmaChannel for AnySpiDmaChannel {
|
||||||
type Rx = SpiDmaRxChannelImpl<AnySpiDmaChannelInner>;
|
type Rx = SpiDmaRxChannelImpl<AnySpiDmaChannelInner>;
|
||||||
type Tx = SpiDmaTxChannelImpl<AnySpiDmaChannelInner>;
|
type Tx = SpiDmaTxChannelImpl<AnySpiDmaChannelInner>;
|
||||||
|
|
||||||
fn async_handler<M: Mode>(ch: &Channel<'_, Self, M>) -> InterruptHandler {
|
|
||||||
match &ch.tx.tx_impl.0 {
|
|
||||||
AnySpiDmaChannelInner::Spi2(_) => Spi2DmaChannel::handler(),
|
|
||||||
AnySpiDmaChannelInner::Spi3(_) => Spi3DmaChannel::handler(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn interrupts<M: Mode>(ch: &Channel<'_, Self, M>) -> &'static [Interrupt] {
|
|
||||||
match &ch.tx.tx_impl.0 {
|
|
||||||
AnySpiDmaChannelInner::Spi2(_) => Spi2DmaChannel::isrs(),
|
|
||||||
AnySpiDmaChannelInner::Spi3(_) => Spi3DmaChannel::isrs(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::any_enum! {
|
crate::any_enum! {
|
||||||
@ -966,6 +966,8 @@ impl PdmaChannel for AnySpiDmaChannelInner {
|
|||||||
fn tx_waker(&self) -> &'static AtomicWaker;
|
fn tx_waker(&self) -> &'static AtomicWaker;
|
||||||
fn rx_waker(&self) -> &'static AtomicWaker;
|
fn rx_waker(&self) -> &'static AtomicWaker;
|
||||||
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
|
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
|
||||||
|
fn peripheral_interrupt(&self) -> Interrupt;
|
||||||
|
fn async_handler(&self) -> InterruptHandler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -978,22 +980,6 @@ impl crate::private::Sealed for AnyI2sDmaChannel {}
|
|||||||
impl DmaChannel for AnyI2sDmaChannel {
|
impl DmaChannel for AnyI2sDmaChannel {
|
||||||
type Rx = I2sDmaRxChannelImpl<AnyI2sDmaChannelInner>;
|
type Rx = I2sDmaRxChannelImpl<AnyI2sDmaChannelInner>;
|
||||||
type Tx = I2sDmaTxChannelImpl<AnyI2sDmaChannelInner>;
|
type Tx = I2sDmaTxChannelImpl<AnyI2sDmaChannelInner>;
|
||||||
|
|
||||||
fn async_handler<M: Mode>(ch: &Channel<'_, Self, M>) -> InterruptHandler {
|
|
||||||
match &ch.tx.tx_impl.0 {
|
|
||||||
AnyI2sDmaChannelInner::I2s0(_) => I2s0DmaChannel::handler(),
|
|
||||||
#[cfg(i2s1)]
|
|
||||||
AnyI2sDmaChannelInner::I2s1(_) => I2s1DmaChannel::handler(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn interrupts<M: Mode>(ch: &Channel<'_, Self, M>) -> &'static [Interrupt] {
|
|
||||||
match &ch.tx.tx_impl.0 {
|
|
||||||
AnyI2sDmaChannelInner::I2s0(_) => I2s0DmaChannel::isrs(),
|
|
||||||
#[cfg(i2s1)]
|
|
||||||
AnyI2sDmaChannelInner::I2s1(_) => I2s1DmaChannel::isrs(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::any_enum! {
|
crate::any_enum! {
|
||||||
@ -1020,6 +1006,8 @@ impl PdmaChannel for AnyI2sDmaChannelInner {
|
|||||||
fn tx_waker(&self) -> &'static AtomicWaker;
|
fn tx_waker(&self) -> &'static AtomicWaker;
|
||||||
fn rx_waker(&self) -> &'static AtomicWaker;
|
fn rx_waker(&self) -> &'static AtomicWaker;
|
||||||
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
|
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
|
||||||
|
fn peripheral_interrupt(&self) -> Interrupt;
|
||||||
|
fn async_handler(&self) -> InterruptHandler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,8 +74,6 @@
|
|||||||
//!
|
//!
|
||||||
//! - Only TDM Philips standard is supported.
|
//! - Only TDM Philips standard is supported.
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
|
||||||
|
|
||||||
use enumset::{EnumSet, EnumSetType};
|
use enumset::{EnumSet, EnumSetType};
|
||||||
use private::*;
|
use private::*;
|
||||||
|
|
||||||
@ -251,6 +249,7 @@ impl DataFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Instance of the I2S peripheral driver
|
/// Instance of the I2S peripheral driver
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct I2s<'d, M, T = AnyI2s>
|
pub struct I2s<'d, M, T = AnyI2s>
|
||||||
where
|
where
|
||||||
T: RegisterAccess,
|
T: RegisterAccess,
|
||||||
@ -260,7 +259,6 @@ where
|
|||||||
pub i2s_rx: RxCreator<'d, M, T>,
|
pub i2s_rx: RxCreator<'d, M, T>,
|
||||||
/// Handles the transmission (TX) side of the I2S peripheral.
|
/// Handles the transmission (TX) side of the I2S peripheral.
|
||||||
pub i2s_tx: TxCreator<'d, M, T>,
|
pub i2s_tx: TxCreator<'d, M, T>,
|
||||||
phantom: PhantomData<M>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, DmaMode, T> I2s<'d, DmaMode, T>
|
impl<'d, DmaMode, T> I2s<'d, DmaMode, T>
|
||||||
@ -274,7 +272,7 @@ where
|
|||||||
standard: Standard,
|
standard: Standard,
|
||||||
data_format: DataFormat,
|
data_format: DataFormat,
|
||||||
sample_rate: impl Into<fugit::HertzU32>,
|
sample_rate: impl Into<fugit::HertzU32>,
|
||||||
channel: Channel<'d, CH, DmaMode>,
|
channel: Channel<'d, DmaMode, CH>,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
) -> Self
|
) -> Self
|
||||||
@ -299,15 +297,12 @@ where
|
|||||||
i2s: unsafe { i2s.clone_unchecked() },
|
i2s: unsafe { i2s.clone_unchecked() },
|
||||||
rx_channel: channel.rx,
|
rx_channel: channel.rx,
|
||||||
descriptors: rx_descriptors,
|
descriptors: rx_descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
i2s_tx: TxCreator {
|
i2s_tx: TxCreator {
|
||||||
i2s,
|
i2s,
|
||||||
tx_channel: channel.tx,
|
tx_channel: channel.tx,
|
||||||
descriptors: tx_descriptors,
|
descriptors: tx_descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,14 +371,14 @@ impl<'d> I2s<'d, Blocking> {
|
|||||||
standard: Standard,
|
standard: Standard,
|
||||||
data_format: DataFormat,
|
data_format: DataFormat,
|
||||||
sample_rate: impl Into<fugit::HertzU32>,
|
sample_rate: impl Into<fugit::HertzU32>,
|
||||||
channel: Channel<'d, CH, DM>,
|
channel: Channel<'d, DM, CH>,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
CH: DmaChannelConvert<<AnyI2s as DmaEligible>::Dma>,
|
CH: DmaChannelConvert<<AnyI2s as DmaEligible>::Dma>,
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
|
Channel<'d, Blocking, CH>: From<Channel<'d, DM, CH>>,
|
||||||
{
|
{
|
||||||
Self::new_typed(
|
Self::new_typed(
|
||||||
i2s.map_into(),
|
i2s.map_into(),
|
||||||
@ -409,14 +404,14 @@ where
|
|||||||
standard: Standard,
|
standard: Standard,
|
||||||
data_format: DataFormat,
|
data_format: DataFormat,
|
||||||
sample_rate: impl Into<fugit::HertzU32>,
|
sample_rate: impl Into<fugit::HertzU32>,
|
||||||
channel: Channel<'d, CH, DM>,
|
channel: Channel<'d, DM, CH>,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
CH: DmaChannelConvert<T::Dma>,
|
CH: DmaChannelConvert<T::Dma>,
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
|
Channel<'d, Blocking, CH>: From<Channel<'d, DM, CH>>,
|
||||||
{
|
{
|
||||||
crate::into_ref!(i2s);
|
crate::into_ref!(i2s);
|
||||||
Self::new_internal(
|
Self::new_internal(
|
||||||
@ -432,26 +427,17 @@ where
|
|||||||
|
|
||||||
/// Converts the SPI instance into async mode.
|
/// Converts the SPI instance into async mode.
|
||||||
pub fn into_async(self) -> I2s<'d, Async, T> {
|
pub fn into_async(self) -> I2s<'d, Async, T> {
|
||||||
let channel = Channel {
|
|
||||||
rx: self.i2s_rx.rx_channel,
|
|
||||||
tx: self.i2s_tx.tx_channel,
|
|
||||||
phantom: PhantomData::<Blocking>,
|
|
||||||
};
|
|
||||||
let channel = channel.into_async();
|
|
||||||
I2s {
|
I2s {
|
||||||
i2s_rx: RxCreator {
|
i2s_rx: RxCreator {
|
||||||
i2s: self.i2s_rx.i2s,
|
i2s: self.i2s_rx.i2s,
|
||||||
rx_channel: channel.rx,
|
rx_channel: self.i2s_rx.rx_channel.into_async(),
|
||||||
descriptors: self.i2s_rx.descriptors,
|
descriptors: self.i2s_rx.descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
i2s_tx: TxCreator {
|
i2s_tx: TxCreator {
|
||||||
i2s: self.i2s_tx.i2s,
|
i2s: self.i2s_tx.i2s,
|
||||||
tx_channel: channel.tx,
|
tx_channel: self.i2s_tx.tx_channel.into_async(),
|
||||||
descriptors: self.i2s_tx.descriptors,
|
descriptors: self.i2s_tx.descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -477,9 +463,8 @@ where
|
|||||||
T: RegisterAccess,
|
T: RegisterAccess,
|
||||||
{
|
{
|
||||||
i2s: PeripheralRef<'d, T>,
|
i2s: PeripheralRef<'d, T>,
|
||||||
tx_channel: ChannelTx<'d, T::Dma>,
|
tx_channel: ChannelTx<'d, DmaMode, T::Dma>,
|
||||||
tx_chain: DescriptorChain,
|
tx_chain: DescriptorChain,
|
||||||
phantom: PhantomData<DmaMode>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DmaMode, T> core::fmt::Debug for I2sTx<'_, DmaMode, T>
|
impl<DmaMode, T> core::fmt::Debug for I2sTx<'_, DmaMode, T>
|
||||||
@ -511,7 +496,7 @@ where
|
|||||||
T: RegisterAccess,
|
T: RegisterAccess,
|
||||||
DmaMode: Mode,
|
DmaMode: Mode,
|
||||||
{
|
{
|
||||||
type TX = ChannelTx<'d, T::Dma>;
|
type TX = ChannelTx<'d, DmaMode, T::Dma>;
|
||||||
|
|
||||||
fn tx(&mut self) -> &mut Self::TX {
|
fn tx(&mut self) -> &mut Self::TX {
|
||||||
&mut self.tx_channel
|
&mut self.tx_channel
|
||||||
@ -610,9 +595,8 @@ where
|
|||||||
DmaMode: Mode,
|
DmaMode: Mode,
|
||||||
{
|
{
|
||||||
i2s: PeripheralRef<'d, T>,
|
i2s: PeripheralRef<'d, T>,
|
||||||
rx_channel: ChannelRx<'d, T::Dma>,
|
rx_channel: ChannelRx<'d, DmaMode, T::Dma>,
|
||||||
rx_chain: DescriptorChain,
|
rx_chain: DescriptorChain,
|
||||||
phantom: PhantomData<DmaMode>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DmaMode, T> core::fmt::Debug for I2sRx<'_, DmaMode, T>
|
impl<DmaMode, T> core::fmt::Debug for I2sRx<'_, DmaMode, T>
|
||||||
@ -644,7 +628,7 @@ where
|
|||||||
T: RegisterAccess,
|
T: RegisterAccess,
|
||||||
DmaMode: Mode,
|
DmaMode: Mode,
|
||||||
{
|
{
|
||||||
type RX = ChannelRx<'d, T::Dma>;
|
type RX = ChannelRx<'d, DmaMode, T::Dma>;
|
||||||
|
|
||||||
fn rx(&mut self) -> &mut Self::RX {
|
fn rx(&mut self) -> &mut Self::RX {
|
||||||
&mut self.rx_channel
|
&mut self.rx_channel
|
||||||
@ -750,8 +734,6 @@ pub trait RegisterAccess: RegisterAccessPrivate {}
|
|||||||
impl<T> RegisterAccess for T where T: RegisterAccessPrivate {}
|
impl<T> RegisterAccess for T where T: RegisterAccessPrivate {}
|
||||||
|
|
||||||
mod private {
|
mod private {
|
||||||
use core::marker::PhantomData;
|
|
||||||
|
|
||||||
use enumset::EnumSet;
|
use enumset::EnumSet;
|
||||||
use fugit::HertzU32;
|
use fugit::HertzU32;
|
||||||
|
|
||||||
@ -790,22 +772,20 @@ mod private {
|
|||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
pub i2s: PeripheralRef<'d, T>,
|
pub i2s: PeripheralRef<'d, T>,
|
||||||
pub tx_channel: ChannelTx<'d, T::Dma>,
|
pub tx_channel: ChannelTx<'d, M, T::Dma>,
|
||||||
pub descriptors: &'static mut [DmaDescriptor],
|
pub descriptors: &'static mut [DmaDescriptor],
|
||||||
pub(crate) phantom: PhantomData<M>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, DmaMode, T> TxCreator<'d, DmaMode, T>
|
impl<'d, M, T> TxCreator<'d, M, T>
|
||||||
where
|
where
|
||||||
|
M: Mode,
|
||||||
T: RegisterAccess,
|
T: RegisterAccess,
|
||||||
DmaMode: Mode,
|
|
||||||
{
|
{
|
||||||
pub fn build(self) -> I2sTx<'d, DmaMode, T> {
|
pub fn build(self) -> I2sTx<'d, M, T> {
|
||||||
I2sTx {
|
I2sTx {
|
||||||
i2s: self.i2s,
|
i2s: self.i2s,
|
||||||
tx_channel: self.tx_channel,
|
tx_channel: self.tx_channel,
|
||||||
tx_chain: DescriptorChain::new(self.descriptors),
|
tx_chain: DescriptorChain::new(self.descriptors),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,22 +829,20 @@ mod private {
|
|||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
pub i2s: PeripheralRef<'d, T>,
|
pub i2s: PeripheralRef<'d, T>,
|
||||||
pub rx_channel: ChannelRx<'d, T::Dma>,
|
pub rx_channel: ChannelRx<'d, M, T::Dma>,
|
||||||
pub descriptors: &'static mut [DmaDescriptor],
|
pub descriptors: &'static mut [DmaDescriptor],
|
||||||
pub(crate) phantom: PhantomData<M>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, M, T> RxCreator<'d, M, T>
|
impl<'d, M, T> RxCreator<'d, M, T>
|
||||||
where
|
where
|
||||||
T: RegisterAccess,
|
|
||||||
M: Mode,
|
M: Mode,
|
||||||
|
T: RegisterAccess,
|
||||||
{
|
{
|
||||||
pub fn build(self) -> I2sRx<'d, M, T> {
|
pub fn build(self) -> I2sRx<'d, M, T> {
|
||||||
I2sRx {
|
I2sRx {
|
||||||
i2s: self.i2s,
|
i2s: self.i2s,
|
||||||
rx_channel: self.rx_channel,
|
rx_channel: self.rx_channel,
|
||||||
rx_chain: DescriptorChain::new(self.descriptors),
|
rx_chain: DescriptorChain::new(self.descriptors),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,6 @@
|
|||||||
//! - `DMA`
|
//! - `DMA`
|
||||||
//! - `system` (to configure and enable the I2S peripheral)
|
//! - `system` (to configure and enable the I2S peripheral)
|
||||||
use core::{
|
use core::{
|
||||||
marker::PhantomData,
|
|
||||||
mem::ManuallyDrop,
|
mem::ManuallyDrop,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
@ -177,8 +176,7 @@ where
|
|||||||
I: Instance,
|
I: Instance,
|
||||||
{
|
{
|
||||||
instance: PeripheralRef<'d, I>,
|
instance: PeripheralRef<'d, I>,
|
||||||
tx_channel: ChannelTx<'d, I::Dma>,
|
tx_channel: ChannelTx<'d, DM, I::Dma>,
|
||||||
mode: PhantomData<DM>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, DM> I2sParallel<'d, DM>
|
impl<'d, DM> I2sParallel<'d, DM>
|
||||||
@ -188,7 +186,7 @@ where
|
|||||||
/// Create a new I2S Parallel Interface
|
/// Create a new I2S Parallel Interface
|
||||||
pub fn new<CH>(
|
pub fn new<CH>(
|
||||||
i2s: impl Peripheral<P = impl Instance> + 'd,
|
i2s: impl Peripheral<P = impl Instance> + 'd,
|
||||||
channel: Channel<'d, CH, DM>,
|
channel: Channel<'d, DM, CH>,
|
||||||
frequency: impl Into<fugit::HertzU32>,
|
frequency: impl Into<fugit::HertzU32>,
|
||||||
pins: impl TxPins<'d>,
|
pins: impl TxPins<'d>,
|
||||||
clock_pin: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
clock_pin: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
||||||
@ -208,7 +206,7 @@ where
|
|||||||
/// Create a new I2S Parallel Interface
|
/// Create a new I2S Parallel Interface
|
||||||
pub fn new_typed<CH>(
|
pub fn new_typed<CH>(
|
||||||
i2s: impl Peripheral<P = I> + 'd,
|
i2s: impl Peripheral<P = I> + 'd,
|
||||||
channel: Channel<'d, CH, DM>,
|
channel: Channel<'d, DM, CH>,
|
||||||
frequency: impl Into<fugit::HertzU32>,
|
frequency: impl Into<fugit::HertzU32>,
|
||||||
mut pins: impl TxPins<'d>,
|
mut pins: impl TxPins<'d>,
|
||||||
clock_pin: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
clock_pin: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
||||||
@ -234,7 +232,6 @@ where
|
|||||||
Self {
|
Self {
|
||||||
instance: i2s,
|
instance: i2s,
|
||||||
tx_channel: channel.tx,
|
tx_channel: channel.tx,
|
||||||
mode: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -82,6 +82,7 @@ use crate::{
|
|||||||
lcd_cam::{calculate_clkm, BitOrder, ByteOrder},
|
lcd_cam::{calculate_clkm, BitOrder, ByteOrder},
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::LCD_CAM,
|
peripherals::LCD_CAM,
|
||||||
|
Blocking,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Generation of GDMA SUC EOF
|
/// Generation of GDMA SUC EOF
|
||||||
@ -125,14 +126,14 @@ pub struct Cam<'d> {
|
|||||||
/// Represents the camera interface with DMA support.
|
/// Represents the camera interface with DMA support.
|
||||||
pub struct Camera<'d> {
|
pub struct Camera<'d> {
|
||||||
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
||||||
rx_channel: ChannelRx<'d, <LCD_CAM as DmaEligible>::Dma>,
|
rx_channel: ChannelRx<'d, Blocking, <LCD_CAM as DmaEligible>::Dma>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> Camera<'d> {
|
impl<'d> Camera<'d> {
|
||||||
/// Creates a new `Camera` instance with DMA support.
|
/// Creates a new `Camera` instance with DMA support.
|
||||||
pub fn new<P, CH>(
|
pub fn new<P, CH>(
|
||||||
cam: Cam<'d>,
|
cam: Cam<'d>,
|
||||||
channel: ChannelRx<'d, CH>,
|
channel: ChannelRx<'d, Blocking, CH>,
|
||||||
_pins: P,
|
_pins: P,
|
||||||
frequency: HertzU32,
|
frequency: HertzU32,
|
||||||
) -> Self
|
) -> Self
|
||||||
|
|||||||
@ -83,21 +83,25 @@ use crate::{
|
|||||||
},
|
},
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::LCD_CAM,
|
peripherals::LCD_CAM,
|
||||||
|
Blocking,
|
||||||
Mode,
|
Mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents the I8080 LCD interface.
|
/// Represents the I8080 LCD interface.
|
||||||
pub struct I8080<'d, DM: Mode> {
|
pub struct I8080<'d, DM: Mode> {
|
||||||
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
||||||
tx_channel: ChannelTx<'d, <LCD_CAM as DmaEligible>::Dma>,
|
tx_channel: ChannelTx<'d, Blocking, <LCD_CAM as DmaEligible>::Dma>,
|
||||||
_phantom: PhantomData<DM>,
|
_mode: PhantomData<DM>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, DM: Mode> I8080<'d, DM> {
|
impl<'d, DM> I8080<'d, DM>
|
||||||
|
where
|
||||||
|
DM: Mode,
|
||||||
|
{
|
||||||
/// Creates a new instance of the I8080 LCD interface.
|
/// Creates a new instance of the I8080 LCD interface.
|
||||||
pub fn new<P, CH>(
|
pub fn new<P, CH>(
|
||||||
lcd: Lcd<'d, DM>,
|
lcd: Lcd<'d, DM>,
|
||||||
channel: ChannelTx<'d, CH>,
|
channel: ChannelTx<'d, Blocking, CH>,
|
||||||
mut pins: P,
|
mut pins: P,
|
||||||
frequency: HertzU32,
|
frequency: HertzU32,
|
||||||
config: Config,
|
config: Config,
|
||||||
@ -209,12 +213,10 @@ impl<'d, DM: Mode> I8080<'d, DM> {
|
|||||||
Self {
|
Self {
|
||||||
lcd_cam,
|
lcd_cam,
|
||||||
tx_channel: channel.degrade(),
|
tx_channel: channel.degrade(),
|
||||||
_phantom: PhantomData,
|
_mode: PhantomData,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, DM: Mode> I8080<'d, DM> {
|
|
||||||
/// Configures the byte order for data transmission in 16-bit mode.
|
/// Configures the byte order for data transmission in 16-bit mode.
|
||||||
/// This must be set to [ByteOrder::default()] when transmitting in 8-bit
|
/// This must be set to [ByteOrder::default()] when transmitting in 8-bit
|
||||||
/// mode.
|
/// mode.
|
||||||
|
|||||||
@ -118,3 +118,16 @@ macro_rules! any_peripheral {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Macro to choose between two expressions. Useful for implementing "else" for
|
||||||
|
/// `$()?` macro syntax.
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! if_set {
|
||||||
|
(, $not_set:expr) => {
|
||||||
|
$not_set
|
||||||
|
};
|
||||||
|
($set:expr, $not_set:expr) => {
|
||||||
|
$set
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@ -23,8 +23,6 @@
|
|||||||
//!
|
//!
|
||||||
//! [Parallel IO TX]: https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/parl_io_tx.rs
|
//! [Parallel IO TX]: https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/parl_io_tx.rs
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
|
||||||
|
|
||||||
use enumset::{EnumSet, EnumSetType};
|
use enumset::{EnumSet, EnumSetType};
|
||||||
use fugit::HertzU32;
|
use fugit::HertzU32;
|
||||||
use peripheral::PeripheralRef;
|
use peripheral::PeripheralRef;
|
||||||
@ -769,7 +767,6 @@ where
|
|||||||
Ok(ParlIoTx {
|
Ok(ParlIoTx {
|
||||||
tx_channel: self.tx_channel,
|
tx_channel: self.tx_channel,
|
||||||
tx_chain: DescriptorChain::new(self.descriptors),
|
tx_chain: DescriptorChain::new(self.descriptors),
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -801,7 +798,6 @@ where
|
|||||||
Ok(ParlIoTx {
|
Ok(ParlIoTx {
|
||||||
tx_channel: self.tx_channel,
|
tx_channel: self.tx_channel,
|
||||||
tx_chain: DescriptorChain::new(self.descriptors),
|
tx_chain: DescriptorChain::new(self.descriptors),
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -811,9 +807,8 @@ pub struct ParlIoTx<'d, DM>
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
{
|
{
|
||||||
tx_channel: ChannelTx<'d, <PARL_IO as DmaEligible>::Dma>,
|
tx_channel: ChannelTx<'d, DM, <PARL_IO as DmaEligible>::Dma>,
|
||||||
tx_chain: DescriptorChain,
|
tx_chain: DescriptorChain,
|
||||||
phantom: PhantomData<DM>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DM> core::fmt::Debug for ParlIoTx<'_, DM>
|
impl<DM> core::fmt::Debug for ParlIoTx<'_, DM>
|
||||||
@ -850,7 +845,6 @@ where
|
|||||||
Ok(ParlIoRx {
|
Ok(ParlIoRx {
|
||||||
rx_channel: self.rx_channel,
|
rx_channel: self.rx_channel,
|
||||||
rx_chain: DescriptorChain::new(self.descriptors),
|
rx_chain: DescriptorChain::new(self.descriptors),
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -880,7 +874,6 @@ where
|
|||||||
Ok(ParlIoRx {
|
Ok(ParlIoRx {
|
||||||
rx_channel: self.rx_channel,
|
rx_channel: self.rx_channel,
|
||||||
rx_chain: DescriptorChain::new(self.descriptors),
|
rx_chain: DescriptorChain::new(self.descriptors),
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -890,9 +883,8 @@ pub struct ParlIoRx<'d, DM>
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
{
|
{
|
||||||
rx_channel: ChannelRx<'d, <PARL_IO as DmaEligible>::Dma>,
|
rx_channel: ChannelRx<'d, DM, <PARL_IO as DmaEligible>::Dma>,
|
||||||
rx_chain: DescriptorChain,
|
rx_chain: DescriptorChain,
|
||||||
phantom: PhantomData<DM>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DM> core::fmt::Debug for ParlIoRx<'_, DM>
|
impl<DM> core::fmt::Debug for ParlIoRx<'_, DM>
|
||||||
@ -1005,7 +997,7 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> {
|
|||||||
/// Create a new instance of [ParlIoFullDuplex]
|
/// Create a new instance of [ParlIoFullDuplex]
|
||||||
pub fn new<CH, DM>(
|
pub fn new<CH, DM>(
|
||||||
_parl_io: impl Peripheral<P = peripherals::PARL_IO> + 'd,
|
_parl_io: impl Peripheral<P = peripherals::PARL_IO> + 'd,
|
||||||
dma_channel: Channel<'d, CH, DM>,
|
dma_channel: Channel<'d, DM, CH>,
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
frequency: HertzU32,
|
frequency: HertzU32,
|
||||||
@ -1013,43 +1005,33 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> {
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
CH: DmaChannelConvert<<PARL_IO as DmaEligible>::Dma>,
|
CH: DmaChannelConvert<<PARL_IO as DmaEligible>::Dma>,
|
||||||
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
|
Channel<'d, Blocking, CH>: From<Channel<'d, DM, CH>>,
|
||||||
{
|
{
|
||||||
let dma_channel = Channel::<'d, CH, Blocking>::from(dma_channel);
|
let dma_channel = Channel::<Blocking, CH>::from(dma_channel);
|
||||||
internal_init(frequency)?;
|
internal_init(frequency)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
tx: TxCreatorFullDuplex {
|
tx: TxCreatorFullDuplex {
|
||||||
tx_channel: dma_channel.tx.degrade(),
|
tx_channel: dma_channel.tx.degrade(),
|
||||||
descriptors: tx_descriptors,
|
descriptors: tx_descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
rx: RxCreatorFullDuplex {
|
rx: RxCreatorFullDuplex {
|
||||||
rx_channel: dma_channel.rx.degrade(),
|
rx_channel: dma_channel.rx.degrade(),
|
||||||
descriptors: rx_descriptors,
|
descriptors: rx_descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to an async version.
|
/// Convert to an async version.
|
||||||
pub fn into_async(self) -> ParlIoFullDuplex<'d, Async> {
|
pub fn into_async(self) -> ParlIoFullDuplex<'d, Async> {
|
||||||
let channel = Channel {
|
|
||||||
tx: self.tx.tx_channel,
|
|
||||||
rx: self.rx.rx_channel,
|
|
||||||
phantom: PhantomData::<Blocking>,
|
|
||||||
};
|
|
||||||
let channel = channel.into_async();
|
|
||||||
ParlIoFullDuplex {
|
ParlIoFullDuplex {
|
||||||
tx: TxCreatorFullDuplex {
|
tx: TxCreatorFullDuplex {
|
||||||
tx_channel: channel.tx,
|
tx_channel: self.tx.tx_channel.into_async(),
|
||||||
descriptors: self.tx.descriptors,
|
descriptors: self.tx.descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
rx: RxCreatorFullDuplex {
|
rx: RxCreatorFullDuplex {
|
||||||
rx_channel: channel.rx,
|
rx_channel: self.rx.rx_channel.into_async(),
|
||||||
descriptors: self.rx.descriptors,
|
descriptors: self.rx.descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1094,22 +1076,14 @@ impl InterruptConfigurable for ParlIoFullDuplex<'_, Blocking> {
|
|||||||
impl<'d> ParlIoFullDuplex<'d, Async> {
|
impl<'d> ParlIoFullDuplex<'d, Async> {
|
||||||
/// Convert to a blocking version.
|
/// Convert to a blocking version.
|
||||||
pub fn into_blocking(self) -> ParlIoFullDuplex<'d, Blocking> {
|
pub fn into_blocking(self) -> ParlIoFullDuplex<'d, Blocking> {
|
||||||
let channel = Channel {
|
|
||||||
tx: self.tx.tx_channel,
|
|
||||||
rx: self.rx.rx_channel,
|
|
||||||
phantom: PhantomData::<Async>,
|
|
||||||
};
|
|
||||||
let channel = channel.into_blocking();
|
|
||||||
ParlIoFullDuplex {
|
ParlIoFullDuplex {
|
||||||
tx: TxCreatorFullDuplex {
|
tx: TxCreatorFullDuplex {
|
||||||
tx_channel: channel.tx,
|
tx_channel: self.tx.tx_channel.into_blocking(),
|
||||||
descriptors: self.tx.descriptors,
|
descriptors: self.tx.descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
rx: RxCreatorFullDuplex {
|
rx: RxCreatorFullDuplex {
|
||||||
rx_channel: channel.rx,
|
rx_channel: self.rx.rx_channel.into_blocking(),
|
||||||
descriptors: self.rx.descriptors,
|
descriptors: self.rx.descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1133,7 +1107,7 @@ where
|
|||||||
// TODO: only take a TX DMA channel?
|
// TODO: only take a TX DMA channel?
|
||||||
pub fn new<CH>(
|
pub fn new<CH>(
|
||||||
_parl_io: impl Peripheral<P = peripherals::PARL_IO> + 'd,
|
_parl_io: impl Peripheral<P = peripherals::PARL_IO> + 'd,
|
||||||
dma_channel: Channel<'d, CH, DM>,
|
dma_channel: Channel<'d, DM, CH>,
|
||||||
descriptors: &'static mut [DmaDescriptor],
|
descriptors: &'static mut [DmaDescriptor],
|
||||||
frequency: HertzU32,
|
frequency: HertzU32,
|
||||||
) -> Result<Self, Error>
|
) -> Result<Self, Error>
|
||||||
@ -1146,7 +1120,6 @@ where
|
|||||||
tx: TxCreator {
|
tx: TxCreator {
|
||||||
tx_channel: dma_channel.tx.degrade(),
|
tx_channel: dma_channel.tx.degrade(),
|
||||||
descriptors,
|
descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1208,7 +1181,7 @@ where
|
|||||||
// TODO: only take a RX DMA channel?
|
// TODO: only take a RX DMA channel?
|
||||||
pub fn new<CH>(
|
pub fn new<CH>(
|
||||||
_parl_io: impl Peripheral<P = peripherals::PARL_IO> + 'd,
|
_parl_io: impl Peripheral<P = peripherals::PARL_IO> + 'd,
|
||||||
dma_channel: Channel<'d, CH, DM>,
|
dma_channel: Channel<'d, DM, CH>,
|
||||||
descriptors: &'static mut [DmaDescriptor],
|
descriptors: &'static mut [DmaDescriptor],
|
||||||
frequency: HertzU32,
|
frequency: HertzU32,
|
||||||
) -> Result<Self, Error>
|
) -> Result<Self, Error>
|
||||||
@ -1221,7 +1194,6 @@ where
|
|||||||
rx: RxCreator {
|
rx: RxCreator {
|
||||||
rx_channel: dma_channel.rx.degrade(),
|
rx_channel: dma_channel.rx.degrade(),
|
||||||
descriptors,
|
descriptors,
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1372,7 +1344,7 @@ impl<'d, DM> DmaSupportTx for ParlIoTx<'d, DM>
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
{
|
{
|
||||||
type TX = ChannelTx<'d, <PARL_IO as DmaEligible>::Dma>;
|
type TX = ChannelTx<'d, DM, <PARL_IO as DmaEligible>::Dma>;
|
||||||
|
|
||||||
fn tx(&mut self) -> &mut Self::TX {
|
fn tx(&mut self) -> &mut Self::TX {
|
||||||
&mut self.tx_channel
|
&mut self.tx_channel
|
||||||
@ -1414,7 +1386,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn start_receive_bytes_dma(
|
fn start_receive_bytes_dma(
|
||||||
rx_channel: &mut ChannelRx<'d, <PARL_IO as DmaEligible>::Dma>,
|
rx_channel: &mut ChannelRx<'d, DM, <PARL_IO as DmaEligible>::Dma>,
|
||||||
rx_chain: &mut DescriptorChain,
|
rx_chain: &mut DescriptorChain,
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
len: usize,
|
len: usize,
|
||||||
@ -1468,7 +1440,7 @@ impl<'d, DM> DmaSupportRx for ParlIoRx<'d, DM>
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
{
|
{
|
||||||
type RX = ChannelRx<'d, <PARL_IO as DmaEligible>::Dma>;
|
type RX = ChannelRx<'d, DM, <PARL_IO as DmaEligible>::Dma>;
|
||||||
|
|
||||||
fn rx(&mut self) -> &mut Self::RX {
|
fn rx(&mut self) -> &mut Self::RX {
|
||||||
&mut self.rx_channel
|
&mut self.rx_channel
|
||||||
@ -1484,9 +1456,8 @@ pub struct TxCreator<'d, DM>
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
{
|
{
|
||||||
tx_channel: ChannelTx<'d, <PARL_IO as DmaEligible>::Dma>,
|
tx_channel: ChannelTx<'d, DM, <PARL_IO as DmaEligible>::Dma>,
|
||||||
descriptors: &'static mut [DmaDescriptor],
|
descriptors: &'static mut [DmaDescriptor],
|
||||||
phantom: PhantomData<DM>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a RX channel
|
/// Creates a RX channel
|
||||||
@ -1494,9 +1465,8 @@ pub struct RxCreator<'d, DM>
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
{
|
{
|
||||||
rx_channel: ChannelRx<'d, <PARL_IO as DmaEligible>::Dma>,
|
rx_channel: ChannelRx<'d, DM, <PARL_IO as DmaEligible>::Dma>,
|
||||||
descriptors: &'static mut [DmaDescriptor],
|
descriptors: &'static mut [DmaDescriptor],
|
||||||
phantom: PhantomData<DM>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a TX channel
|
/// Creates a TX channel
|
||||||
@ -1504,9 +1474,8 @@ pub struct TxCreatorFullDuplex<'d, DM>
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
{
|
{
|
||||||
tx_channel: ChannelTx<'d, <PARL_IO as DmaEligible>::Dma>,
|
tx_channel: ChannelTx<'d, DM, <PARL_IO as DmaEligible>::Dma>,
|
||||||
descriptors: &'static mut [DmaDescriptor],
|
descriptors: &'static mut [DmaDescriptor],
|
||||||
phantom: PhantomData<DM>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a RX channel
|
/// Creates a RX channel
|
||||||
@ -1514,9 +1483,8 @@ pub struct RxCreatorFullDuplex<'d, DM>
|
|||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
{
|
{
|
||||||
rx_channel: ChannelRx<'d, <PARL_IO as DmaEligible>::Dma>,
|
rx_channel: ChannelRx<'d, DM, <PARL_IO as DmaEligible>::Dma>,
|
||||||
descriptors: &'static mut [DmaDescriptor],
|
descriptors: &'static mut [DmaDescriptor],
|
||||||
phantom: PhantomData<DM>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|||||||
@ -474,11 +474,11 @@ where
|
|||||||
/// This method prepares the SPI instance for DMA transfers using SPI
|
/// This method prepares the SPI instance for DMA transfers using SPI
|
||||||
/// and returns an instance of `SpiDma` that supports DMA
|
/// and returns an instance of `SpiDma` that supports DMA
|
||||||
/// operations.
|
/// operations.
|
||||||
pub fn with_dma<CH, DM>(self, channel: Channel<'d, CH, DM>) -> SpiDma<'d, M, T>
|
pub fn with_dma<CH, DM>(self, channel: Channel<'d, DM, CH>) -> SpiDma<'d, M, T>
|
||||||
where
|
where
|
||||||
CH: DmaChannelConvert<T::Dma>,
|
CH: DmaChannelConvert<T::Dma>,
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
Channel<'d, CH, M>: From<Channel<'d, CH, DM>>,
|
Channel<'d, M, CH>: From<Channel<'d, DM, CH>>,
|
||||||
{
|
{
|
||||||
SpiDma::new(self.spi, channel.into())
|
SpiDma::new(self.spi, channel.into())
|
||||||
}
|
}
|
||||||
@ -880,7 +880,7 @@ mod dma {
|
|||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
pub(crate) spi: PeripheralRef<'d, T>,
|
pub(crate) spi: PeripheralRef<'d, T>,
|
||||||
pub(crate) channel: Channel<'d, T::Dma, M>,
|
pub(crate) channel: Channel<'d, M, T::Dma>,
|
||||||
tx_transfer_in_progress: bool,
|
tx_transfer_in_progress: bool,
|
||||||
rx_transfer_in_progress: bool,
|
rx_transfer_in_progress: bool,
|
||||||
#[cfg(all(esp32, spi_address_workaround))]
|
#[cfg(all(esp32, spi_address_workaround))]
|
||||||
@ -990,7 +990,7 @@ mod dma {
|
|||||||
T: Instance,
|
T: Instance,
|
||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
pub(super) fn new<CH>(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self
|
pub(super) fn new<CH>(spi: PeripheralRef<'d, T>, channel: Channel<'d, M, CH>) -> Self
|
||||||
where
|
where
|
||||||
CH: DmaChannelConvert<T::Dma>,
|
CH: DmaChannelConvert<T::Dma>,
|
||||||
{
|
{
|
||||||
@ -3003,10 +3003,10 @@ macro_rules! spi_instance {
|
|||||||
cs: OutputSignal::$cs,
|
cs: OutputSignal::$cs,
|
||||||
sio0_input: InputSignal::$mosi,
|
sio0_input: InputSignal::$mosi,
|
||||||
sio1_output: OutputSignal::$miso,
|
sio1_output: OutputSignal::$miso,
|
||||||
sio2_output: if_set!($(Some(OutputSignal::$sio2))?, None),
|
sio2_output: $crate::if_set!($(Some(OutputSignal::$sio2))?, None),
|
||||||
sio2_input: if_set!($(Some(InputSignal::$sio2))?, None),
|
sio2_input: $crate::if_set!($(Some(InputSignal::$sio2))?, None),
|
||||||
sio3_output: if_set!($(Some(OutputSignal::$sio3))?, None),
|
sio3_output: $crate::if_set!($(Some(OutputSignal::$sio3))?, None),
|
||||||
sio3_input: if_set!($(Some(InputSignal::$sio3))?, None),
|
sio3_input: $crate::if_set!($(Some(InputSignal::$sio3))?, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
&INFO
|
&INFO
|
||||||
@ -3022,17 +3022,6 @@ macro_rules! spi_instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Macro to choose between two expressions. Useful for implementing "else" for
|
|
||||||
/// `$()?` macro syntax.
|
|
||||||
macro_rules! if_set {
|
|
||||||
(, $not_set:expr) => {
|
|
||||||
$not_set
|
|
||||||
};
|
|
||||||
($set:expr, $not_set:expr) => {
|
|
||||||
$set
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(spi2)]
|
#[cfg(spi2)]
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(esp32)] {
|
if #[cfg(esp32)] {
|
||||||
|
|||||||
@ -202,14 +202,14 @@ pub mod dma {
|
|||||||
#[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")]
|
#[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")]
|
||||||
pub fn with_dma<CH, DM>(
|
pub fn with_dma<CH, DM>(
|
||||||
self,
|
self,
|
||||||
channel: Channel<'d, CH, DM>,
|
channel: Channel<'d, DM, CH>,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
) -> SpiDma<'d, M, T>
|
) -> SpiDma<'d, M, T>
|
||||||
where
|
where
|
||||||
CH: DmaChannelConvert<T::Dma>,
|
CH: DmaChannelConvert<T::Dma>,
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
Channel<'d, CH, M>: From<Channel<'d, CH, DM>>,
|
Channel<'d, M, CH>: From<Channel<'d, DM, CH>>,
|
||||||
{
|
{
|
||||||
self.spi.info().set_data_mode(self.data_mode, true);
|
self.spi.info().set_data_mode(self.data_mode, true);
|
||||||
SpiDma::new(self.spi, channel.into(), rx_descriptors, tx_descriptors)
|
SpiDma::new(self.spi, channel.into(), rx_descriptors, tx_descriptors)
|
||||||
@ -223,7 +223,7 @@ pub mod dma {
|
|||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
pub(crate) spi: PeripheralRef<'d, T>,
|
pub(crate) spi: PeripheralRef<'d, T>,
|
||||||
pub(crate) channel: Channel<'d, T::Dma, M>,
|
pub(crate) channel: Channel<'d, M, T::Dma>,
|
||||||
rx_chain: DescriptorChain,
|
rx_chain: DescriptorChain,
|
||||||
tx_chain: DescriptorChain,
|
tx_chain: DescriptorChain,
|
||||||
}
|
}
|
||||||
@ -262,7 +262,7 @@ pub mod dma {
|
|||||||
T: InstanceDma,
|
T: InstanceDma,
|
||||||
DmaMode: Mode,
|
DmaMode: Mode,
|
||||||
{
|
{
|
||||||
type TX = ChannelTx<'d, T::Dma>;
|
type TX = ChannelTx<'d, DmaMode, T::Dma>;
|
||||||
|
|
||||||
fn tx(&mut self) -> &mut Self::TX {
|
fn tx(&mut self) -> &mut Self::TX {
|
||||||
&mut self.channel.tx
|
&mut self.channel.tx
|
||||||
@ -278,7 +278,7 @@ pub mod dma {
|
|||||||
T: InstanceDma,
|
T: InstanceDma,
|
||||||
DmaMode: Mode,
|
DmaMode: Mode,
|
||||||
{
|
{
|
||||||
type RX = ChannelRx<'d, T::Dma>;
|
type RX = ChannelRx<'d, DmaMode, T::Dma>;
|
||||||
|
|
||||||
fn rx(&mut self) -> &mut Self::RX {
|
fn rx(&mut self) -> &mut Self::RX {
|
||||||
&mut self.channel.rx
|
&mut self.channel.rx
|
||||||
@ -296,7 +296,7 @@ pub mod dma {
|
|||||||
{
|
{
|
||||||
fn new<CH>(
|
fn new<CH>(
|
||||||
spi: PeripheralRef<'d, T>,
|
spi: PeripheralRef<'d, T>,
|
||||||
channel: Channel<'d, CH, DmaMode>,
|
channel: Channel<'d, DmaMode, CH>,
|
||||||
rx_descriptors: &'static mut [DmaDescriptor],
|
rx_descriptors: &'static mut [DmaDescriptor],
|
||||||
tx_descriptors: &'static mut [DmaDescriptor],
|
tx_descriptors: &'static mut [DmaDescriptor],
|
||||||
) -> Self
|
) -> Self
|
||||||
|
|||||||
@ -25,7 +25,7 @@ cfg_if::cfg_if! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
channel: Channel<'static, AnyGdmaChannel, Blocking>,
|
channel: Channel<'static, Blocking, AnyGdmaChannel>,
|
||||||
dma_peripheral: DmaPeripheralType,
|
dma_peripheral: DmaPeripheralType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -90,27 +90,6 @@ mod tests {
|
|||||||
xfer.wait().0.unwrap();
|
xfer.wait().0.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_i8080_8bit_async_channel(ctx: Context<'static>) {
|
|
||||||
let channel = ctx
|
|
||||||
.dma
|
|
||||||
.channel0
|
|
||||||
.configure(false, DmaPriority::Priority0)
|
|
||||||
.into_async();
|
|
||||||
let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin);
|
|
||||||
|
|
||||||
let i8080 = I8080::new(
|
|
||||||
ctx.lcd_cam.lcd,
|
|
||||||
channel.tx,
|
|
||||||
pins,
|
|
||||||
20.MHz(),
|
|
||||||
Config::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let xfer = i8080.send(Command::<u8>::None, 0, ctx.dma_buf).unwrap();
|
|
||||||
xfer.wait().0.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_i8080_8bit_is_seen_by_pcnt(ctx: Context<'static>) {
|
fn test_i8080_8bit_is_seen_by_pcnt(ctx: Context<'static>) {
|
||||||
// FIXME: Update this test to exercise all the I8080 output signals once the
|
// FIXME: Update this test to exercise all the I8080 output signals once the
|
||||||
|
|||||||
@ -70,31 +70,4 @@ mod tests {
|
|||||||
|
|
||||||
transfer.wait().0.unwrap();
|
transfer.wait().0.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
async fn test_i8080_8bit_async_channel(ctx: Context<'static>) {
|
|
||||||
let channel = ctx
|
|
||||||
.dma
|
|
||||||
.channel0
|
|
||||||
.configure(false, DmaPriority::Priority0)
|
|
||||||
.into_async();
|
|
||||||
let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin);
|
|
||||||
|
|
||||||
let i8080 = I8080::new(
|
|
||||||
ctx.lcd_cam.lcd,
|
|
||||||
channel.tx,
|
|
||||||
pins,
|
|
||||||
20.MHz(),
|
|
||||||
Config::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut transfer = i8080.send(Command::<u8>::None, 0, ctx.dma_buf).unwrap();
|
|
||||||
|
|
||||||
transfer.wait_for_done().await;
|
|
||||||
|
|
||||||
// This should not block forever and should immediately return.
|
|
||||||
transfer.wait_for_done().await;
|
|
||||||
|
|
||||||
transfer.wait().0.unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ struct Context {
|
|||||||
spi: Spi<'static, Blocking>,
|
spi: Spi<'static, Blocking>,
|
||||||
#[cfg(pcnt)]
|
#[cfg(pcnt)]
|
||||||
pcnt: esp_hal::peripherals::PCNT,
|
pcnt: esp_hal::peripherals::PCNT,
|
||||||
dma_channel: Channel<'static, DmaChannel0, Blocking>,
|
dma_channel: Channel<'static, Blocking, DmaChannel0>,
|
||||||
gpios: [AnyPin; 3],
|
gpios: [AnyPin; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user