pub mod prelude {
pub use crate::esp32c3_systimer_monotonic;
pub use crate::Monotonic;
pub use fugit::{self, ExtU64, ExtU64Ceil};
}
use crate::TimerQueueBackend;
use esp32c3::{INTERRUPT_CORE0, SYSTIMER};
use rtic_time::timer_queue::TimerQueue;
pub struct TimerBackend;
impl TimerBackend {
pub fn _start(timer: SYSTIMER) {
const INTERRUPT_MAP_BASE: u32 = 0x600c2000;
let interrupt_number = 37isize;
let cpu_interrupt_number = 31isize;
unsafe {
let intr_map_base = INTERRUPT_MAP_BASE as *mut u32;
intr_map_base
.offset(interrupt_number)
.write_volatile(cpu_interrupt_number as u32);
(*INTERRUPT_CORE0::ptr())
.cpu_int_enable()
.modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); let intr = INTERRUPT_CORE0::ptr();
let intr_prio_base = (*intr).cpu_int_pri(0).as_ptr();
intr_prio_base
.offset(cpu_interrupt_number)
.write_volatile(15);
}
timer.conf().write(|w| w.timer_unit0_work_en().set_bit());
timer
.conf()
.write(|w| w.timer_unit1_core0_stall_en().clear_bit());
TIMER_QUEUE.initialize(Self {})
}
}
static TIMER_QUEUE: TimerQueue<TimerBackend> = TimerQueue::new();
use esp32c3;
impl TimerQueueBackend for TimerBackend {
type Ticks = u64;
fn now() -> Self::Ticks {
let peripherals = unsafe { esp32c3::Peripherals::steal() };
peripherals
.SYSTIMER
.unit0_op()
.write(|w| w.update().set_bit());
while peripherals.SYSTIMER.unit0_op().read().value_valid() == false {}
let instant: u64 = (peripherals.SYSTIMER.unit_value(0).lo().read().bits() as u64)
| ((peripherals.SYSTIMER.unit_value(0).hi().read().bits() as u64) << 32);
instant
}
fn set_compare(instant: Self::Ticks) {
let systimer = unsafe { esp32c3::Peripherals::steal() }.SYSTIMER;
systimer
.target0_conf()
.write(|w| w.timer_unit_sel().set_bit());
systimer
.target0_conf()
.write(|w| w.period_mode().clear_bit());
systimer
.trgt(0)
.lo()
.write(|w| unsafe { w.bits((instant & 0xFFFFFFFF).try_into().unwrap()) });
systimer
.trgt(0)
.hi()
.write(|w| unsafe { w.bits((instant >> 32).try_into().unwrap()) });
systimer.comp0_load().write(|w| w.load().set_bit()); systimer.conf().write(|w| w.target0_work_en().set_bit());
systimer.int_ena().write(|w| w.target0().set_bit());
}
fn clear_compare_flag() {
unsafe { esp32c3::Peripherals::steal() }
.SYSTIMER
.int_clr()
.write(|w| w.target0().bit(true));
}
fn pend_interrupt() {
extern "C" {
fn interrupt31();
}
riscv::interrupt::disable();
unsafe { interrupt31() };
unsafe { riscv::interrupt::enable() };
}
fn timer_queue() -> &'static TimerQueue<Self> {
&TIMER_QUEUE
}
}
#[macro_export]
macro_rules! esp32c3_systimer_monotonic {
($name:ident) => {
pub struct $name;
impl $name {
pub fn start(timer: esp32c3::SYSTIMER) {
#[export_name = "interrupt31"]
#[allow(non_snake_case)]
unsafe extern "C" fn Systimer() {
use $crate::TimerQueueBackend;
$crate::esp32c3::TimerBackend::timer_queue().on_monotonic_interrupt();
}
$crate::esp32c3::TimerBackend::_start(timer);
}
}
impl $crate::TimerQueueBasedMonotonic for $name {
type Backend = $crate::esp32c3::TimerBackend;
type Instant = $crate::fugit::Instant<
<Self::Backend as $crate::TimerQueueBackend>::Ticks,
1,
16_000_000,
>;
type Duration = $crate::fugit::Duration<
<Self::Backend as $crate::TimerQueueBackend>::Ticks,
1,
16_000_000,
>;
}
$crate::rtic_time::impl_embedded_hal_delay_fugit!($name);
$crate::rtic_time::impl_embedded_hal_async_delay_fugit!($name);
};
}