diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs
index 1f285faa8..fb5f094f5 100644
--- a/esp-hal-procmacros/src/lib.rs
+++ b/esp-hal-procmacros/src/lib.rs
@@ -361,9 +361,12 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
/// Mark a function as an interrupt handler.
///
-/// This is really just a nicer looking way to make a function `unsafe extern
-/// "C"`
+/// Optionally a priority can be specified, e.g. `#[handler("Priority3")]`,
+/// "min" and "max" are special values.
+///
+/// If no priority is given, "Priority::min()" is assumed
#[cfg(feature = "interrupt")]
+#[proc_macro_error::proc_macro_error]
#[proc_macro_attribute]
pub fn handler(args: TokenStream, input: TokenStream) -> TokenStream {
use darling::ast::NestedMeta;
@@ -385,9 +388,40 @@ pub fn handler(args: TokenStream, input: TokenStream) -> TokenStream {
}
};
- if attr_args.len() > 0 {
- abort!(Span::call_site(), "This attribute accepts no arguments")
- }
+ let root = Ident::new(
+ if let Ok(FoundCrate::Name(ref name)) = crate_name("esp-hal") {
+ &name
+ } else {
+ "crate"
+ },
+ Span::call_site().into(),
+ );
+
+ let priority = if attr_args.len() > 1 {
+ abort!(
+ Span::call_site(),
+ "This attribute accepts one optional argument"
+ )
+ } else if attr_args.len() == 1 {
+ match &attr_args[0] {
+ NestedMeta::Lit(syn::Lit::Str(priority)) => priority.value(),
+ _ => abort!(
+ Span::call_site(),
+ "The priority must be provided as a string"
+ ),
+ }
+ } else {
+ String::from("min")
+ };
+
+ let priority = match priority.as_str() {
+ "min" => quote::quote_spanned!(original_span => #root::interrupt::Priority::min()),
+ "max" => quote::quote_spanned!(original_span => #root::interrupt::Priority::max()),
+ _ => {
+ let priority = Ident::new(&priority, proc_macro2::Span::call_site());
+ quote::quote_spanned!(original_span => #root::interrupt::Priority::#priority)
+ }
+ };
// XXX should we blacklist other attributes?
@@ -419,17 +453,9 @@ pub fn handler(args: TokenStream, input: TokenStream) -> TokenStream {
.into();
}
- let root = Ident::new(
- if let Ok(FoundCrate::Name(ref name)) = crate_name("esp-hal") {
- &name
- } else {
- "crate"
- },
- Span::call_site().into(),
- );
-
f.sig.abi = syn::parse_quote_spanned!(original_span => extern "C");
let orig = f.sig.ident;
+ let vis = f.vis.clone();
f.sig.ident = Ident::new(
&format!("__esp_hal_internal_{}", orig),
proc_macro2::Span::call_site(),
@@ -440,7 +466,7 @@ pub fn handler(args: TokenStream, input: TokenStream) -> TokenStream {
#f
#[allow(non_upper_case_globals)]
- static #orig: #root::interrupt::InterruptHandler = #root::interrupt::InterruptHandler::new(#new, #root::interrupt::Priority::min());
+ #vis static #orig: #root::interrupt::InterruptHandler = #root::interrupt::InterruptHandler::new(#new, #priority);
)
.into()
}
diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md
index 3c4add5db..d039ad349 100644
--- a/esp-hal/CHANGELOG.md
+++ b/esp-hal/CHANGELOG.md
@@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Renamed `eh1` feature to `embedded-hal`, feature-gated `embedded-hal@0.2.x` trait implementations (#1273)
- Enable `embedded-hal` feature by default, instead of the `embedded-hal-02` feature (#1313)
- `Uart` structs now take a `Mode` parameter which defines how the driver is initialized (#1294)
+- `Rmt` can be created in async or blocking mode. The blocking constructor takes an optional interrupt handler argument. (#1341)
### Removed
diff --git a/esp-hal/src/embassy/mod.rs b/esp-hal/src/embassy/mod.rs
index cba292ba7..ef3b907f0 100644
--- a/esp-hal/src/embassy/mod.rs
+++ b/esp-hal/src/embassy/mod.rs
@@ -150,9 +150,6 @@ pub fn init(clocks: &Clocks, td: time_driver::TimerType) {
#[cfg(i2s1)]
crate::interrupt::enable(Interrupt::I2S1, Priority::min()).unwrap();
- #[cfg(rmt)]
- crate::interrupt::enable(Interrupt::RMT, Priority::min()).unwrap();
-
#[cfg(usb_device)]
crate::interrupt::enable(Interrupt::USB_DEVICE, Priority::min()).unwrap();
diff --git a/esp-hal/src/interrupt/xtensa.rs b/esp-hal/src/interrupt/xtensa.rs
index 7545a951a..d8b37231a 100644
--- a/esp-hal/src/interrupt/xtensa.rs
+++ b/esp-hal/src/interrupt/xtensa.rs
@@ -68,6 +68,21 @@ pub const RESERVED_INTERRUPTS: &[usize] = &[
CpuInterrupt::Interrupt22EdgePriority3 as _,
];
+pub(crate) fn setup_interrupts() {
+ // disable all known interrupts
+ // at least after the 2nd stage bootloader there are some interrupts enabled
+ // (e.g. UART)
+ for peripheral_interrupt in 0..255 {
+ crate::soc::peripherals::Interrupt::try_from(peripheral_interrupt)
+ .map(|intr| {
+ #[cfg(multi_core)]
+ disable(Cpu::AppCpu, intr);
+ disable(Cpu::ProCpu, intr);
+ })
+ .ok();
+ }
+}
+
/// Enable an interrupt by directly binding it to a available CPU interrupt
///
/// Unless you are sure, you most likely want to use [`enable`] with the
diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs
index fd4b4f5b8..78665da2e 100644
--- a/esp-hal/src/lib.rs
+++ b/esp-hal/src/lib.rs
@@ -158,9 +158,11 @@ extern "C" fn EspDefaultHandler(_interrupt: peripherals::Interrupt) {
pub trait Mode: crate::private::Sealed {}
/// Driver initialized in blocking mode.
+#[derive(Debug)]
pub struct Blocking;
/// Driver initialized in async mode.
+#[derive(Debug)]
pub struct Async;
impl crate::Mode for Blocking {}
diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs
index 52820fd2f..543d03b64 100644
--- a/esp-hal/src/rmt.rs
+++ b/esp-hal/src/rmt.rs
@@ -83,11 +83,14 @@
//! channel = transaction.wait().unwrap();
//! ```
+use core::marker::PhantomData;
+
use fugit::HertzU32;
use crate::{
clock::Clocks,
gpio::{InputPin, OutputPin},
+ interrupt::InterruptHandler,
peripheral::Peripheral,
rmt::private::CreateInstance,
soc::constants,
@@ -201,12 +204,18 @@ pub struct RxChannelConfig {
pub use impl_for_chip::Rmt;
-impl<'d> Rmt<'d> {
- /// Create a new RMT instance
- pub fn new(
+#[cfg(feature = "async")]
+use self::asynch::{RxChannelAsync, TxChannelAsync};
+
+impl<'d, M> Rmt<'d, M>
+where
+ M: crate::Mode,
+{
+ pub fn new_internal(
peripheral: impl Peripheral
+ 'd,
frequency: HertzU32,
_clocks: &Clocks,
+ interrupt: Option,
) -> Result {
let me = Rmt::create(peripheral);
@@ -223,6 +232,17 @@ impl<'d> Rmt<'d> {
#[cfg(any(esp32, esp32s2))]
self::chip_specific::configure_clock();
+ if let Some(interrupt) = interrupt {
+ unsafe {
+ crate::interrupt::bind_interrupt(
+ crate::peripherals::Interrupt::RMT,
+ interrupt.handler(),
+ );
+ crate::interrupt::enable(crate::peripherals::Interrupt::RMT, interrupt.priority())
+ .unwrap();
+ }
+ }
+
Ok(me)
}
@@ -246,6 +266,35 @@ impl<'d> Rmt<'d> {
}
}
+impl<'d> Rmt<'d, crate::Blocking> {
+ /// Create a new RMT instance
+ pub fn new(
+ peripheral: impl Peripheral + 'd,
+ frequency: HertzU32,
+ _clocks: &Clocks,
+ interrupt: Option,
+ ) -> Result {
+ Self::new_internal(peripheral, frequency, _clocks, interrupt)
+ }
+}
+
+#[cfg(feature = "async")]
+impl<'d> Rmt<'d, crate::Async> {
+ /// Create a new RMT instance
+ pub fn new_async(
+ peripheral: impl Peripheral + 'd,
+ frequency: HertzU32,
+ _clocks: &Clocks,
+ ) -> Result {
+ Self::new_internal(
+ peripheral,
+ frequency,
+ _clocks,
+ Some(asynch::async_interrupt_handler),
+ )
+ }
+}
+
pub trait TxChannelCreator<'d, T, P>
where
P: OutputPin,
@@ -276,6 +325,37 @@ where
}
}
+#[cfg(feature = "async")]
+pub trait TxChannelCreatorAsync<'d, T, P>
+where
+ P: OutputPin,
+ T: TxChannelAsync,
+{
+ /// Configure the TX channel
+ fn configure(
+ self,
+ pin: impl Peripheral + 'd,
+ config: TxChannelConfig,
+ ) -> Result
+ where
+ Self: Sized,
+ {
+ crate::into_ref!(pin);
+ pin.set_to_push_pull_output()
+ .connect_peripheral_to_output(T::output_signal());
+ T::set_divider(config.clk_divider);
+ T::set_carrier(
+ config.carrier_modulation,
+ config.carrier_high,
+ config.carrier_low,
+ config.carrier_level,
+ );
+ T::set_idle_output(config.idle_output, config.idle_output_level);
+
+ Ok(T::new())
+ }
+}
+
pub trait RxChannelCreator<'d, T, P>
where
P: InputPin,
@@ -321,6 +401,52 @@ where
}
}
+#[cfg(feature = "async")]
+pub trait RxChannelCreatorAsync<'d, T, P>
+where
+ P: InputPin,
+ T: RxChannelAsync,
+{
+ /// Configure the RX channel
+ fn configure(
+ self,
+ pin: impl Peripheral + 'd,
+ config: RxChannelConfig,
+ ) -> Result
+ where
+ Self: Sized,
+ {
+ if config.filter_threshold > 0b111_1111 {
+ return Err(Error::InvalidArgument);
+ }
+
+ #[cfg(any(esp32, esp32s2))]
+ if config.idle_threshold > 0b111_1111_1111_1111 {
+ return Err(Error::InvalidArgument);
+ }
+
+ #[cfg(not(any(esp32, esp32s2)))]
+ if config.idle_threshold > 0b11_1111_1111_1111 {
+ return Err(Error::InvalidArgument);
+ }
+
+ crate::into_ref!(pin);
+ pin.set_to_input()
+ .connect_input_to_peripheral(T::input_signal());
+ T::set_divider(config.clk_divider);
+ T::set_carrier(
+ config.carrier_modulation,
+ config.carrier_high,
+ config.carrier_low,
+ config.carrier_level,
+ );
+ T::set_filter_threshold(config.filter_threshold);
+ T::set_idle_threshold(config.idle_threshold);
+
+ Ok(T::new())
+ }
+}
+
/// An in-progress transaction for a single shot TX transaction.
pub struct SingleShotTxTransaction<'a, C, T: Into + Copy>
where
@@ -338,18 +464,18 @@ where
/// Wait for the transaction to complete
pub fn wait(mut self) -> Result {
loop {
- if ::is_error() {
+ if >::is_error() {
return Err((Error::TransmissionError, self.channel));
}
if self.index < self.data.len() {
// wait for TX-THR
loop {
- if ::is_threshold_set() {
+ if >::is_threshold_set() {
break;
}
}
- ::reset_threshold_set();
+ >::reset_threshold_set();
// re-fill TX RAM
let ram_index = (((self.index - constants::RMT_CHANNEL_RAM_SIZE)
@@ -377,11 +503,11 @@ where
}
loop {
- if ::is_error() {
+ if >::is_error() {
return Err((Error::TransmissionError, self.channel));
}
- if ::is_done() {
+ if >::is_done() {
break;
}
}
@@ -404,15 +530,15 @@ where
{
/// Stop transaction when the current iteration ends.
pub fn stop_next(self) -> Result {
- ::set_continuous(false);
- ::update();
+ >::set_continuous(false);
+ >::update();
loop {
- if ::is_error() {
+ if >::is_error() {
return Err((Error::TransmissionError, self.channel));
}
- if ::is_done() {
+ if >::is_done() {
break;
}
}
@@ -422,8 +548,8 @@ where
/// Stop transaction as soon as possible.
pub fn stop(self) -> Result {
- ::set_continuous(false);
- ::update();
+ >::set_continuous(false);
+ >::update();
let ptr = (constants::RMT_RAM_START
+ C::CHANNEL as usize * constants::RMT_CHANNEL_RAM_SIZE * 4)
@@ -435,11 +561,11 @@ where
}
loop {
- if ::is_error() {
+ if >::is_error() {
return Err((Error::TransmissionError, self.channel));
}
- if ::is_done() {
+ if >::is_done() {
break;
}
}
@@ -448,71 +574,110 @@ where
}
pub fn is_loopcount_interrupt_set(&self) -> bool {
- ::is_loopcount_interrupt_set()
+ >::is_loopcount_interrupt_set()
}
}
macro_rules! impl_tx_channel_creator {
($channel:literal) => {
- impl<'d, P> $crate::rmt::TxChannelCreator<'d, $crate::rmt::Channel<$channel>, P>
- for ChannelCreator<$channel>
+ impl<'d, P> $crate::rmt::TxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>, P>
+ for ChannelCreator<$crate::Blocking, $channel>
where
P: $crate::gpio::OutputPin,
{
}
- impl $crate::rmt::TxChannel for $crate::rmt::Channel<$channel> {}
+ impl $crate::rmt::TxChannel for $crate::rmt::Channel<$crate::Blocking, $channel> {}
#[cfg(feature = "async")]
- impl $crate::rmt::asynch::TxChannelAsync for $crate::rmt::Channel<$channel> {}
+ impl<'d, P> $crate::rmt::TxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>, P>
+ for ChannelCreator<$crate::Async, $channel>
+ where
+ P: $crate::gpio::OutputPin,
+ {
+ }
+
+ #[cfg(feature = "async")]
+ impl $crate::rmt::asynch::TxChannelAsync for $crate::rmt::Channel<$crate::Async, $channel> {}
};
}
macro_rules! impl_rx_channel_creator {
($channel:literal) => {
- impl<'d, P> $crate::rmt::RxChannelCreator<'d, $crate::rmt::Channel<$channel>, P>
- for ChannelCreator<$channel>
+ impl<'d, P> $crate::rmt::RxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>, P>
+ for ChannelCreator<$crate::Blocking, $channel>
where
P: $crate::gpio::InputPin,
{
}
- impl $crate::rmt::RxChannel for $crate::rmt::Channel<$channel> {}
+ impl $crate::rmt::RxChannel for $crate::rmt::Channel<$crate::Blocking, $channel> {}
#[cfg(feature = "async")]
- impl $crate::rmt::asynch::RxChannelAsync for $crate::rmt::Channel<$channel> {}
+ impl<'d, P> $crate::rmt::RxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>, P>
+ for ChannelCreator<$crate::Async, $channel>
+ where
+ P: $crate::gpio::InputPin,
+ {
+ }
+
+ #[cfg(feature = "async")]
+ impl $crate::rmt::asynch::RxChannelAsync for $crate::rmt::Channel<$crate::Async, $channel> {}
};
}
#[cfg(not(any(esp32, esp32s2, esp32s3)))]
mod impl_for_chip {
+ use core::marker::PhantomData;
+
use super::private::CreateInstance;
use crate::peripheral::{Peripheral, PeripheralRef};
/// RMT Instance
- pub struct Rmt<'d> {
+ pub struct Rmt<'d, M>
+ where
+ M: crate::Mode,
+ {
_peripheral: PeripheralRef<'d, crate::peripherals::RMT>,
- pub channel0: ChannelCreator<0>,
- pub channel1: ChannelCreator<1>,
- pub channel2: ChannelCreator<2>,
- pub channel3: ChannelCreator<3>,
+ pub channel0: ChannelCreator,
+ pub channel1: ChannelCreator,
+ pub channel2: ChannelCreator,
+ pub channel3: ChannelCreator,
+ phantom: PhantomData,
}
- impl<'d> CreateInstance<'d> for Rmt<'d> {
+ impl<'d, M> CreateInstance<'d> for Rmt<'d, M>
+ where
+ M: crate::Mode,
+ {
fn create(peripheral: impl Peripheral + 'd) -> Self {
crate::into_ref!(peripheral);
Self {
_peripheral: peripheral,
- channel0: ChannelCreator {},
- channel1: ChannelCreator {},
- channel2: ChannelCreator {},
- channel3: ChannelCreator {},
+ channel0: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel1: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel2: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel3: ChannelCreator {
+ phantom: PhantomData,
+ },
+ phantom: PhantomData,
}
}
}
- pub struct ChannelCreator {}
+ pub struct ChannelCreator
+ where
+ M: crate::Mode,
+ {
+ phantom: PhantomData,
+ }
impl_tx_channel_creator!(0);
impl_tx_channel_creator!(1);
@@ -529,41 +694,72 @@ mod impl_for_chip {
#[cfg(esp32)]
mod impl_for_chip {
+ use core::marker::PhantomData;
+
use super::private::CreateInstance;
use crate::peripheral::{Peripheral, PeripheralRef};
/// RMT Instance
- pub struct Rmt<'d> {
+ pub struct Rmt<'d, M>
+ where
+ M: crate::Mode,
+ {
_peripheral: PeripheralRef<'d, crate::peripherals::RMT>,
- pub channel0: ChannelCreator<0>,
- pub channel1: ChannelCreator<1>,
- pub channel2: ChannelCreator<2>,
- pub channel3: ChannelCreator<3>,
- pub channel4: ChannelCreator<4>,
- pub channel5: ChannelCreator<5>,
- pub channel6: ChannelCreator<6>,
- pub channel7: ChannelCreator<7>,
+ pub channel0: ChannelCreator,
+ pub channel1: ChannelCreator,
+ pub channel2: ChannelCreator,
+ pub channel3: ChannelCreator,
+ pub channel4: ChannelCreator,
+ pub channel5: ChannelCreator,
+ pub channel6: ChannelCreator,
+ pub channel7: ChannelCreator,
+ phantom: PhantomData,
}
- impl<'d> CreateInstance<'d> for Rmt<'d> {
+ impl<'d, M> CreateInstance<'d> for Rmt<'d, M>
+ where
+ M: crate::Mode,
+ {
fn create(peripheral: impl Peripheral + 'd) -> Self {
crate::into_ref!(peripheral);
Self {
_peripheral: peripheral,
- channel0: ChannelCreator {},
- channel1: ChannelCreator {},
- channel2: ChannelCreator {},
- channel3: ChannelCreator {},
- channel4: ChannelCreator {},
- channel5: ChannelCreator {},
- channel6: ChannelCreator {},
- channel7: ChannelCreator {},
+ channel0: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel1: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel2: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel3: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel4: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel5: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel6: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel7: ChannelCreator {
+ phantom: PhantomData,
+ },
+ phantom: PhantomData,
}
}
}
- pub struct ChannelCreator {}
+ pub struct ChannelCreator
+ where
+ M: crate::Mode,
+ {
+ phantom: PhantomData,
+ }
impl_tx_channel_creator!(0);
impl_tx_channel_creator!(1);
@@ -604,33 +800,56 @@ mod impl_for_chip {
#[cfg(esp32s2)]
mod impl_for_chip {
+ use core::marker::PhantomData;
+
use super::private::CreateInstance;
use crate::peripheral::{Peripheral, PeripheralRef};
/// RMT Instance
- pub struct Rmt<'d> {
+ pub struct Rmt<'d, M>
+ where
+ M: crate::Mode,
+ {
_peripheral: PeripheralRef<'d, crate::peripherals::RMT>,
- pub channel0: ChannelCreator<0>,
- pub channel1: ChannelCreator<1>,
- pub channel2: ChannelCreator<2>,
- pub channel3: ChannelCreator<3>,
+ pub channel0: ChannelCreator,
+ pub channel1: ChannelCreator,
+ pub channel2: ChannelCreator,
+ pub channel3: ChannelCreator,
+ phantom: PhantomData,
}
- impl<'d> CreateInstance<'d> for Rmt<'d> {
+ impl<'d, M> CreateInstance<'d> for Rmt<'d, M>
+ where
+ M: crate::Mode,
+ {
fn create(peripheral: impl Peripheral + 'd) -> Self {
crate::into_ref!(peripheral);
Self {
_peripheral: peripheral,
- channel0: ChannelCreator {},
- channel1: ChannelCreator {},
- channel2: ChannelCreator {},
- channel3: ChannelCreator {},
+ channel0: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel1: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel2: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel3: ChannelCreator {
+ phantom: PhantomData,
+ },
+ phantom: PhantomData,
}
}
}
- pub struct ChannelCreator {}
+ pub struct ChannelCreator
+ where
+ M: crate::Mode,
+ {
+ phantom: PhantomData,
+ }
impl_tx_channel_creator!(0);
impl_tx_channel_creator!(1);
@@ -655,41 +874,72 @@ mod impl_for_chip {
#[cfg(esp32s3)]
mod impl_for_chip {
+ use core::marker::PhantomData;
+
use super::private::CreateInstance;
use crate::peripheral::{Peripheral, PeripheralRef};
/// RMT Instance
- pub struct Rmt<'d> {
+ pub struct Rmt<'d, M>
+ where
+ M: crate::Mode,
+ {
_peripheral: PeripheralRef<'d, crate::peripherals::RMT>,
- pub channel0: ChannelCreator<0>,
- pub channel1: ChannelCreator<1>,
- pub channel2: ChannelCreator<2>,
- pub channel3: ChannelCreator<3>,
- pub channel4: ChannelCreator<4>,
- pub channel5: ChannelCreator<5>,
- pub channel6: ChannelCreator<6>,
- pub channel7: ChannelCreator<7>,
+ pub channel0: ChannelCreator,
+ pub channel1: ChannelCreator,
+ pub channel2: ChannelCreator,
+ pub channel3: ChannelCreator,
+ pub channel4: ChannelCreator,
+ pub channel5: ChannelCreator,
+ pub channel6: ChannelCreator,
+ pub channel7: ChannelCreator,
+ phantom: PhantomData,
}
- impl<'d> CreateInstance<'d> for Rmt<'d> {
+ impl<'d, M> CreateInstance<'d> for Rmt<'d, M>
+ where
+ M: crate::Mode,
+ {
fn create(peripheral: impl Peripheral + 'd) -> Self {
crate::into_ref!(peripheral);
Self {
_peripheral: peripheral,
- channel0: ChannelCreator {},
- channel1: ChannelCreator {},
- channel2: ChannelCreator {},
- channel3: ChannelCreator {},
- channel4: ChannelCreator {},
- channel5: ChannelCreator {},
- channel6: ChannelCreator {},
- channel7: ChannelCreator {},
+ channel0: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel1: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel2: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel3: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel4: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel5: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel6: ChannelCreator {
+ phantom: PhantomData,
+ },
+ channel7: ChannelCreator {
+ phantom: PhantomData,
+ },
+ phantom: PhantomData,
}
}
}
- pub struct ChannelCreator {}
+ pub struct ChannelCreator
+ where
+ M: crate::Mode,
+ {
+ phantom: PhantomData,
+ }
impl_tx_channel_creator!(0);
impl_tx_channel_creator!(1);
@@ -715,9 +965,14 @@ mod impl_for_chip {
/// RMT Channel
#[non_exhaustive]
#[derive(Debug)]
-pub struct Channel {}
+pub struct Channel
+where
+ M: crate::Mode,
+{
+ phantom: PhantomData,
+}
-pub trait TxChannel: private::TxChannelInternal {
+pub trait TxChannel: private::TxChannelInternal {
/// Start transmitting the given pulse code sequence.
/// This returns a [`SingleShotTxTransaction`] which can be used to wait for
/// the transaction to complete and get back the channel for further
@@ -784,18 +1039,18 @@ where
/// Wait for the transaction to complete
pub fn wait(self) -> Result {
loop {
- if ::is_error() {
+ if >::is_error() {
return Err((Error::TransmissionError, self.channel));
}
- if ::is_done() {
+ if >::is_done() {
break;
}
}
- ::stop();
- ::clear_interrupts();
- ::update();
+ >::stop();
+ >::clear_interrupts();
+ >::update();
let ptr = (constants::RMT_RAM_START
+ C::CHANNEL as usize * constants::RMT_CHANNEL_RAM_SIZE * 4)
@@ -809,7 +1064,7 @@ where
}
}
-pub trait RxChannel: private::RxChannelInternal {
+pub trait RxChannel: private::RxChannelInternal {
/// Start receiving pulse codes into the given buffer.
/// This returns a [RxTransaction] which can be used to wait for receive to
/// complete and get back the channel for further use.
@@ -834,13 +1089,12 @@ pub trait RxChannel: private::RxChannelInternal {
#[cfg(feature = "async")]
pub mod asynch {
use core::{
- marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use embassy_sync::waitqueue::AtomicWaker;
- use procmacros::interrupt;
+ use procmacros::handler;
use super::{private::Event, *};
@@ -887,7 +1141,7 @@ pub mod asynch {
}
}
- pub trait TxChannelAsync: private::TxChannelInternal {
+ pub trait TxChannelAsync: private::TxChannelInternal {
/// Start transmitting the given pulse code sequence.
/// The length of sequence cannot exceed the size of the allocated RMT
/// RAM.
@@ -948,7 +1202,7 @@ pub mod asynch {
}
}
- pub trait RxChannelAsync: private::RxChannelInternal {
+ pub trait RxChannelAsync: private::RxChannelInternal {
/// Start receiving a pulse code sequence.
/// The length of sequence cannot exceed the size of the allocated RMT
/// RAM.
@@ -988,49 +1242,48 @@ pub mod asynch {
}
#[cfg(not(any(esp32, esp32s2)))]
- #[interrupt]
- fn RMT() {
+ #[handler]
+ pub(super) fn async_interrupt_handler() {
if let Some(channel) = super::chip_specific::pending_interrupt_for_channel() {
use crate::rmt::private::{RxChannelInternal, TxChannelInternal};
match channel {
0 => {
- super::Channel::<0>::unlisten_interrupt(Event::End);
- super::Channel::<0>::unlisten_interrupt(Event::Error);
+ super::Channel::::unlisten_interrupt(Event::End);
+ super::Channel::::unlisten_interrupt(Event::Error);
}
1 => {
- super::Channel::<1>::unlisten_interrupt(Event::End);
- super::Channel::<1>::unlisten_interrupt(Event::Error);
+ super::Channel::::unlisten_interrupt(Event::End);
+ super::Channel::::unlisten_interrupt(Event::Error);
}
2 => {
- super::Channel::<2>::unlisten_interrupt(Event::End);
- super::Channel::<2>::unlisten_interrupt(Event::Error);
+ super::Channel::::unlisten_interrupt(Event::End);
+ super::Channel::::unlisten_interrupt(Event::Error);
}
3 => {
- super::Channel::<3>::unlisten_interrupt(Event::End);
- super::Channel::<3>::unlisten_interrupt(Event::Error);
+ super::Channel::::unlisten_interrupt(Event::End);
+ super::Channel::::unlisten_interrupt(Event::Error);
}
- // TODO ... how to handle chips which can use a channel for tx AND rx?
#[cfg(any(esp32, esp32s3))]
4 => {
- super::Channel::<4>::unlisten_interrupt(Event::End);
- super::Channel::<4>::unlisten_interrupt(Event::Error);
+ super::Channel::::unlisten_interrupt(Event::End);
+ super::Channel::::unlisten_interrupt(Event::Error);
}
#[cfg(any(esp32, esp32s3))]
5 => {
- super::Channel::<5>::unlisten_interrupt(Event::End);
- super::Channel::<5>::unlisten_interrupt(Event::Error);
+ super::Channel::::unlisten_interrupt(Event::End);
+ super::Channel::::unlisten_interrupt(Event::Error);
}
#[cfg(any(esp32, esp32s3))]
6 => {
- super::Channel::<6>::unlisten_interrupt(Event::End);
- super::Channel::<6>::unlisten_interrupt(Event::Error);
+ super::Channel::::unlisten_interrupt(Event::End);
+ super::Channel::::unlisten_interrupt(Event::Error);
}
#[cfg(any(esp32, esp32s3))]
7 => {
- super::Channel::<7>::unlisten_interrupt(Event::End);
- super::Channel::<7>::unlisten_interrupt(Event::Error);
+ super::Channel::::unlisten_interrupt(Event::End);
+ super::Channel::::unlisten_interrupt(Event::Error);
}
_ => unreachable!(),
@@ -1041,123 +1294,123 @@ pub mod asynch {
}
#[cfg(any(esp32, esp32s2))]
- #[interrupt]
- fn RMT() {
+ #[handler]
+ pub(super) fn async_interrupt_handler() {
if let Some(channel) = super::chip_specific::pending_interrupt_for_channel() {
match channel {
0 => {
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::Error,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::Error,
);
}
1 => {
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::Error,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::Error,
);
}
2 => {
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::Error,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::Error,
);
}
3 => {
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::Error,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::Error,
);
}
#[cfg(esp32)]
4 => {
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::Error,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::Error,
);
}
#[cfg(any(esp32, esp32s3))]
5 => {
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::Error,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::Error,
);
}
#[cfg(any(esp32, esp32s3))]
6 => {
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::Error,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::Error,
);
}
#[cfg(any(esp32, esp32s3))]
7 => {
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::TxChannelInternal>::unlisten_interrupt(
+ as super::private::TxChannelInternal>::unlisten_interrupt(
Event::Error,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::End,
);
- as super::private::RxChannelInternal>::unlisten_interrupt(
+ as super::private::RxChannelInternal>::unlisten_interrupt(
Event::Error,
);
}
@@ -1183,7 +1436,10 @@ mod private {
fn create(peripheral: impl Peripheral + 'd) -> Self;
}
- pub trait TxChannelInternal {
+ pub trait TxChannelInternal
+ where
+ M: crate::Mode,
+ {
const CHANNEL: u8;
fn new() -> Self;
@@ -1261,7 +1517,10 @@ mod private {
fn unlisten_interrupt(event: Event);
}
- pub trait RxChannelInternal {
+ pub trait RxChannelInternal
+ where
+ M: crate::Mode,
+ {
const CHANNEL: u8;
fn new() -> Self;
@@ -1396,11 +1655,13 @@ mod chip_specific {
macro_rules! impl_tx_channel {
($channel:ident, $signal:ident, $ch_num:literal) => {
paste::paste! {
- impl $crate::rmt::private::TxChannelInternal for $crate::rmt::$channel<$ch_num> {
+ impl $crate::rmt::private::TxChannelInternal for $crate::rmt::$channel where M: $crate::Mode {
const CHANNEL: u8 = $ch_num;
fn new() -> Self {
- Self {}
+ Self {
+ phantom: core::marker::PhantomData,
+ }
}
fn output_signal() -> crate::gpio::OutputSignal {
@@ -1587,11 +1848,13 @@ mod chip_specific {
macro_rules! impl_rx_channel {
($channel:ident, $signal:ident, $ch_num:literal, $ch_index:literal) => {
paste::paste! {
- impl $crate::rmt::private::RxChannelInternal for $crate::rmt::$channel<$ch_num> {
+ impl $crate::rmt::private::RxChannelInternal for $crate::rmt::$channel where M: $crate::Mode {
const CHANNEL: u8 = $ch_num;
fn new() -> Self {
- Self {}
+ Self {
+ phantom: core::marker::PhantomData,
+ }
}
fn input_signal() -> crate::gpio::InputSignal {
@@ -1801,11 +2064,13 @@ mod chip_specific {
macro_rules! impl_tx_channel {
($channel:ident, $signal:ident, $ch_num:literal) => {
paste::paste! {
- impl super::private::TxChannelInternal for super::$channel<$ch_num> {
+ impl super::private::TxChannelInternal for super::$channel where M: $crate::Mode {
const CHANNEL: u8 = $ch_num;
fn new() -> Self {
- Self {}
+ Self {
+ phantom: core::marker::PhantomData,
+ }
}
fn output_signal() -> crate::gpio::OutputSignal {
@@ -1972,11 +2237,13 @@ mod chip_specific {
macro_rules! impl_rx_channel {
($channel:ident, $signal:ident, $ch_num:literal) => {
paste::paste! {
- impl super::private::RxChannelInternal for super::$channel<$ch_num> {
+ impl super::private::RxChannelInternal for super::$channel where M: $crate::Mode {
const CHANNEL: u8 = $ch_num;
fn new() -> Self {
- Self {}
+ Self {
+ phantom: core::marker::PhantomData,
+ }
}
fn input_signal() -> crate::gpio::InputSignal {
diff --git a/esp-hal/src/soc/esp32/mod.rs b/esp-hal/src/soc/esp32/mod.rs
index d9e1b5916..e065a5a6d 100644
--- a/esp-hal/src/soc/esp32/mod.rs
+++ b/esp-hal/src/soc/esp32/mod.rs
@@ -76,6 +76,8 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
stack_chk_guard.write_volatile(0xdeadbabe);
}
+ crate::interrupt::setup_interrupts();
+
// continue with default reset handler
xtensa_lx_rt::Reset();
}
diff --git a/esp-hal/src/soc/esp32s2/mod.rs b/esp-hal/src/soc/esp32s2/mod.rs
index a54650347..94649c2d9 100644
--- a/esp-hal/src/soc/esp32s2/mod.rs
+++ b/esp-hal/src/soc/esp32s2/mod.rs
@@ -80,6 +80,8 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
stack_chk_guard.write_volatile(0xdeadbabe);
}
+ crate::interrupt::setup_interrupts();
+
// continue with default reset handler
xtensa_lx_rt::Reset();
}
diff --git a/esp-hal/src/soc/esp32s3/mod.rs b/esp-hal/src/soc/esp32s3/mod.rs
index 5dc5918fc..b2bef618e 100644
--- a/esp-hal/src/soc/esp32s3/mod.rs
+++ b/esp-hal/src/soc/esp32s3/mod.rs
@@ -115,6 +115,8 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
stack_chk_guard.write_volatile(0xdeadbabe);
}
+ crate::interrupt::setup_interrupts();
+
// continue with default reset handler
xtensa_lx_rt::Reset();
}
diff --git a/examples/src/bin/embassy_rmt_rx.rs b/examples/src/bin/embassy_rmt_rx.rs
index 7b61478b7..d5e6637e8 100644
--- a/examples/src/bin/embassy_rmt_rx.rs
+++ b/examples/src/bin/embassy_rmt_rx.rs
@@ -18,7 +18,7 @@ use esp_hal::{
gpio::{Gpio5, Output, PushPull, IO},
peripherals::Peripherals,
prelude::*,
- rmt::{asynch::RxChannelAsync, PulseCode, Rmt, RxChannelConfig, RxChannelCreator},
+ rmt::{asynch::RxChannelAsync, PulseCode, Rmt, RxChannelConfig, RxChannelCreatorAsync},
};
use esp_println::{print, println};
@@ -58,7 +58,7 @@ async fn main(spawner: Spawner) {
}
};
- let rmt = Rmt::new(peripherals.RMT, freq, &clocks).unwrap();
+ let rmt = Rmt::new_async(peripherals.RMT, freq, &clocks).unwrap();
let rx_config = RxChannelConfig {
clk_divider: 255,
idle_threshold: 10000,
diff --git a/examples/src/bin/embassy_rmt_tx.rs b/examples/src/bin/embassy_rmt_tx.rs
index 9cd84873a..ded064cb9 100644
--- a/examples/src/bin/embassy_rmt_tx.rs
+++ b/examples/src/bin/embassy_rmt_tx.rs
@@ -18,7 +18,7 @@ use esp_hal::{
gpio::IO,
peripherals::Peripherals,
prelude::*,
- rmt::{asynch::TxChannelAsync, PulseCode, Rmt, TxChannelConfig, TxChannelCreator},
+ rmt::{asynch::TxChannelAsync, PulseCode, Rmt, TxChannelConfig, TxChannelCreatorAsync},
timer::TimerGroup,
};
use esp_println::println;
@@ -43,7 +43,7 @@ async fn main(_spawner: Spawner) {
}
};
- let rmt = Rmt::new(peripherals.RMT, freq, &clocks).unwrap();
+ let rmt = Rmt::new_async(peripherals.RMT, freq, &clocks).unwrap();
let mut channel = rmt
.channel0
diff --git a/examples/src/bin/hello_rgb.rs b/examples/src/bin/hello_rgb.rs
index 96e817e21..20ba84e88 100644
--- a/examples/src/bin/hello_rgb.rs
+++ b/examples/src/bin/hello_rgb.rs
@@ -56,9 +56,9 @@ fn main() -> ! {
// Configure RMT peripheral globally
#[cfg(not(feature = "esp32h2"))]
- let rmt = Rmt::new(peripherals.RMT, 80.MHz(), &clocks).unwrap();
+ let rmt = Rmt::new(peripherals.RMT, 80.MHz(), &clocks, None).unwrap();
#[cfg(feature = "esp32h2")]
- let rmt = Rmt::new(peripherals.RMT, 32.MHz(), &clocks).unwrap();
+ let rmt = Rmt::new(peripherals.RMT, 32.MHz(), &clocks, None).unwrap();
// We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can
// be used directly with all `smart_led` implementations
diff --git a/examples/src/bin/rmt_rx.rs b/examples/src/bin/rmt_rx.rs
index 69e1123ad..ab2292134 100644
--- a/examples/src/bin/rmt_rx.rs
+++ b/examples/src/bin/rmt_rx.rs
@@ -38,7 +38,7 @@ fn main() -> ! {
}
};
- let rmt = Rmt::new(peripherals.RMT, freq, &clocks).unwrap();
+ let rmt = Rmt::new(peripherals.RMT, freq, &clocks, None).unwrap();
let rx_config = RxChannelConfig {
clk_divider: 1,
diff --git a/examples/src/bin/rmt_tx.rs b/examples/src/bin/rmt_tx.rs
index 284324acd..8b267ac3f 100644
--- a/examples/src/bin/rmt_tx.rs
+++ b/examples/src/bin/rmt_tx.rs
@@ -33,7 +33,7 @@ fn main() -> ! {
}
};
- let rmt = Rmt::new(peripherals.RMT, freq, &clocks).unwrap();
+ let rmt = Rmt::new(peripherals.RMT, freq, &clocks, None).unwrap();
let tx_config = TxChannelConfig {
clk_divider: 255,