Skip to content

Commit

Permalink
Slight general cleanup, enable dma-macros test, allow using virtual m…
Browse files Browse the repository at this point in the history
…em2mem channel on c2 (#2200)

* Cfg features, not devices

* Remove InterruptBinder

* Clean up allow(declare_interior_mutable_const)

* Small embassy cleanup

* Enable dma-macros for 32 and S2

* Use MEM2MEM1 on C2

* Remove esp32-specific code from test
bugadani authored Sep 20, 2024
1 parent 3d0a199 commit d4e463b
Showing 18 changed files with 97 additions and 234 deletions.
2 changes: 2 additions & 0 deletions esp-hal-embassy/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- MSRV bump to 1.79 (#2156)

### Fixed

### Removed
2 changes: 1 addition & 1 deletion esp-hal-embassy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
name = "esp-hal-embassy"
version = "0.3.0"
edition = "2021"
rust-version = "1.76.0"
rust-version = "1.79.0"
description = "Embassy support for esp-hal"
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"
18 changes: 5 additions & 13 deletions esp-hal-embassy/src/time_driver.rs
Original file line number Diff line number Diff line change
@@ -36,11 +36,8 @@ pub(super) struct EmbassyTimer {
alarms: Mutex<[AlarmState; MAX_SUPPORTED_ALARM_COUNT]>,
}

#[allow(clippy::declare_interior_mutable_const)]
const ALARM_STATE_NONE: AlarmState = AlarmState::new();

embassy_time_driver::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer {
alarms: Mutex::new([ALARM_STATE_NONE; MAX_SUPPORTED_ALARM_COUNT]),
alarms: Mutex::new([const { AlarmState::new() }; MAX_SUPPORTED_ALARM_COUNT]),
});

impl EmbassyTimer {
@@ -99,18 +96,13 @@ impl EmbassyTimer {
fn on_interrupt(&self, id: usize) {
let cb = critical_section::with(|cs| {
let mut timers = TIMERS.borrow_ref_mut(cs);
let timers = timers.as_mut().expect("Time driver not initialized");
let timers = unwrap!(timers.as_mut(), "Time driver not initialized");
let timer = &mut timers[id];

timer.clear_interrupt();

let alarm = &self.alarms.borrow(cs)[id];

if let Some((f, ctx)) = alarm.callback.get() {
Some((f, ctx))
} else {
None
}
alarm.callback.get()
});

if let Some((f, ctx)) = cb {
@@ -123,7 +115,7 @@ impl EmbassyTimer {
let ts = timestamp.micros();
// if the TS is already in the past make the timer fire immediately
let timeout = if ts > now { ts - now } else { 0.micros() };
timer.schedule(timeout).unwrap();
unwrap!(timer.schedule(timeout));
timer.enable_interrupt(true);
}
}
@@ -171,7 +163,7 @@ impl Driver for EmbassyTimer {
// soon as possible, but not synchronously.)
critical_section::with(|cs| {
let mut timers = TIMERS.borrow_ref_mut(cs);
let timers = timers.as_mut().expect("Time driver not initialized");
let timers = unwrap!(timers.as_mut(), "Time driver not initialized");
let timer = &mut timers[alarm.id() as usize];

Self::arm(timer, timestamp);
62 changes: 14 additions & 48 deletions esp-hal/src/dma/gdma.rs
Original file line number Diff line number Diff line change
@@ -12,10 +12,6 @@
//! GDMA peripheral can be initializes using the `new` function, which requires
//! a DMA peripheral instance and a clock control reference.
//!
//! ## Usage
//! This module implements DMA channels, such as `channel0`, `channel1` and so
//! on. Each channel struct implements the `ChannelTypes` trait, which provides
//! associated types for peripheral configuration.
//! <em>PS: Note that the number of DMA channels is chip-specific.</em>
use crate::{
@@ -29,12 +25,6 @@ pub struct Channel<const N: u8> {}

impl<const N: u8> crate::private::Sealed for Channel<N> {}

#[doc(hidden)]
#[non_exhaustive]
pub struct ChannelInterruptBinder<const N: u8> {}

impl<const N: u8> crate::private::Sealed for ChannelInterruptBinder<N> {}

impl<const N: u8> Channel<N> {
#[inline(always)]
fn ch() -> &'static crate::peripherals::dma::ch::CH {
@@ -102,10 +92,8 @@ impl<const N: u8> RegisterAccess for Channel<N> {

fn set_out_burstmode(burst_mode: bool) {
Self::ch().out_conf0().modify(|_, w| {
w.out_data_burst_en()
.bit(burst_mode)
.outdscr_burst_en()
.bit(burst_mode)
w.out_data_burst_en().bit(burst_mode);
w.outdscr_burst_en().bit(burst_mode)
});
}

@@ -222,10 +210,8 @@ impl<const N: u8> RegisterAccess for Channel<N> {

fn set_in_burstmode(burst_mode: bool) {
Self::ch().in_conf0().modify(|_, w| {
w.in_data_burst_en()
.bit(burst_mode)
.indscr_burst_en()
.bit(burst_mode)
w.in_data_burst_en().bit(burst_mode);
w.indscr_burst_en().bit(burst_mode)
});
}

@@ -422,12 +408,8 @@ pub struct ChannelTxImpl<const N: u8> {}

use embassy_sync::waitqueue::AtomicWaker;

#[allow(clippy::declare_interior_mutable_const)]
const INIT: AtomicWaker = AtomicWaker::new();

static TX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [INIT; CHANNEL_COUNT];

static RX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [INIT; CHANNEL_COUNT];
static TX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];
static RX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];

impl<const N: u8> crate::private::Sealed for ChannelTxImpl<N> {}

@@ -461,10 +443,13 @@ impl<const N: u8> PeripheralMarker for SuitablePeripheral<N> {}
// with GDMA every channel can be used for any peripheral
impl<const N: u8> SpiPeripheral for SuitablePeripheral<N> {}
impl<const N: u8> Spi2Peripheral for SuitablePeripheral<N> {}
#[cfg(esp32s3)]
#[cfg(spi3)]
impl<const N: u8> Spi3Peripheral for SuitablePeripheral<N> {}
#[cfg(any(i2s0, i2s1))]
impl<const N: u8> I2sPeripheral for SuitablePeripheral<N> {}
#[cfg(i2s0)]
impl<const N: u8> I2s0Peripheral for SuitablePeripheral<N> {}
#[cfg(i2s1)]
impl<const N: u8> I2s1Peripheral for SuitablePeripheral<N> {}
#[cfg(parl_io)]
impl<const N: u8> ParlIoPeripheral for SuitablePeripheral<N> {}
@@ -476,22 +461,7 @@ impl<const N: u8> LcdCamPeripheral for SuitablePeripheral<N> {}
macro_rules! impl_channel {
($num: literal, $async_handler: path, $($interrupt: ident),* ) => {
paste::paste! {
#[doc(hidden)]
pub type [<Channel $num>] = Channel<$num>;

#[doc(hidden)]
pub type [<Channel $num TxImpl>] = ChannelTxImpl<$num>;

#[doc(hidden)]
pub type [<Channel $num RxImpl>] = ChannelRxImpl<$num>;

#[doc(hidden)]
pub type [<ChannelCreator $num>] = ChannelCreator<$num>;

#[doc(hidden)]
pub type [<Channel $num InterruptBinder>] = ChannelInterruptBinder<$num>;

impl InterruptBinder for ChannelInterruptBinder<$num> {
impl ChannelTypes for Channel<$num> {
fn set_isr(handler: $crate::interrupt::InterruptHandler) {
let mut dma = unsafe { crate::peripherals::DMA::steal() };
$(
@@ -501,10 +471,6 @@ macro_rules! impl_channel {
}
}

impl ChannelTypes for Channel<$num> {
type Binder = ChannelInterruptBinder<$num>;
}

/// A description of a GDMA channel
#[non_exhaustive]
pub struct [<DmaChannel $num>] {}
@@ -556,7 +522,7 @@ macro_rules! impl_channel {
let mut rx_impl = ChannelRxImpl {};
rx_impl.init(burst_mode, priority);

<Channel<$num> as ChannelTypes>::Binder::set_isr($async_handler);
<Channel<$num> as ChannelTypes>::set_isr($async_handler);

crate::dma::Channel {
tx: ChannelTx::new(tx_impl, burst_mode),
@@ -590,7 +556,7 @@ cfg_if::cfg_if! {
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);
}
}
}

/// GDMA Peripheral
@@ -725,7 +691,7 @@ mod m2m {
///
/// # Safety
///
/// You must insure 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.
pub unsafe fn new_unsafe(
mut channel: Channel<'d, C, MODE>,
57 changes: 14 additions & 43 deletions esp-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
@@ -641,7 +641,7 @@ pub enum DmaPeripheral {
Spi2 = 0,
#[cfg(any(pdma, esp32s3))]
Spi3 = 1,
#[cfg(any(esp32c6, esp32h2))]
#[cfg(any(esp32c2, esp32c6, esp32h2))]
Mem2Mem1 = 1,
#[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
Uhci0 = 2,
@@ -1888,11 +1888,6 @@ pub trait RegisterAccess: crate::private::Sealed {

#[doc(hidden)]
pub trait ChannelTypes: crate::private::Sealed {
type Binder: InterruptBinder;
}

#[doc(hidden)]
pub trait InterruptBinder: crate::private::Sealed {
fn set_isr(handler: InterruptHandler);
}

@@ -1918,7 +1913,7 @@ where
///
/// Interrupts are not enabled at the peripheral level here.
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
<C::Channel as ChannelTypes>::Binder::set_isr(handler);
<C::Channel as ChannelTypes>::set_isr(handler);
}

/// Listen for the given interrupts
@@ -3213,65 +3208,39 @@ pub(crate) mod asynch {
pub(crate) mod interrupt {
use procmacros::handler;

use super::*;
pub(crate) fn interrupt_handler_ch<const CH: u8>() {
use crate::dma::gdma::{Channel, ChannelRxImpl, ChannelTxImpl};

super::handle_interrupt::<Channel<CH>, ChannelRxImpl<CH>, ChannelTxImpl<CH>>();
}

#[handler(priority = crate::interrupt::Priority::max())]
pub(crate) fn interrupt_handler_ch0() {
use crate::dma::gdma::{
Channel0 as Channel,
Channel0RxImpl as ChannelRxImpl,
Channel0TxImpl as ChannelTxImpl,
};

handle_interrupt::<Channel, ChannelRxImpl, ChannelTxImpl>();
interrupt_handler_ch::<0>();
}

#[cfg(not(esp32c2))]
#[handler(priority = crate::interrupt::Priority::max())]
pub(crate) fn interrupt_handler_ch1() {
use crate::dma::gdma::{
Channel1 as Channel,
Channel1RxImpl as ChannelRxImpl,
Channel1TxImpl as ChannelTxImpl,
};

handle_interrupt::<Channel, ChannelRxImpl, ChannelTxImpl>();
interrupt_handler_ch::<1>();
}

#[cfg(not(esp32c2))]
#[handler(priority = crate::interrupt::Priority::max())]
pub(crate) fn interrupt_handler_ch2() {
use crate::dma::gdma::{
Channel2 as Channel,
Channel2RxImpl as ChannelRxImpl,
Channel2TxImpl as ChannelTxImpl,
};

handle_interrupt::<Channel, ChannelRxImpl, ChannelTxImpl>();
interrupt_handler_ch::<2>();
}

#[cfg(esp32s3)]
#[handler(priority = crate::interrupt::Priority::max())]
pub(crate) fn interrupt_handler_ch3() {
use crate::dma::gdma::{
Channel3 as Channel,
Channel3RxImpl as ChannelRxImpl,
Channel3TxImpl as ChannelTxImpl,
};

handle_interrupt::<Channel, ChannelRxImpl, ChannelTxImpl>();
interrupt_handler_ch::<3>();
}

#[cfg(esp32s3)]
#[handler(priority = crate::interrupt::Priority::max())]
pub(crate) fn interrupt_handler_ch4() {
use crate::dma::gdma::{
Channel4 as Channel,
Channel4RxImpl as ChannelRxImpl,
Channel4TxImpl as ChannelTxImpl,
};

handle_interrupt::<Channel, ChannelRxImpl, ChannelTxImpl>();
interrupt_handler_ch::<4>();
}
}

@@ -3292,6 +3261,7 @@ pub(crate) mod asynch {
handle_interrupt::<Channel, ChannelRxImpl, ChannelTxImpl>();
}

#[cfg(spi3)]
#[handler(priority = crate::interrupt::Priority::max())]
pub(crate) fn interrupt_handler_spi3_dma() {
use crate::dma::pdma::{
@@ -3303,6 +3273,7 @@ pub(crate) mod asynch {
handle_interrupt::<Channel, ChannelRxImpl, ChannelTxImpl>();
}

#[cfg(i2s0)]
#[handler(priority = crate::interrupt::Priority::max())]
pub(crate) fn interrupt_handler_i2s0() {
use crate::dma::pdma::{
Loading

0 comments on commit d4e463b

Please sign in to comment.