Skip to content

Commit

Permalink
Merge branch 'main' into esp-phy-crate
Browse files Browse the repository at this point in the history
  • Loading branch information
Frostie314159 authored Nov 14, 2024
2 parents 3af4918 + 38dde2e commit d0625dd
Show file tree
Hide file tree
Showing 36 changed files with 517 additions and 420 deletions.
2 changes: 2 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
- 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)
- The `Camera` and `I8080` drivers' constructors now only accepts blocking-mode DMA channels. (#2519)

### Fixed

Expand Down Expand Up @@ -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)
- `I2C` driver renamed to `I2c` (#2320)
- 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

Expand Down
47 changes: 45 additions & 2 deletions esp-hal/MIGRATING-0.21.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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

Creating peripheral interconnect signals now consume the GPIO pin used for the connection.
Expand Down Expand Up @@ -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.

Expand All @@ -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
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`

When trying to send a one-shot transmission will fail if it doesn't end with an end-marker.
Expand Down
12 changes: 6 additions & 6 deletions esp-hal/src/aes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,21 +276,21 @@ pub mod dma {
/// The underlying [`Aes`](super::Aes) driver
pub aes: super::Aes<'d>,

channel: Channel<'d, <AES as DmaEligible>::Dma, Blocking>,
channel: Channel<'d, Blocking, <AES as DmaEligible>::Dma>,
rx_chain: DescriptorChain,
tx_chain: DescriptorChain,
}

impl<'d> crate::aes::Aes<'d> {
/// Enable DMA for the current instance of the AES driver
pub fn with_dma<C>(
pub fn with_dma<CH>(
self,
channel: Channel<'d, C, Blocking>,
channel: Channel<'d, Blocking, CH>,
rx_descriptors: &'static mut [DmaDescriptor],
tx_descriptors: &'static mut [DmaDescriptor],
) -> AesDma<'d>
where
C: DmaChannelConvert<<AES as DmaEligible>::Dma>,
CH: DmaChannelConvert<<AES as DmaEligible>::Dma>,
{
AesDma {
aes: self,
Expand Down Expand Up @@ -324,7 +324,7 @@ pub mod dma {
}

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 {
&mut self.channel.tx
Expand All @@ -336,7 +336,7 @@ pub mod dma {
}

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 {
&mut self.channel.rx
Expand Down
147 changes: 97 additions & 50 deletions esp-hal/src/dma/gdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,48 +25,78 @@ use crate::{
#[doc(hidden)]
pub trait GdmaChannel {
fn number(&self) -> u8;
}

/// An arbitrary GDMA channel
#[non_exhaustive]
pub struct AnyGdmaChannel(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!(),
}
}

impl crate::private::Sealed for AnyGdmaChannel {}
impl DmaChannel for AnyGdmaChannel {
type Rx = ChannelRxImpl<Self>;
type Tx = ChannelTxImpl<Self>;
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<M: Mode>(ch: &Channel<'_, Self, M>) -> InterruptHandler {
match ch.tx.tx_impl.0.number() {
0 => DmaChannel0::handler(),
fn async_handler_in(&self) -> Option<InterruptHandler> {
match self.number() {
0 => DmaChannel0::handler_in(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::handler(),
1 => DmaChannel1::handler_in(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::handler(),
2 => DmaChannel2::handler_in(),
#[cfg(esp32s3)]
3 => DmaChannel3::handler(),
3 => DmaChannel3::handler_in(),
#[cfg(esp32s3)]
4 => DmaChannel4::handler(),
4 => DmaChannel4::handler_in(),
_ => unreachable!(),
}
}

fn interrupts<M: Mode>(ch: &Channel<'_, Self, M>) -> &'static [Interrupt] {
match ch.tx.tx_impl.0.number() {
0 => DmaChannel0::isrs(),
fn peripheral_interrupt_in(&self) -> Option<Interrupt> {
match self.number() {
0 => DmaChannel0::isr_in(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::isrs(),
1 => DmaChannel1::isr_in(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::isrs(),
2 => DmaChannel2::isr_in(),
#[cfg(esp32s3)]
3 => DmaChannel3::isrs(),
3 => DmaChannel3::isr_in(),
#[cfg(esp32s3)]
4 => DmaChannel4::isrs(),
4 => DmaChannel4::isr_in(),
_ => unreachable!(),
}
}
}

/// An arbitrary GDMA channel
#[non_exhaustive]
pub struct AnyGdmaChannel(u8);

impl crate::private::Sealed for AnyGdmaChannel {}
impl DmaChannel for AnyGdmaChannel {
type Rx = ChannelRxImpl<Self>;
type Tx = ChannelTxImpl<Self>;
}

#[non_exhaustive]
#[doc(hidden)]
pub struct SpecificGdmaChannel<const N: u8> {}
Expand Down Expand Up @@ -202,6 +232,14 @@ impl<C: GdmaChannel> TxRegisterAccess for ChannelTxImpl<C> {
.out_eof_des_addr()
.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> {
Expand Down Expand Up @@ -385,6 +423,14 @@ impl<C: GdmaChannel> RxRegisterAccess for ChannelRxImpl<C> {
.in_conf0()
.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> {
Expand Down Expand Up @@ -473,15 +519,15 @@ impl<C: GdmaChannel> InterruptAccess<DmaRxInterrupt> for ChannelRxImpl<C> {
#[non_exhaustive]
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.
pub fn runtime_ensure_compatible<P: DmaEligible>(&self, _peripheral: &PeripheralRef<'_, P>) {
// No runtime checks; GDMA channels are compatible with any peripheral
}
}

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! {
/// A description of a specific GDMA channel
#[non_exhaustive]
Expand All @@ -490,26 +536,26 @@ macro_rules! impl_channel {
impl crate::private::Sealed for [<DmaChannel $num>] {}

impl [<DmaChannel $num>] {
fn handler() -> InterruptHandler {
$async_handler
fn handler_in() -> Option<InterruptHandler> {
Some($async_handler)
}

fn isr_in() -> Option<Interrupt> {
Some(Interrupt::$interrupt_in)
}

fn handler_out() -> Option<InterruptHandler> {
$crate::if_set! { $(Some($async_handler_out))?, None }
}

fn isrs() -> &'static [Interrupt] {
&[$(Interrupt::$interrupt),*]
fn isr_out() -> Option<Interrupt> {
$crate::if_set! { $(Some(Interrupt::$interrupt_out))?, None }
}
}

impl DmaChannel for [<DmaChannel $num>] {
type Rx = ChannelRxImpl<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>] {
Expand Down Expand Up @@ -537,11 +583,10 @@ macro_rules! impl_channel {
self,
burst_mode: bool,
priority: DmaPriority,
) -> Channel<'a, [<DmaChannel $num>], Blocking> {
) -> Channel<'a, Blocking, [<DmaChannel $num>]> {
let mut this = Channel {
tx: ChannelTx::new(ChannelTxImpl(SpecificGdmaChannel::<$num> {})),
rx: ChannelRx::new(ChannelRxImpl(SpecificGdmaChannel::<$num> {})),
phantom: PhantomData,
};

this.configure(burst_mode, priority);
Expand All @@ -553,27 +598,29 @@ macro_rules! impl_channel {
};
}

use super::asynch::interrupt as asynch_handler;

cfg_if::cfg_if! {
if #[cfg(esp32c2)] {
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)] {
const CHANNEL_COUNT: usize = 3;
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_CH0);
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_CH1);
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_CH2);
impl_channel!(0, DMA_CH0, asynch_handler::interrupt_handler_ch0);
impl_channel!(1, DMA_CH1, asynch_handler::interrupt_handler_ch1);
impl_channel!(2, DMA_CH2, asynch_handler::interrupt_handler_ch2);
} else if #[cfg(any(esp32c6, esp32h2))] {
const CHANNEL_COUNT: usize = 3;
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_IN_CH0, DMA_OUT_CH0);
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_IN_CH1, DMA_OUT_CH1);
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_IN_CH2, DMA_OUT_CH2);
impl_channel!(0, DMA_IN_CH0, asynch_handler::interrupt_handler_ch0, DMA_OUT_CH0, asynch_handler::interrupt_handler_ch0);
impl_channel!(1, DMA_IN_CH1, asynch_handler::interrupt_handler_ch1, DMA_OUT_CH1, asynch_handler::interrupt_handler_ch1);
impl_channel!(2, DMA_IN_CH2, asynch_handler::interrupt_handler_ch2, DMA_OUT_CH2, asynch_handler::interrupt_handler_ch2);
} else if #[cfg(esp32s3)] {
const CHANNEL_COUNT: usize = 5;
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_IN_CH0, DMA_OUT_CH0);
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_IN_CH1, DMA_OUT_CH1);
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_IN_CH2, DMA_OUT_CH2);
impl_channel!(3, super::asynch::interrupt::interrupt_handler_ch3, DMA_IN_CH3, DMA_OUT_CH3);
impl_channel!(4, super::asynch::interrupt::interrupt_handler_ch4, DMA_IN_CH4, DMA_OUT_CH4);
impl_channel!(0, DMA_IN_CH0, asynch_handler::interrupt_handler_ch0, DMA_OUT_CH0, asynch_handler::interrupt_handler_ch0);
impl_channel!(1, DMA_IN_CH1, asynch_handler::interrupt_handler_ch1, DMA_OUT_CH1, asynch_handler::interrupt_handler_ch1);
impl_channel!(2, DMA_IN_CH2, asynch_handler::interrupt_handler_ch2, DMA_OUT_CH2, asynch_handler::interrupt_handler_ch2);
impl_channel!(3, DMA_IN_CH3, asynch_handler::interrupt_handler_ch3, DMA_OUT_CH3, asynch_handler::interrupt_handler_ch3);
impl_channel!(4, DMA_IN_CH4, asynch_handler::interrupt_handler_ch4, DMA_OUT_CH4, asynch_handler::interrupt_handler_ch4);
}
}

Expand Down
Loading

0 comments on commit d0625dd

Please sign in to comment.