1#![cfg_attr(esp32s2, doc = "64-bit")]
6#![cfg_attr(not(esp32s2), doc = "52-bit")]
7use core::{fmt::Debug, marker::PhantomData};
21
22use esp_sync::RawMutex;
23
24use super::{Error, Timer as _};
25use crate::{
26 asynch::AtomicWaker,
27 interrupt::{self, InterruptHandler},
28 peripherals::{Interrupt, SYSTIMER},
29 system::{Cpu, Peripheral as PeripheralEnable, PeripheralClockControl},
30 time::{Duration, Instant},
31};
32
33#[derive(Copy, Clone)]
35pub enum UnitConfig {
36 Disabled,
38
39 DisabledIfCpuIsStalled(Cpu),
41
42 Enabled,
44}
45
46pub struct SystemTimer<'d> {
48 pub alarm0: Alarm<'d>,
50
51 pub alarm1: Alarm<'d>,
53
54 pub alarm2: Alarm<'d>,
56}
57
58impl<'d> SystemTimer<'d> {
59 cfg_if::cfg_if! {
60 if #[cfg(esp32s2)] {
61 pub const BIT_MASK: u64 = u64::MAX;
63 const PERIOD_MASK: u64 = 0x1FFF_FFFF;
65 } else {
66 pub const BIT_MASK: u64 = 0xF_FFFF_FFFF_FFFF;
68 const PERIOD_MASK: u64 = 0x3FF_FFFF;
70 }
71 }
72
73 #[inline]
75 pub fn ticks_per_second() -> u64 {
76 cfg_if::cfg_if! {
77 if #[cfg(esp32s2)] {
78 const MULTIPLIER: u32 = 2;
79 const DIVIDER: u32 = 1;
80 } else if #[cfg(esp32h2)] {
81 const MULTIPLIER: u32 = 1;
85 const DIVIDER: u32 = 2;
86 } else {
87 const MULTIPLIER: u32 = 4;
91 const DIVIDER: u32 = 10;
92 }
93 }
94 let xtal_freq_mhz = crate::clock::Clocks::xtal_freq().as_hz();
95 ((xtal_freq_mhz * MULTIPLIER) / DIVIDER) as u64
96 }
97
98 pub fn new(_systimer: SYSTIMER<'d>) -> Self {
100 PeripheralClockControl::enable(PeripheralEnable::Systimer);
102
103 #[cfg(soc_has_etm)]
104 etm::enable_etm();
105
106 Self {
107 alarm0: Alarm::new(Comparator::Comparator0),
108 alarm1: Alarm::new(Comparator::Comparator1),
109 alarm2: Alarm::new(Comparator::Comparator2),
110 }
111 }
112
113 #[inline]
115 pub fn unit_value(unit: Unit) -> u64 {
116 unit.read_count()
121 }
122
123 #[cfg(not(esp32s2))]
124 pub unsafe fn configure_unit(unit: Unit, config: UnitConfig) {
133 unit.configure(config)
134 }
135
136 pub unsafe fn set_unit_value(unit: Unit, value: u64) {
147 unit.set_count(value)
148 }
149}
150
151#[cfg_attr(esp32s2, doc = "64-bit")]
153#[cfg_attr(not(esp32s2), doc = "52-bit")]
154#[derive(Copy, Clone, Debug, PartialEq, Eq)]
156#[cfg_attr(feature = "defmt", derive(defmt::Format))]
157pub enum Unit {
158 Unit0 = 0,
160 #[cfg(not(esp32s2))]
161 Unit1 = 1,
163}
164
165impl Unit {
166 #[inline]
167 fn channel(&self) -> u8 {
168 *self as _
169 }
170
171 #[cfg(not(esp32s2))]
172 fn configure(&self, config: UnitConfig) {
173 CONF_LOCK.lock(|| {
174 SYSTIMER::regs().conf().modify(|_, w| match config {
175 UnitConfig::Disabled => match self.channel() {
176 0 => w.timer_unit0_work_en().clear_bit(),
177 1 => w.timer_unit1_work_en().clear_bit(),
178 _ => unreachable!(),
179 },
180 UnitConfig::DisabledIfCpuIsStalled(cpu) => match self.channel() {
181 0 => {
182 w.timer_unit0_work_en().set_bit();
183 w.timer_unit0_core0_stall_en().bit(cpu == Cpu::ProCpu);
184 w.timer_unit0_core1_stall_en().bit(cpu != Cpu::ProCpu)
185 }
186 1 => {
187 w.timer_unit1_work_en().set_bit();
188 w.timer_unit1_core0_stall_en().bit(cpu == Cpu::ProCpu);
189 w.timer_unit1_core1_stall_en().bit(cpu != Cpu::ProCpu)
190 }
191 _ => unreachable!(),
192 },
193 UnitConfig::Enabled => match self.channel() {
194 0 => {
195 w.timer_unit0_work_en().set_bit();
196 w.timer_unit0_core0_stall_en().clear_bit();
197 w.timer_unit0_core1_stall_en().clear_bit()
198 }
199 1 => {
200 w.timer_unit1_work_en().set_bit();
201 w.timer_unit1_core0_stall_en().clear_bit();
202 w.timer_unit1_core1_stall_en().clear_bit()
203 }
204 _ => unreachable!(),
205 },
206 });
207 });
208 }
209
210 fn set_count(&self, value: u64) {
211 let systimer = SYSTIMER::regs();
212 #[cfg(not(esp32s2))]
213 {
214 let unitload = systimer.unitload(self.channel() as _);
215 let unit_load = systimer.unit_load(self.channel() as _);
216
217 unitload.hi().write(|w| w.load_hi().set((value << 32) as _));
218 unitload
219 .lo()
220 .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _));
221
222 unit_load.write(|w| w.load().set_bit());
223 }
224 #[cfg(esp32s2)]
225 {
226 systimer
227 .load_hi()
228 .write(|w| w.load_hi().set((value << 32) as _));
229 systimer
230 .load_lo()
231 .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _));
232
233 systimer.load().write(|w| w.load().set_bit());
234 }
235 }
236
237 #[inline]
238 fn read_count(&self) -> u64 {
239 let channel = self.channel() as usize;
242 let systimer = SYSTIMER::regs();
243
244 systimer.unit_op(channel).write(|w| w.update().set_bit());
245 while !systimer.unit_op(channel).read().value_valid().bit_is_set() {}
246
247 let unit_value = systimer.unit_value(channel);
253 let mut lo_prev = unit_value.lo().read().bits();
254 loop {
255 let lo = lo_prev;
256 let hi = unit_value.hi().read().bits();
257 lo_prev = unit_value.lo().read().bits();
258
259 if lo == lo_prev {
260 return ((hi as u64) << 32) | lo as u64;
261 }
262 }
263 }
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq)]
267#[cfg_attr(feature = "defmt", derive(defmt::Format))]
268enum Comparator {
269 Comparator0,
270 Comparator1,
271 Comparator2,
272}
273
274#[derive(Debug)]
276#[cfg_attr(feature = "defmt", derive(defmt::Format))]
277pub struct Alarm<'d> {
278 comp: Comparator,
279 unit: Unit,
280 _lifetime: PhantomData<&'d mut ()>,
281}
282
283impl Alarm<'_> {
284 const fn new(comp: Comparator) -> Self {
285 Alarm {
286 comp,
287 unit: Unit::Unit0,
288 _lifetime: PhantomData,
289 }
290 }
291
292 pub unsafe fn clone_unchecked(&self) -> Self {
299 Self {
300 comp: self.comp,
301 unit: self.unit,
302 _lifetime: PhantomData,
303 }
304 }
305
306 pub fn reborrow(&mut self) -> Alarm<'_> {
315 unsafe { self.clone_unchecked() }
316 }
317
318 #[inline]
320 fn channel(&self) -> u8 {
321 self.comp as u8
322 }
323
324 fn set_enable(&self, enable: bool) {
327 CONF_LOCK.lock(|| {
328 #[cfg(not(esp32s2))]
329 SYSTIMER::regs().conf().modify(|_, w| match self.channel() {
330 0 => w.target0_work_en().bit(enable),
331 1 => w.target1_work_en().bit(enable),
332 2 => w.target2_work_en().bit(enable),
333 _ => unreachable!(),
334 });
335 });
336
337 #[cfg(esp32s2)]
340 SYSTIMER::regs()
341 .target_conf(self.channel() as usize)
342 .modify(|_r, w| w.work_en().bit(enable));
343 }
344
345 fn is_enabled(&self) -> bool {
348 #[cfg(not(esp32s2))]
349 match self.channel() {
350 0 => SYSTIMER::regs().conf().read().target0_work_en().bit(),
351 1 => SYSTIMER::regs().conf().read().target1_work_en().bit(),
352 2 => SYSTIMER::regs().conf().read().target2_work_en().bit(),
353 _ => unreachable!(),
354 }
355
356 #[cfg(esp32s2)]
357 SYSTIMER::regs()
358 .target_conf(self.channel() as usize)
359 .read()
360 .work_en()
361 .bit()
362 }
363
364 #[cfg(not(esp32s2))]
366 pub fn set_unit(&self, unit: Unit) {
367 SYSTIMER::regs()
368 .target_conf(self.channel() as usize)
369 .modify(|_, w| w.timer_unit_sel().bit(matches!(unit, Unit::Unit1)));
370 }
371
372 fn set_mode(&self, mode: ComparatorMode) {
374 let is_period_mode = match mode {
375 ComparatorMode::Period => true,
376 ComparatorMode::Target => false,
377 };
378 SYSTIMER::regs()
379 .target_conf(self.channel() as usize)
380 .modify(|_, w| w.period_mode().bit(is_period_mode));
381 }
382
383 fn mode(&self) -> ComparatorMode {
386 if SYSTIMER::regs()
387 .target_conf(self.channel() as usize)
388 .read()
389 .period_mode()
390 .bit()
391 {
392 ComparatorMode::Period
393 } else {
394 ComparatorMode::Target
395 }
396 }
397
398 fn set_period(&self, value: u32) {
401 let systimer = SYSTIMER::regs();
402 let tconf = systimer.target_conf(self.channel() as usize);
403 unsafe { tconf.modify(|_, w| w.period().bits(value)) };
404 #[cfg(not(esp32s2))]
405 {
406 let comp_load = systimer.comp_load(self.channel() as usize);
407 comp_load.write(|w| w.load().set_bit());
408 }
409 }
410
411 fn set_target(&self, value: u64) {
413 let systimer = SYSTIMER::regs();
414 let target = systimer.trgt(self.channel() as usize);
415 target.hi().write(|w| w.hi().set((value >> 32) as u32));
416 target
417 .lo()
418 .write(|w| w.lo().set((value & 0xFFFF_FFFF) as u32));
419 #[cfg(not(esp32s2))]
420 {
421 let comp_load = systimer.comp_load(self.channel() as usize);
422 comp_load.write(|w| w.load().set_bit());
423 }
424 }
425
426 fn set_interrupt_handler(&self, handler: InterruptHandler) {
428 let interrupt = match self.channel() {
429 0 => Interrupt::SYSTIMER_TARGET0,
430 1 => Interrupt::SYSTIMER_TARGET1,
431 2 => Interrupt::SYSTIMER_TARGET2,
432 _ => unreachable!(),
433 };
434
435 for core in crate::system::Cpu::other() {
436 crate::interrupt::disable(core, interrupt);
437 }
438
439 #[cfg(not(esp32s2))]
440 unsafe {
441 interrupt::bind_interrupt(interrupt, handler.handler());
442 }
443
444 #[cfg(esp32s2)]
445 {
446 static mut HANDLERS: [Option<crate::interrupt::IsrCallback>; 3] = [None, None, None];
453
454 #[crate::ram]
455 extern "C" fn _handle_interrupt<const CH: u8>() {
456 if SYSTIMER::regs().int_raw().read().target(CH).bit_is_set() {
457 let handler = unsafe { HANDLERS[CH as usize] };
458 if let Some(handler) = handler {
459 (handler.aligned_ptr())();
460 }
461 }
462 }
463
464 unsafe {
465 HANDLERS[self.channel() as usize] = Some(handler.handler());
466 let handler = match self.channel() {
467 0 => _handle_interrupt::<0>,
468 1 => _handle_interrupt::<1>,
469 2 => _handle_interrupt::<2>,
470 _ => unreachable!(),
471 };
472 interrupt::bind_interrupt(interrupt, crate::interrupt::IsrCallback::new(handler));
473 }
474 }
475 unwrap!(interrupt::enable(interrupt, handler.priority()));
476 }
477}
478
479#[derive(Copy, Clone)]
481enum ComparatorMode {
482 Period,
484
485 Target,
488}
489
490impl super::Timer for Alarm<'_> {
491 fn start(&self) {
492 self.set_enable(true);
493 }
494
495 fn stop(&self) {
496 self.set_enable(false);
497 }
498
499 fn reset(&self) {
500 #[cfg(esp32s2)]
501 SYSTIMER::regs()
503 .step()
504 .modify(|_, w| unsafe { w.xtal_step().bits(0x1) });
505
506 #[cfg(not(esp32s2))]
507 SYSTIMER::regs()
508 .conf()
509 .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit());
510 }
511
512 fn is_running(&self) -> bool {
513 self.is_enabled()
514 }
515
516 fn now(&self) -> Instant {
517 let ticks = self.unit.read_count();
521
522 let us = ticks / (SystemTimer::ticks_per_second() / 1_000_000);
523
524 Instant::from_ticks(us)
525 }
526
527 fn load_value(&self, value: Duration) -> Result<(), Error> {
528 let mode = self.mode();
529
530 let us = value.as_micros();
531 let ticks = us * (SystemTimer::ticks_per_second() / 1_000_000);
532
533 if matches!(mode, ComparatorMode::Period) {
534 if (ticks & !SystemTimer::PERIOD_MASK) != 0 {
540 return Err(Error::InvalidTimeout);
541 }
542
543 self.set_period(ticks as u32);
544
545 self.set_mode(ComparatorMode::Target);
548 self.set_mode(ComparatorMode::Period);
549 } else {
550 #[cfg(not(esp32s2))]
556 if (ticks & !SystemTimer::BIT_MASK) != 0 {
557 return Err(Error::InvalidTimeout);
558 }
559
560 let v = self.unit.read_count();
561 let t = v + ticks;
562
563 self.set_target(t);
564 }
565
566 Ok(())
567 }
568
569 fn enable_auto_reload(&self, auto_reload: bool) {
570 let mode = if auto_reload {
572 ComparatorMode::Period
573 } else {
574 ComparatorMode::Target
575 };
576 self.set_mode(mode)
577 }
578
579 fn enable_interrupt(&self, state: bool) {
580 INT_ENA_LOCK.lock(|| {
581 SYSTIMER::regs()
582 .int_ena()
583 .modify(|_, w| w.target(self.channel()).bit(state));
584 });
585 }
586
587 fn clear_interrupt(&self) {
588 SYSTIMER::regs()
589 .int_clr()
590 .write(|w| w.target(self.channel()).clear_bit_by_one());
591 }
592
593 fn is_interrupt_set(&self) -> bool {
594 SYSTIMER::regs()
595 .int_raw()
596 .read()
597 .target(self.channel())
598 .bit_is_set()
599 }
600
601 fn async_interrupt_handler(&self) -> InterruptHandler {
602 match self.channel() {
603 0 => asynch::target0_handler,
604 1 => asynch::target1_handler,
605 2 => asynch::target2_handler,
606 _ => unreachable!(),
607 }
608 }
609
610 fn peripheral_interrupt(&self) -> Interrupt {
611 match self.channel() {
612 0 => Interrupt::SYSTIMER_TARGET0,
613 1 => Interrupt::SYSTIMER_TARGET1,
614 2 => Interrupt::SYSTIMER_TARGET2,
615 _ => unreachable!(),
616 }
617 }
618
619 fn set_interrupt_handler(&self, handler: InterruptHandler) {
620 self.set_interrupt_handler(handler)
621 }
622
623 fn waker(&self) -> &AtomicWaker {
624 asynch::waker(self)
625 }
626}
627
628impl crate::private::Sealed for Alarm<'_> {}
629
630static CONF_LOCK: RawMutex = RawMutex::new();
631static INT_ENA_LOCK: RawMutex = RawMutex::new();
632
633mod asynch {
635 use core::marker::PhantomData;
636
637 use procmacros::handler;
638
639 use super::*;
640 use crate::asynch::AtomicWaker;
641
642 const NUM_ALARMS: usize = 3;
643 static WAKERS: [AtomicWaker; NUM_ALARMS] = [const { AtomicWaker::new() }; NUM_ALARMS];
644
645 pub(super) fn waker(alarm: &Alarm<'_>) -> &'static AtomicWaker {
646 &WAKERS[alarm.channel() as usize]
647 }
648
649 #[inline]
650 fn handle_alarm(comp: Comparator) {
651 Alarm {
652 comp,
653 unit: Unit::Unit0,
654 _lifetime: PhantomData,
655 }
656 .enable_interrupt(false);
657
658 WAKERS[comp as usize].wake();
659 }
660
661 #[handler]
662 pub(crate) fn target0_handler() {
663 handle_alarm(Comparator::Comparator0);
664 }
665
666 #[handler]
667 pub(crate) fn target1_handler() {
668 handle_alarm(Comparator::Comparator1);
669 }
670
671 #[handler]
672 pub(crate) fn target2_handler() {
673 handle_alarm(Comparator::Comparator2);
674 }
675}
676
677#[cfg(soc_has_etm)]
678pub mod etm {
679 #![cfg_attr(docsrs, procmacros::doc_replace)]
680 use super::*;
726
727 pub struct Event {
729 id: u8,
730 }
731
732 impl Event {
733 pub fn new(alarm: &Alarm<'_>) -> Self {
735 Self {
736 id: 50 + alarm.channel(),
737 }
738 }
739 }
740
741 impl crate::private::Sealed for Event {}
742
743 impl crate::etm::EtmEvent for Event {
744 fn id(&self) -> u8 {
745 self.id
746 }
747 }
748
749 pub(super) fn enable_etm() {
750 SYSTIMER::regs().conf().modify(|_, w| w.etm_en().set_bit());
751 }
752}