RMT: allow driver to init as blocking or async (#1341)
* RMT: allow driver to init as blocking or async * CHANGELOG and minor fixes
This commit is contained in:
parent
d761ec4def
commit
fd4f5592a4
@ -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()
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user