Timers runtime isr binding (#1348)

* Runtime ISR binding for TIMG/SYSTIMER

* CHANGELOG.md

* Implement `set_interrupt_handler` only for blocking

* Adapt HIL test
This commit is contained in:
Björn Quentin 2024-04-03 10:14:27 +02:00 committed by GitHub
parent 81a40703bd
commit 256d7198f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 612 additions and 215 deletions

View File

@ -49,6 +49,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Runtime ISR binding for SHA,ECC and RSA (#1354)
- Runtime ISR binding for I2C (#1376)
- `UsbSerialJtag` can be created in async or blocking mode. The blocking constructor takes an optional interrupt handler argument (#1377)
- SYSTIMER and TIMG instances can now be created in async or blocking mode. The blocking constructor takes an optional argument to set interrupt handlers. The constructors are named `create`/`create_async` (#1348)
- SYSTIMER and TIMG instances can now be created in async or blocking mode (#1348)
### Removed

View File

@ -1,4 +1,5 @@
use critical_section::{CriticalSection, Mutex};
use procmacros::handler;
use super::AlarmState;
use crate::{
@ -9,22 +10,22 @@ use crate::{
pub const ALARM_COUNT: usize = 3;
pub type TimerType = SystemTimer<'static>;
pub type TimerType = SystemTimer<'static, crate::Async>;
pub struct EmbassyTimer {
pub(crate) alarms: Mutex<[AlarmState; ALARM_COUNT]>,
pub(crate) alarm0: Alarm<Target, 0>,
pub(crate) alarm1: Alarm<Target, 1>,
pub(crate) alarm2: Alarm<Target, 2>,
pub(crate) alarm0: Alarm<Target, crate::Async, 0>,
pub(crate) alarm1: Alarm<Target, crate::Async, 1>,
pub(crate) alarm2: Alarm<Target, crate::Async, 2>,
}
const ALARM_STATE_NONE: AlarmState = AlarmState::new();
embassy_time_driver::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer {
alarms: Mutex::new([ALARM_STATE_NONE; ALARM_COUNT]),
alarm0: unsafe { Alarm::<_, 0>::conjure() },
alarm1: unsafe { Alarm::<_, 1>::conjure() },
alarm2: unsafe { Alarm::<_, 2>::conjure() },
alarm0: unsafe { Alarm::<_, crate::Async, 0>::conjure() },
alarm1: unsafe { Alarm::<_, crate::Async, 1>::conjure() },
alarm2: unsafe { Alarm::<_, crate::Async, 2>::conjure() },
});
impl EmbassyTimer {
@ -42,9 +43,9 @@ impl EmbassyTimer {
pub(super) fn on_alarm_allocated(&self, n: usize) {
match n {
0 => self.alarm0.enable_interrupt(true),
1 => self.alarm1.enable_interrupt(true),
2 => self.alarm2.enable_interrupt(true),
0 => self.alarm0.enable_interrupt_internal(true),
1 => self.alarm1.enable_interrupt_internal(true),
2 => self.alarm2.enable_interrupt_internal(true),
_ => {}
}
}
@ -57,31 +58,47 @@ impl EmbassyTimer {
}
pub fn init(_clocks: &Clocks, _systimer: TimerType) {
use crate::{interrupt, interrupt::Priority, macros::interrupt};
unsafe {
crate::interrupt::bind_interrupt(
peripherals::Interrupt::SYSTIMER_TARGET0,
target0_handler.handler(),
);
unwrap!(crate::interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET0,
target0_handler.priority()
));
unwrap!(interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET0,
Priority::max()
));
unwrap!(interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET1,
Priority::max()
));
unwrap!(interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET2,
Priority::max()
));
crate::interrupt::bind_interrupt(
peripherals::Interrupt::SYSTIMER_TARGET1,
target1_handler.handler(),
);
unwrap!(crate::interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET1,
target1_handler.priority()
));
#[interrupt]
fn SYSTIMER_TARGET0() {
crate::interrupt::bind_interrupt(
peripherals::Interrupt::SYSTIMER_TARGET2,
target2_handler.handler(),
);
unwrap!(crate::interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET2,
target2_handler.priority()
));
}
#[handler]
fn target0_handler() {
DRIVER.on_interrupt(0);
}
#[interrupt]
fn SYSTIMER_TARGET1() {
#[handler]
fn target1_handler() {
DRIVER.on_interrupt(1);
}
#[interrupt]
fn SYSTIMER_TARGET2() {
#[handler]
fn target2_handler() {
DRIVER.on_interrupt(2);
}
}
@ -109,9 +126,9 @@ impl EmbassyTimer {
fn clear_interrupt(&self, id: usize) {
match id {
0 => self.alarm0.clear_interrupt(),
1 => self.alarm1.clear_interrupt(),
2 => self.alarm2.clear_interrupt(),
0 => self.alarm0.clear_interrupt_internal(),
1 => self.alarm1.clear_interrupt_internal(),
2 => self.alarm2.clear_interrupt_internal(),
_ => {}
}
}

View File

@ -16,7 +16,7 @@ pub const ALARM_COUNT: usize = 1;
#[cfg(any(esp32, esp32s2, esp32s3))]
pub const ALARM_COUNT: usize = 2;
pub type TimerType = TimerGroup<'static, TIMG0>;
pub type TimerType = TimerGroup<'static, TIMG0, crate::Async>;
pub struct EmbassyTimer {
pub(crate) alarms: Mutex<[AlarmState; ALARM_COUNT]>,
@ -51,8 +51,6 @@ impl EmbassyTimer {
}
pub fn init(clocks: &Clocks, mut timer: TimerType) {
use crate::{interrupt, interrupt::Priority};
// set divider to get a 1mhz clock. APB (80mhz) / 80 = 1mhz...
// TODO: assert APB clock is the source and its at the correct speed for the
// divider
@ -65,25 +63,39 @@ impl EmbassyTimer {
timer.timer1.set_counter_active(true);
}
unwrap!(interrupt::enable(
peripherals::Interrupt::TG0_T0_LEVEL,
Priority::max()
));
unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::TG0_T0_LEVEL,
tg0_t0_level.handler(),
);
crate::interrupt::enable(
crate::peripherals::Interrupt::TG0_T0_LEVEL,
tg0_t0_level.priority(),
)
.unwrap();
}
#[cfg(any(esp32, esp32s2, esp32s3))]
unwrap!(interrupt::enable(
peripherals::Interrupt::TG0_T1_LEVEL,
Priority::max()
));
unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::TG0_T1_LEVEL,
tg0_t1_level.handler(),
);
crate::interrupt::enable(
crate::peripherals::Interrupt::TG0_T1_LEVEL,
tg0_t1_level.priority(),
)
.unwrap();
}
#[interrupt]
fn TG0_T0_LEVEL() {
#[handler(priority = crate::interrupt::Priority::max())]
fn tg0_t0_level() {
let timer = unsafe { Timer0::<TIMG0>::steal() };
DRIVER.on_interrupt(0, timer);
}
#[cfg(any(esp32, esp32s2, esp32s3))]
#[interrupt]
fn TG0_T1_LEVEL() {
#[handler(priority = crate::interrupt::Priority::max())]
fn tg0_t1_level() {
let timer = unsafe { Timer1::<TIMG0>::steal() };
DRIVER.on_interrupt(1, timer);
}

View File

@ -96,6 +96,6 @@ unsafe fn post_init() {
let mut rtc = Rtc::new(LPWR::steal());
rtc.rwdt.disable();
Wdt::<TIMG0>::set_wdt_enabled(false);
Wdt::<TIMG1>::set_wdt_enabled(false);
Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Wdt::<TIMG1, crate::Blocking>::set_wdt_enabled(false);
}

View File

@ -31,5 +31,5 @@ unsafe fn post_init() {
rtc.swd.disable();
rtc.rwdt.disable();
Wdt::<TIMG0>::set_wdt_enabled(false);
Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
}

View File

@ -43,6 +43,6 @@ unsafe fn post_init() {
rtc.swd.disable();
rtc.rwdt.disable();
Wdt::<TIMG0>::set_wdt_enabled(false);
Wdt::<TIMG1>::set_wdt_enabled(false);
Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Wdt::<TIMG1, crate::Blocking>::set_wdt_enabled(false);
}

View File

@ -49,6 +49,6 @@ unsafe fn post_init() {
rtc.swd.disable();
rtc.rwdt.disable();
Wdt::<TIMG0>::set_wdt_enabled(false);
Wdt::<TIMG1>::set_wdt_enabled(false);
Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Wdt::<TIMG1, crate::Blocking>::set_wdt_enabled(false);
}

View File

@ -48,6 +48,6 @@ unsafe fn post_init() {
rtc.swd.disable();
rtc.rwdt.disable();
Wdt::<TIMG0>::set_wdt_enabled(false);
Wdt::<TIMG1>::set_wdt_enabled(false);
Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Wdt::<TIMG1, crate::Blocking>::set_wdt_enabled(false);
}

View File

@ -100,6 +100,6 @@ unsafe fn post_init() {
let mut rtc = Rtc::new(LPWR::steal());
rtc.rwdt.disable();
Wdt::<TIMG0>::set_wdt_enabled(false);
Wdt::<TIMG1>::set_wdt_enabled(false);
Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Wdt::<TIMG1, crate::Blocking>::set_wdt_enabled(false);
}

View File

@ -134,6 +134,6 @@ unsafe fn post_init() {
let mut rtc = Rtc::new(LPWR::steal());
rtc.rwdt.disable();
Wdt::<TIMG0>::set_wdt_enabled(false);
Wdt::<TIMG1>::set_wdt_enabled(false);
Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Wdt::<TIMG1, crate::Blocking>::set_wdt_enabled(false);
}

View File

@ -31,7 +31,8 @@ use core::{marker::PhantomData, mem::transmute};
use fugit::MicrosDurationU32;
use crate::{
peripheral::{Peripheral, PeripheralRef},
interrupt::InterruptHandler,
peripheral::Peripheral,
peripherals::{
generic::Reg,
systimer::{
@ -45,42 +46,45 @@ use crate::{
// TODO this only handles unit0 of the systimer
pub struct SystemTimer<'d> {
_inner: PeripheralRef<'d, SYSTIMER>,
pub alarm0: Alarm<Target, 0>,
pub alarm1: Alarm<Target, 1>,
pub alarm2: Alarm<Target, 2>,
/// The SystemTimer
pub struct SystemTimer<'d, DM: crate::Mode> {
pub alarm0: Alarm<Target, DM, 0>,
pub alarm1: Alarm<Target, DM, 1>,
pub alarm2: Alarm<Target, DM, 2>,
_phantom: &'d PhantomData<()>,
}
impl<'d> SystemTimer<'d> {
impl<'d> SystemTimer<'d, crate::Blocking> {
/// Bitmask to be applied to the raw register value
#[cfg(esp32s2)]
pub const BIT_MASK: u64 = u64::MAX;
#[cfg(not(esp32s2))]
pub const BIT_MASK: u64 = 0xF_FFFF_FFFF_FFFF;
/// The ticks per second the underlying peripheral uses
#[cfg(esp32s2)]
pub const TICKS_PER_SECOND: u64 = 80_000_000; // TODO this can change when we have support for changing APB frequency
#[cfg(not(esp32s2))]
pub const TICKS_PER_SECOND: u64 = 16_000_000;
pub fn new(p: impl Peripheral<P = SYSTIMER> + 'd) -> Self {
crate::into_ref!(p);
/// Create a new instance in [crate::Blocking] mode.
pub fn new(_p: impl Peripheral<P = SYSTIMER> + 'd) -> Self {
#[cfg(soc_etm)]
etm::enable_etm();
Self {
_inner: p,
alarm0: Alarm::new(),
alarm1: Alarm::new(),
alarm2: Alarm::new(),
_phantom: &PhantomData,
}
}
// TODO use fugit types
/// Get the current count of the system-timer.
pub fn now() -> u64 {
// This should be safe to access from multiple contexts
// worst case scenario the second accesor ends up reading
// worst case scenario the second accessor ends up reading
// an older time stamp
let systimer = unsafe { &*SYSTIMER::ptr() };
systimer
@ -101,43 +105,41 @@ impl<'d> SystemTimer<'d> {
}
}
impl<'d> SystemTimer<'d, crate::Async> {
/// Create a new instance in [crate::Async] mode.
pub fn new_async(_p: impl Peripheral<P = SYSTIMER> + 'd) -> Self {
#[cfg(soc_etm)]
etm::enable_etm();
Self {
alarm0: Alarm::new(),
alarm1: Alarm::new(),
alarm2: Alarm::new(),
_phantom: &PhantomData,
}
}
}
/// A marker for a [Alarm] in target mode.
#[derive(Debug)]
pub struct Target;
/// A marker for a [Alarm] in periodic mode.
#[derive(Debug)]
pub struct Periodic; // TODO, also impl e-h timer traits
/// A single alarm.
#[derive(Debug)]
pub struct Alarm<MODE, const CHANNEL: u8> {
_pd: PhantomData<MODE>,
pub struct Alarm<MODE, DM: crate::Mode, const CHANNEL: u8> {
_pd: PhantomData<(MODE, DM)>,
}
impl<T, const CHANNEL: u8> Alarm<T, CHANNEL> {
impl<T, DM: crate::Mode, const CHANNEL: u8> Alarm<T, DM, CHANNEL> {
// private constructor
fn new() -> Self {
Self { _pd: PhantomData }
}
pub fn enable_interrupt(&self, val: bool) {
let systimer = unsafe { &*SYSTIMER::ptr() };
match CHANNEL {
0 => systimer.int_ena().modify(|_, w| w.target0().bit(val)),
1 => systimer.int_ena().modify(|_, w| w.target1().bit(val)),
2 => systimer.int_ena().modify(|_, w| w.target2().bit(val)),
_ => unreachable!(),
}
}
pub fn clear_interrupt(&self) {
let systimer = unsafe { &*SYSTIMER::ptr() };
match CHANNEL {
0 => systimer.int_clr().write(|w| w.target0().clear_bit_by_one()),
1 => systimer.int_clr().write(|w| w.target1().clear_bit_by_one()),
2 => systimer.int_clr().write(|w| w.target2().clear_bit_by_one()),
_ => unreachable!(),
}
}
fn configure(
&self,
conf: impl FnOnce(&Reg<TARGET0_CONF_SPEC>, &Reg<TARGET0_HI_SPEC>, &Reg<TARGET0_LO_SPEC>),
@ -212,9 +214,78 @@ impl<T, const CHANNEL: u8> Alarm<T, CHANNEL> {
});
}
}
pub(crate) fn enable_interrupt_internal(&self, val: bool) {
let systimer = unsafe { &*SYSTIMER::ptr() };
match CHANNEL {
0 => systimer.int_ena().modify(|_, w| w.target0().bit(val)),
1 => systimer.int_ena().modify(|_, w| w.target1().bit(val)),
2 => systimer.int_ena().modify(|_, w| w.target2().bit(val)),
_ => unreachable!(),
}
}
pub(crate) fn clear_interrupt_internal(&self) {
let systimer = unsafe { &*SYSTIMER::ptr() };
match CHANNEL {
0 => systimer.int_clr().write(|w| w.target0().clear_bit_by_one()),
1 => systimer.int_clr().write(|w| w.target1().clear_bit_by_one()),
2 => systimer.int_clr().write(|w| w.target2().clear_bit_by_one()),
_ => unreachable!(),
}
}
}
impl<const CHANNEL: u8> Alarm<Target, CHANNEL> {
impl<T, const CHANNEL: u8> Alarm<T, crate::Blocking, CHANNEL> {
/// Set the interrupt handler for this alarm.
pub fn set_interrupt_handler(&self, handler: InterruptHandler) {
match CHANNEL {
0 => unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::SYSTIMER_TARGET0,
handler.handler(),
);
unwrap!(crate::interrupt::enable(
crate::peripherals::Interrupt::SYSTIMER_TARGET0,
handler.priority(),
));
},
1 => unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::SYSTIMER_TARGET1,
handler.handler(),
);
unwrap!(crate::interrupt::enable(
crate::peripherals::Interrupt::SYSTIMER_TARGET1,
handler.priority(),
));
},
2 => unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::SYSTIMER_TARGET2,
handler.handler(),
);
unwrap!(crate::interrupt::enable(
crate::peripherals::Interrupt::SYSTIMER_TARGET2,
handler.priority(),
));
},
_ => unreachable!(),
}
}
/// Enable the interrupt for this alarm.
pub fn enable_interrupt(&self, val: bool) {
self.enable_interrupt_internal(val);
}
/// Enable the interrupt pending status for this alarm.
pub fn clear_interrupt(&self) {
self.clear_interrupt_internal();
}
}
impl<DM: crate::Mode, const CHANNEL: u8> Alarm<Target, DM, CHANNEL> {
/// Set the target value of this [Alarm]
pub fn set_target(&self, timestamp: u64) {
self.configure(|tconf, hi, lo| unsafe {
tconf.write(|w| w.target0_period_mode().clear_bit()); // target mode
@ -223,12 +294,14 @@ impl<const CHANNEL: u8> Alarm<Target, CHANNEL> {
})
}
pub fn into_periodic(self) -> Alarm<Periodic, CHANNEL> {
/// Converts this [Alarm] into [Periodic] mode
pub fn into_periodic(self) -> Alarm<Periodic, DM, CHANNEL> {
Alarm { _pd: PhantomData }
}
}
impl<const CHANNEL: u8> Alarm<Periodic, CHANNEL> {
impl<DM: crate::Mode, const CHANNEL: u8> Alarm<Periodic, DM, CHANNEL> {
/// Set the period of this [Alarm]
pub fn set_period(&self, period: MicrosDurationU32) {
let us = period.ticks();
let ticks = us * (SystemTimer::TICKS_PER_SECOND / 1_000_000) as u32;
@ -245,12 +318,13 @@ impl<const CHANNEL: u8> Alarm<Periodic, CHANNEL> {
});
}
pub fn into_target(self) -> Alarm<Target, CHANNEL> {
/// Converts this [Alarm] into [Target] mode
pub fn into_target(self) -> Alarm<Target, DM, CHANNEL> {
Alarm { _pd: PhantomData }
}
}
impl<T> Alarm<T, 0> {
impl<T, DM: crate::Mode> Alarm<T, DM, 0> {
/// Conjure an alarm out of thin air.
///
/// # Safety
@ -262,7 +336,7 @@ impl<T> Alarm<T, 0> {
}
}
impl<T> Alarm<T, 1> {
impl<T, DM: crate::Mode> Alarm<T, DM, 1> {
/// Conjure an alarm out of thin air.
///
/// # Safety
@ -274,7 +348,7 @@ impl<T> Alarm<T, 1> {
}
}
impl<T> Alarm<T, 2> {
impl<T, DM: crate::Mode> Alarm<T, DM, 2> {
/// Conjure an alarm out of thin air.
///
/// # Safety
@ -286,13 +360,8 @@ impl<T> Alarm<T, 2> {
}
}
// FIXME: The `embedded_hal_async::delay::DelayUs` trait implementation
// interferes with the embassy time driver, which also uses the
// `SYSTIMER` peripheral. Until we come up with a solution, do not
// implement this trait if the `embassy-time-systick` feature is enabled.
// #[cfg(all(feature = "async", not(feature = "embassy-time-systick")))]
// HACK: disable `asynch` module *always* until we come up with a solution
#[cfg(not(systimer))]
// Async functionality of the system timer.
#[cfg(feature = "async")]
mod asynch {
use core::{
pin::Pin,
@ -300,7 +369,7 @@ mod asynch {
};
use embassy_sync::waitqueue::AtomicWaker;
use procmacros::interrupt;
use procmacros::handler;
use super::*;
@ -310,13 +379,34 @@ mod asynch {
static WAKERS: [AtomicWaker; NUM_ALARMS] = [INIT; NUM_ALARMS];
pub(crate) struct AlarmFuture<'a, const N: u8> {
phantom: PhantomData<&'a Alarm<Periodic, N>>,
phantom: PhantomData<&'a Alarm<Periodic, crate::Async, N>>,
}
impl<'a, const N: u8> AlarmFuture<'a, N> {
pub(crate) fn new(alarm: &'a Alarm<Periodic, N>) -> Self {
alarm.clear_interrupt();
alarm.enable_interrupt(true);
pub(crate) fn new(alarm: &'a Alarm<Periodic, crate::Async, N>) -> Self {
alarm.clear_interrupt_internal();
let (interrupt, handler) = match N {
0 => (
crate::peripherals::Interrupt::SYSTIMER_TARGET0,
target0_handler,
),
1 => (
crate::peripherals::Interrupt::SYSTIMER_TARGET1,
target1_handler,
),
_ => (
crate::peripherals::Interrupt::SYSTIMER_TARGET2,
target2_handler,
),
};
unsafe {
crate::interrupt::bind_interrupt(interrupt, handler.handler());
crate::interrupt::enable(interrupt, handler.priority()).unwrap();
}
alarm.enable_interrupt_internal(true);
Self {
phantom: PhantomData,
@ -325,7 +415,7 @@ mod asynch {
fn event_bit_is_clear(&self) -> bool {
let r = unsafe { &*crate::peripherals::SYSTIMER::PTR }
.int_ena
.int_ena()
.read();
match N {
@ -351,9 +441,11 @@ mod asynch {
}
}
impl<const CHANNEL: u8> embedded_hal_async::delay::DelayUs for Alarm<Periodic, CHANNEL> {
async fn delay_us(&mut self, us: u32) {
let period = MicrosDurationU32::from_ticks(us);
impl<const CHANNEL: u8> embedded_hal_async::delay::DelayNs
for Alarm<Periodic, crate::Async, CHANNEL>
{
async fn delay_ns(&mut self, ns: u32) {
let period = MicrosDurationU32::from_ticks(ns / 1000);
self.set_period(period);
AlarmFuture::new(self).await;
@ -366,28 +458,28 @@ mod asynch {
}
}
#[interrupt]
fn SYSTIMER_TARGET0() {
#[handler]
fn target0_handler() {
unsafe { &*crate::peripherals::SYSTIMER::PTR }
.int_ena
.int_ena()
.modify(|_, w| w.target0().clear_bit());
WAKERS[0].wake();
}
#[interrupt]
fn SYSTIMER_TARGET1() {
#[handler]
fn target1_handler() {
unsafe { &*crate::peripherals::SYSTIMER::PTR }
.int_ena
.int_ena()
.modify(|_, w| w.target1().clear_bit());
WAKERS[1].wake();
}
#[interrupt]
fn SYSTIMER_TARGET2() {
#[handler]
fn target2_handler() {
unsafe { &*crate::peripherals::SYSTIMER::PTR }
.int_ena
.int_ena()
.modify(|_, w| w.target2().clear_bit());
WAKERS[2].wake();
@ -420,26 +512,29 @@ pub mod etm {
use super::*;
/// An ETM controlled SYSTIMER event
pub struct SysTimerEtmEvent<'a, M, const N: u8> {
alarm: &'a mut Alarm<M, N>,
pub struct SysTimerEtmEvent<'a, M, DM: crate::Mode, const N: u8> {
alarm: &'a mut Alarm<M, DM, N>,
}
impl<'a, M, const N: u8> SysTimerEtmEvent<'a, M, N> {
impl<'a, M, DM: crate::Mode, const N: u8> SysTimerEtmEvent<'a, M, DM, N> {
/// Creates an ETM event from the given [Alarm]
pub fn new(alarm: &'a mut Alarm<M, N>) -> Self {
pub fn new(alarm: &'a mut Alarm<M, DM, N>) -> Self {
Self { alarm }
}
/// Execute closure f with mutable access to the wrapped [Alarm].
pub fn with<R>(&self, f: impl FnOnce(&&'a mut Alarm<M, N>) -> R) -> R {
pub fn with<R>(&self, f: impl FnOnce(&&'a mut Alarm<M, DM, N>) -> R) -> R {
let alarm = &self.alarm;
f(alarm)
}
}
impl<'a, M, const N: u8> crate::private::Sealed for SysTimerEtmEvent<'a, M, N> {}
impl<'a, M, DM: crate::Mode, const N: u8> crate::private::Sealed
for SysTimerEtmEvent<'a, M, DM, N>
{
}
impl<'a, M, const N: u8> crate::etm::EtmEvent for SysTimerEtmEvent<'a, M, N> {
impl<'a, M, DM: crate::Mode, const N: u8> crate::etm::EtmEvent for SysTimerEtmEvent<'a, M, DM, N> {
fn id(&self) -> u8 {
50 + N
}

View File

@ -47,6 +47,7 @@ use crate::peripherals::TIMG1;
use crate::soc::constants::TIMG_DEFAULT_CLK_SRC;
use crate::{
clock::Clocks,
interrupt::InterruptHandler,
peripheral::{Peripheral, PeripheralRef},
peripherals::{timg0::RegisterBlock, TIMG0},
system::PeripheralClockControl,
@ -61,17 +62,32 @@ pub enum Error {
AlarmInactive,
}
/// Interrupts which can be registered in [crate::Blocking] mode
#[derive(Debug, Default)]
pub struct TimerInterrupts {
pub timer0_t0: Option<InterruptHandler>,
pub timer0_t1: Option<InterruptHandler>,
pub timer0_wdt: Option<InterruptHandler>,
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
pub timer1_t0: Option<InterruptHandler>,
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
pub timer1_t1: Option<InterruptHandler>,
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
pub timer1_wdt: Option<InterruptHandler>,
}
// A timergroup consisting of up to 2 timers (chip dependent) and a watchdog
// timer
pub struct TimerGroup<'d, T>
pub struct TimerGroup<'d, T, DM>
where
T: TimerGroupInstance,
DM: crate::Mode,
{
_timer_group: PeripheralRef<'d, T>,
pub timer0: Timer<Timer0<T>>,
pub timer0: Timer<Timer0<T>, DM>,
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
pub timer1: Timer<Timer1<T>>,
pub wdt: Wdt<T>,
pub timer1: Timer<Timer1<T>, DM>,
pub wdt: Wdt<T, DM>,
}
pub trait TimerGroupInstance {
@ -181,11 +197,144 @@ impl TimerGroupInstance for TIMG1 {
}
}
impl<'d, T> TimerGroup<'d, T>
impl<'d, T> TimerGroup<'d, T, crate::Blocking>
where
T: TimerGroupInstance,
{
pub fn new(timer_group: impl Peripheral<P = T> + 'd, clocks: &Clocks) -> Self {
pub fn new(
timer_group: impl Peripheral<P = T> + 'd,
clocks: &Clocks,
isr: Option<TimerInterrupts>,
) -> Self {
crate::into_ref!(timer_group);
T::configure_src_clk();
// ESP32-H2 is using PLL_48M_CLK source instead of APB_CLK
let timer0 = Timer::new(
Timer0 {
phantom: PhantomData,
},
#[cfg(not(esp32h2))]
clocks.apb_clock,
#[cfg(esp32h2)]
clocks.pll_48m_clock,
);
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
let timer1 = Timer::new(
Timer1 {
phantom: PhantomData,
},
clocks.apb_clock,
);
if let Some(isr) = isr {
if let Some(handler) = isr.timer0_t0 {
unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::TG0_T0_LEVEL,
handler.handler(),
);
crate::interrupt::enable(
crate::peripherals::Interrupt::TG0_T0_LEVEL,
handler.priority(),
)
.unwrap();
}
}
#[cfg(any(esp32, esp32s2, esp32s3))]
if let Some(handler) = isr.timer0_t1 {
unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::TG0_T1_LEVEL,
handler.handler(),
);
crate::interrupt::enable(
crate::peripherals::Interrupt::TG0_T1_LEVEL,
handler.priority(),
)
.unwrap();
}
}
if let Some(handler) = isr.timer0_wdt {
unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::TG0_WDT_LEVEL,
handler.handler(),
);
crate::interrupt::enable(
crate::peripherals::Interrupt::TG0_WDT_LEVEL,
handler.priority(),
)
.unwrap();
}
}
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
{
if let Some(handler) = isr.timer1_t0 {
unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::TG1_T0_LEVEL,
handler.handler(),
);
crate::interrupt::enable(
crate::peripherals::Interrupt::TG1_T0_LEVEL,
handler.priority(),
)
.unwrap();
}
}
#[cfg(any(esp32, esp32s2, esp32s3))]
if let Some(handler) = isr.timer1_t1 {
unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::TG1_T1_LEVEL,
handler.handler(),
);
crate::interrupt::enable(
crate::peripherals::Interrupt::TG1_T1_LEVEL,
handler.priority(),
)
.unwrap();
}
}
if let Some(handler) = isr.timer1_wdt {
unsafe {
crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::TG1_WDT_LEVEL,
handler.handler(),
);
crate::interrupt::enable(
crate::peripherals::Interrupt::TG1_WDT_LEVEL,
handler.priority(),
)
.unwrap();
}
}
}
}
Self {
_timer_group: timer_group,
timer0,
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
timer1,
wdt: Wdt::new(),
}
}
}
impl<'d, T> TimerGroup<'d, T, crate::Async>
where
T: TimerGroupInstance,
{
pub fn new_async(timer_group: impl Peripheral<P = T> + 'd, clocks: &Clocks) -> Self {
crate::into_ref!(timer_group);
T::configure_src_clk();
@ -220,12 +369,13 @@ where
}
/// General-purpose Timer driver
pub struct Timer<T> {
pub struct Timer<T, DM: crate::Mode> {
timg: T,
apb_clk_freq: HertzU32,
phantom: PhantomData<DM>,
}
impl<T> Timer<T>
impl<T, DM: crate::Mode> Timer<T, DM>
where
T: Instance,
{
@ -236,7 +386,11 @@ where
timg.enable_peripheral();
Self { timg, apb_clk_freq }
Self {
timg,
apb_clk_freq,
phantom: PhantomData,
}
}
/// Start the timer with the given time period.
@ -278,14 +432,9 @@ where
pub fn wait(&mut self) {
while !self.has_elapsed() {}
}
/// Return the raw interface to the underlying timer instance
pub fn free(self) -> T {
self.timg
}
}
impl<T> Deref for Timer<T>
impl<T, DM: crate::Mode> Deref for Timer<T, DM>
where
T: Instance,
{
@ -296,7 +445,7 @@ where
}
}
impl<T> DerefMut for Timer<T>
impl<T, DM: crate::Mode> DerefMut for Timer<T, DM>
where
T: Instance,
{
@ -531,9 +680,10 @@ where
}
#[cfg(feature = "embedded-hal-02")]
impl<T> embedded_hal_02::timer::CountDown for Timer<T>
impl<T, DM> embedded_hal_02::timer::CountDown for Timer<T, DM>
where
T: Instance,
DM: crate::Mode,
{
type Time = MicrosDurationU64;
@ -554,9 +704,10 @@ where
}
#[cfg(feature = "embedded-hal-02")]
impl<T> embedded_hal_02::timer::Cancel for Timer<T>
impl<T, DM> embedded_hal_02::timer::Cancel for Timer<T, DM>
where
T: Instance,
DM: crate::Mode,
{
type Error = Error;
@ -574,17 +725,23 @@ where
}
#[cfg(feature = "embedded-hal-02")]
impl<T> embedded_hal_02::timer::Periodic for Timer<T> where T: Instance {}
impl<T, DM> embedded_hal_02::timer::Periodic for Timer<T, DM>
where
T: Instance,
DM: crate::Mode,
{
}
/// Watchdog timer
pub struct Wdt<TG> {
phantom: PhantomData<TG>,
pub struct Wdt<TG, DM> {
phantom: PhantomData<(TG, DM)>,
}
/// Watchdog driver
impl<TG> Wdt<TG>
impl<TG, DM> Wdt<TG, DM>
where
TG: TimerGroupInstance,
DM: crate::Mode,
{
/// Create a new watchdog timer instance
pub fn new() -> Self {
@ -697,9 +854,10 @@ where
}
}
impl<TG> Default for Wdt<TG>
impl<TG, DM> Default for Wdt<TG, DM>
where
TG: TimerGroupInstance,
DM: crate::Mode,
{
fn default() -> Self {
Self::new()
@ -707,9 +865,10 @@ where
}
#[cfg(feature = "embedded-hal-02")]
impl<TG> embedded_hal_02::watchdog::WatchdogDisable for Wdt<TG>
impl<TG, DM> embedded_hal_02::watchdog::WatchdogDisable for Wdt<TG, DM>
where
TG: TimerGroupInstance,
DM: crate::Mode,
{
fn disable(&mut self) {
self.disable();
@ -717,9 +876,10 @@ where
}
#[cfg(feature = "embedded-hal-02")]
impl<TG> embedded_hal_02::watchdog::WatchdogEnable for Wdt<TG>
impl<TG, DM> embedded_hal_02::watchdog::WatchdogEnable for Wdt<TG, DM>
where
TG: TimerGroupInstance,
DM: crate::Mode,
{
type Time = MicrosDurationU64;
@ -733,9 +893,10 @@ where
}
#[cfg(feature = "embedded-hal-02")]
impl<TG> embedded_hal_02::watchdog::Watchdog for Wdt<TG>
impl<TG, DM> embedded_hal_02::watchdog::Watchdog for Wdt<TG, DM>
where
TG: TimerGroupInstance,
DM: crate::Mode,
{
fn feed(&mut self) {
self.feed();

View File

@ -63,6 +63,7 @@ embassy = ["esp-hal/embassy"]
embassy-executor-thread = ["esp-hal/embassy-executor-thread"]
embassy-executor-interrupt = ["esp-hal/embassy-executor-interrupt"]
embassy-time-systick-16mhz = ["esp-hal/embassy-time-systick-16mhz"]
embassy-time-timg0 = ["esp-hal/embassy-time-timg0"]
embassy-generic-timers = ["embassy-time/generic-queue-8"]

View File

@ -36,7 +36,7 @@ async fn main(spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
spawner.spawn(run()).ok();

View File

@ -0,0 +1,50 @@
//! embassy hello world systimer
//!
//! This is an example of running the embassy executor with multiple tasks
//! concurrently using the systimer time driver.
//!
//! It's not supported on ESP32, on ESP32-S2 the frequency of the systimer is different (so it's left out here)
//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s3
//% FEATURES: embassy embassy-time-systick-16mhz embassy-executor-thread embassy-generic-timers
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_time::{Duration, Timer};
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
embassy,
peripherals::Peripherals,
prelude::*,
systimer::SystemTimer,
};
#[embassy_executor::task]
async fn run() {
loop {
esp_println::println!("Hello world from embassy using esp-hal-async!");
Timer::after(Duration::from_millis(1_000)).await;
}
}
#[main]
async fn main(spawner: Spawner) {
esp_println::println!("Init!");
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let systimer = SystemTimer::new_async(peripherals.SYSTIMER);
embassy::init(&clocks, systimer);
spawner.spawn(run()).ok();
loop {
esp_println::println!("Bing!");
Timer::after(Duration::from_millis(5_000)).await;
}
}

View File

@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -40,7 +40,7 @@ async fn main(_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -57,7 +57,7 @@ async fn main(_spawner: Spawner) {
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let mut cpu_control = CpuControl::new(system.cpu_control);

View File

@ -92,7 +92,7 @@ fn main() -> ! {
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let mut cpu_control = CpuControl::new(system.cpu_control);

View File

@ -84,7 +84,7 @@ async fn main(low_prio_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let spawner = INT_EXECUTOR_0.start(Priority::Priority2);

View File

@ -33,7 +33,7 @@ async fn main(_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -45,7 +45,7 @@ async fn main(spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timer_group0 = esp_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks);
let timer_group0 = esp_hal::timer::TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timer_group0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -30,7 +30,7 @@ async fn main(_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -80,7 +80,7 @@ async fn main(spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let mut uart0 = Uart::new_async(peripherals.UART0, &clocks);

View File

@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -0,0 +1,42 @@
//! embassy systimer delay
//!
//! This is an example of using the `DelayNs` trait implementation
//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy embassy-time-timg0 embassy-executor-thread embassy-generic-timers async
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embedded_hal_async::delay::DelayNs;
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
embassy,
peripherals::Peripherals,
prelude::*,
systimer::SystemTimer,
timer::TimerGroup,
};
#[main]
async fn main(_spawner: Spawner) {
esp_println::println!("Init!");
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let mut alarm0 = SystemTimer::new_async(peripherals.SYSTIMER)
.alarm0
.into_periodic();
loop {
esp_println::println!("Bing!");
alarm0.delay_ms(1000).await;
}
}

View File

@ -80,7 +80,7 @@ async fn main(spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -71,7 +71,7 @@ async fn main(spawner: Spawner) -> () {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
embassy::init(&clocks, TimerGroup::new(peripherals.TIMG0, &clocks));
embassy::init(&clocks, TimerGroup::new_async(peripherals.TIMG0, &clocks));
let (tx, rx) = UsbSerialJtag::new_async(peripherals.USB_DEVICE).split();

View File

@ -29,7 +29,7 @@ async fn main(_spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -14,18 +14,19 @@ use esp_hal::{
clock::ClockControl,
delay::Delay,
etm::Etm,
interrupt::{self, Priority},
peripherals::{Interrupt, Peripherals, TIMG0},
peripherals::{Peripherals, TIMG0},
prelude::*,
timer::{
etm::{TimerEtmEvents, TimerEtmTasks},
Timer,
Timer0,
TimerGroup,
TimerInterrupts,
},
};
static TIMER0: Mutex<RefCell<Option<Timer<Timer0<TIMG0>>>>> = Mutex::new(RefCell::new(None));
static TIMER0: Mutex<RefCell<Option<Timer<Timer0<TIMG0>, esp_hal::Blocking>>>> =
Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
@ -33,7 +34,14 @@ fn main() -> ! {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new(
peripherals.TIMG0,
&clocks,
Some(TimerInterrupts {
timer0_t0: Some(tg0_t0_level),
..Default::default()
}),
);
let mut timer0 = timg0.timer0;
// Configure ETM to stop timer0 when alarm is triggered
@ -50,14 +58,10 @@ fn main() -> ! {
// 80 / 2 (default divider) timer clock cycles == 1 us
timer0.load_alarm_value(100 * 1_000 * 40);
timer0.set_alarm_active(true);
// Enable interrupt that will be triggered by the alarm
interrupt::enable(Interrupt::TG0_T0_LEVEL, Priority::Priority1).unwrap();
timer0.listen();
timer0.set_counter_active(true);
critical_section::with(|cs| {
timer0.listen();
TIMER0.borrow_ref_mut(cs).replace(timer0);
});
@ -75,8 +79,8 @@ fn main() -> ! {
}
}
#[interrupt]
fn TG0_T0_LEVEL() {
#[handler]
fn tg0_t0_level() {
critical_section::with(|cs| {
let mut timer0 = TIMER0.borrow_ref_mut(cs);
let timer0 = timer0.as_mut().unwrap();

View File

@ -18,13 +18,15 @@ use esp_hal::{
peripherals::{Interrupt, Peripherals},
prelude::*,
systimer::{Alarm, Periodic, SystemTimer, Target},
Blocking,
};
use esp_println::println;
use fugit::ExtU32;
static ALARM0: Mutex<RefCell<Option<Alarm<Periodic, 0>>>> = Mutex::new(RefCell::new(None));
static ALARM1: Mutex<RefCell<Option<Alarm<Target, 1>>>> = Mutex::new(RefCell::new(None));
static ALARM2: Mutex<RefCell<Option<Alarm<Target, 2>>>> = Mutex::new(RefCell::new(None));
static ALARM0: Mutex<RefCell<Option<Alarm<Periodic, Blocking, 0>>>> =
Mutex::new(RefCell::new(None));
static ALARM1: Mutex<RefCell<Option<Alarm<Target, Blocking, 1>>>> = Mutex::new(RefCell::new(None));
static ALARM2: Mutex<RefCell<Option<Alarm<Target, Blocking, 2>>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
@ -36,19 +38,22 @@ fn main() -> ! {
println!("SYSTIMER Current value = {}", SystemTimer::now());
let alarm0 = systimer.alarm0.into_periodic();
alarm0.set_period(1u32.secs());
alarm0.enable_interrupt(true);
let alarm1 = systimer.alarm1;
alarm1.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 2));
alarm1.enable_interrupt(true);
let alarm2 = systimer.alarm2;
alarm2.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 3));
alarm2.enable_interrupt(true);
critical_section::with(|cs| {
let alarm0 = systimer.alarm0.into_periodic();
alarm0.set_interrupt_handler(systimer_target0);
alarm0.set_period(1u32.secs());
alarm0.enable_interrupt(true);
let alarm1 = systimer.alarm1;
alarm1.set_interrupt_handler(systimer_target1);
alarm1.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 2));
alarm1.enable_interrupt(true);
let alarm2 = systimer.alarm2;
alarm2.set_interrupt_handler(systimer_target2);
alarm2.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 3));
alarm2.enable_interrupt(true);
ALARM0.borrow_ref_mut(cs).replace(alarm0);
ALARM1.borrow_ref_mut(cs).replace(alarm1);
ALARM2.borrow_ref_mut(cs).replace(alarm2);
@ -67,8 +72,8 @@ fn main() -> ! {
}
}
#[interrupt]
fn SYSTIMER_TARGET0() {
#[handler(priority = esp_hal::interrupt::Priority::min())]
fn systimer_target0() {
println!("Interrupt lvl1 (alarm0)");
critical_section::with(|cs| {
ALARM0
@ -79,8 +84,8 @@ fn SYSTIMER_TARGET0() {
});
}
#[interrupt]
fn SYSTIMER_TARGET1() {
#[handler(priority = esp_hal::interrupt::Priority::Priority1)]
fn systimer_target1() {
println!("Interrupt lvl2 (alarm1)");
critical_section::with(|cs| {
ALARM1
@ -91,8 +96,8 @@ fn SYSTIMER_TARGET1() {
});
}
#[interrupt]
fn SYSTIMER_TARGET2() {
#[handler(priority = esp_hal::interrupt::Priority::max())]
fn systimer_target2() {
println!("Interrupt lvl2 (alarm2)");
critical_section::with(|cs| {
ALARM2

View File

@ -16,10 +16,11 @@ use esp_hal::{
interrupt::{self, Priority},
peripherals::{Interrupt, Peripherals, TIMG0},
prelude::*,
timer::{Timer, Timer0, TimerGroup},
timer::{Timer, Timer0, TimerGroup, TimerInterrupts},
};
static TIMER0: Mutex<RefCell<Option<Timer<Timer0<TIMG0>>>>> = Mutex::new(RefCell::new(None));
static TIMER0: Mutex<RefCell<Option<Timer<Timer0<TIMG0>, esp_hal::Blocking>>>> =
Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
@ -27,7 +28,14 @@ fn main() -> ! {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new(
peripherals.TIMG0,
&clocks,
Some(TimerInterrupts {
timer0_t0: Some(tg0_t0_level),
..Default::default()
}),
);
let mut timer0 = timg0.timer0;
interrupt::enable(Interrupt::TG0_T0_LEVEL, Priority::Priority1).unwrap();
@ -41,8 +49,8 @@ fn main() -> ! {
loop {}
}
#[interrupt]
fn TG0_T0_LEVEL() {
#[handler]
fn tg0_t0_level() {
critical_section::with(|cs| {
esp_println::println!("Interrupt 1");

View File

@ -26,7 +26,7 @@ fn main() -> ! {
let delay = Delay::new(&clocks);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
let mut wdt0 = timg0.wdt;
wdt0.enable();
wdt0.set_timeout(2u64.secs());

View File

@ -45,7 +45,7 @@ impl Context {
let delay = Delay::new(&clocks);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timg0);
Context {