1#![cfg_attr(esp32s2, doc = "64-bit")]
6#![cfg_attr(not(esp32s2), doc = "52-bit")]
7use core::{fmt::Debug, marker::PhantomData};
21
22use super::{Error, Timer as _};
23use crate::{
24 asynch::AtomicWaker,
25 interrupt::{self, InterruptHandler},
26 peripherals::{Interrupt, SYSTIMER},
27 sync::{RawMutex, lock},
28 system::{Cpu, Peripheral as PeripheralEnable, PeripheralClockControl},
29 time::{Duration, Instant},
30};
31
32#[derive(Copy, Clone)]
34pub enum UnitConfig {
35 Disabled,
37
38 DisabledIfCpuIsStalled(Cpu),
40
41 Enabled,
43}
44
45pub struct SystemTimer<'d> {
47 pub alarm0: Alarm<'d>,
49
50 pub alarm1: Alarm<'d>,
52
53 pub alarm2: Alarm<'d>,
55}
56
57impl<'d> SystemTimer<'d> {
58 cfg_if::cfg_if! {
59 if #[cfg(esp32s2)] {
60 pub const BIT_MASK: u64 = u64::MAX;
62 const PERIOD_MASK: u64 = 0x1FFF_FFFF;
64 } else {
65 pub const BIT_MASK: u64 = 0xF_FFFF_FFFF_FFFF;
67 const PERIOD_MASK: u64 = 0x3FF_FFFF;
69 }
70 }
71
72 #[inline]
74 pub fn ticks_per_second() -> u64 {
75 cfg_if::cfg_if! {
76 if #[cfg(esp32s2)] {
77 const MULTIPLIER: u32 = 2;
78 const DIVIDER: u32 = 1;
79 } else if #[cfg(esp32h2)] {
80 const MULTIPLIER: u32 = 1;
84 const DIVIDER: u32 = 2;
85 } else {
86 const MULTIPLIER: u32 = 4;
90 const DIVIDER: u32 = 10;
91 }
92 }
93 let xtal_freq_mhz = crate::clock::Clocks::xtal_freq().as_hz();
94 ((xtal_freq_mhz * MULTIPLIER) / DIVIDER) as u64
95 }
96
97 pub fn new(_systimer: SYSTIMER<'d>) -> Self {
99 PeripheralClockControl::enable(PeripheralEnable::Systimer);
101
102 #[cfg(soc_etm)]
103 etm::enable_etm();
104
105 Self {
106 alarm0: Alarm::new(0),
107 alarm1: Alarm::new(1),
108 alarm2: Alarm::new(2),
109 }
110 }
111
112 pub fn unit_value(unit: Unit) -> u64 {
114 unit.read_count()
119 }
120
121 #[cfg(not(esp32s2))]
122 pub unsafe fn configure_unit(unit: Unit, config: UnitConfig) {
132 unit.configure(config)
133 }
134
135 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 lock(&CONF_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 fn read_count(&self) -> u64 {
238 let channel = self.channel() as usize;
241 let systimer = SYSTIMER::regs();
242
243 systimer.unit_op(channel).write(|w| w.update().set_bit());
244 while !systimer.unit_op(channel).read().value_valid().bit_is_set() {}
245
246 let unit_value = systimer.unit_value(channel);
252 let mut lo_prev = unit_value.lo().read().bits();
253 loop {
254 let lo = lo_prev;
255 let hi = unit_value.hi().read().bits();
256 lo_prev = unit_value.lo().read().bits();
257
258 if lo == lo_prev {
259 return ((hi as u64) << 32) | lo as u64;
260 }
261 }
262 }
263}
264
265#[derive(Debug)]
267#[cfg_attr(feature = "defmt", derive(defmt::Format))]
268pub struct Alarm<'d> {
269 comp: u8,
270 unit: Unit,
271 _lifetime: PhantomData<&'d mut ()>,
272}
273
274impl Alarm<'_> {
275 const fn new(comp: u8) -> Self {
276 Alarm {
277 comp,
278 unit: Unit::Unit0,
279 _lifetime: PhantomData,
280 }
281 }
282
283 pub unsafe fn clone_unchecked(&self) -> Self {
290 Self {
291 comp: self.comp,
292 unit: self.unit,
293 _lifetime: PhantomData,
294 }
295 }
296
297 pub fn reborrow(&mut self) -> Alarm<'_> {
302 unsafe { self.clone_unchecked() }
303 }
304
305 #[inline]
307 fn channel(&self) -> u8 {
308 self.comp
309 }
310
311 fn set_enable(&self, enable: bool) {
314 lock(&CONF_LOCK, || {
315 #[cfg(not(esp32s2))]
316 SYSTIMER::regs().conf().modify(|_, w| match self.channel() {
317 0 => w.target0_work_en().bit(enable),
318 1 => w.target1_work_en().bit(enable),
319 2 => w.target2_work_en().bit(enable),
320 _ => unreachable!(),
321 });
322 });
323
324 #[cfg(esp32s2)]
327 SYSTIMER::regs()
328 .target_conf(self.channel() as usize)
329 .modify(|_r, w| w.work_en().bit(enable));
330 }
331
332 fn is_enabled(&self) -> bool {
335 #[cfg(not(esp32s2))]
336 match self.channel() {
337 0 => SYSTIMER::regs().conf().read().target0_work_en().bit(),
338 1 => SYSTIMER::regs().conf().read().target1_work_en().bit(),
339 2 => SYSTIMER::regs().conf().read().target2_work_en().bit(),
340 _ => unreachable!(),
341 }
342
343 #[cfg(esp32s2)]
344 SYSTIMER::regs()
345 .target_conf(self.channel() as usize)
346 .read()
347 .work_en()
348 .bit()
349 }
350
351 #[cfg(not(esp32s2))]
353 pub fn set_unit(&self, unit: Unit) {
354 SYSTIMER::regs()
355 .target_conf(self.channel() as usize)
356 .modify(|_, w| w.timer_unit_sel().bit(matches!(unit, Unit::Unit1)));
357 }
358
359 fn set_mode(&self, mode: ComparatorMode) {
361 let is_period_mode = match mode {
362 ComparatorMode::Period => true,
363 ComparatorMode::Target => false,
364 };
365 SYSTIMER::regs()
366 .target_conf(self.channel() as usize)
367 .modify(|_, w| w.period_mode().bit(is_period_mode));
368 }
369
370 fn mode(&self) -> ComparatorMode {
373 if SYSTIMER::regs()
374 .target_conf(self.channel() as usize)
375 .read()
376 .period_mode()
377 .bit()
378 {
379 ComparatorMode::Period
380 } else {
381 ComparatorMode::Target
382 }
383 }
384
385 fn set_period(&self, value: u32) {
388 let systimer = SYSTIMER::regs();
389 let tconf = systimer.target_conf(self.channel() as usize);
390 unsafe { tconf.modify(|_, w| w.period().bits(value)) };
391 #[cfg(not(esp32s2))]
392 {
393 let comp_load = systimer.comp_load(self.channel() as usize);
394 comp_load.write(|w| w.load().set_bit());
395 }
396 }
397
398 fn set_target(&self, value: u64) {
400 let systimer = SYSTIMER::regs();
401 let target = systimer.trgt(self.channel() as usize);
402 target.hi().write(|w| w.hi().set((value >> 32) as u32));
403 target
404 .lo()
405 .write(|w| w.lo().set((value & 0xFFFF_FFFF) as u32));
406 #[cfg(not(esp32s2))]
407 {
408 let comp_load = systimer.comp_load(self.channel() as usize);
409 comp_load.write(|w| w.load().set_bit());
410 }
411 }
412
413 fn set_interrupt_handler(&self, handler: InterruptHandler) {
415 let interrupt = match self.channel() {
416 0 => Interrupt::SYSTIMER_TARGET0,
417 1 => Interrupt::SYSTIMER_TARGET1,
418 2 => Interrupt::SYSTIMER_TARGET2,
419 _ => unreachable!(),
420 };
421
422 for core in crate::system::Cpu::other() {
423 crate::interrupt::disable(core, interrupt);
424 }
425
426 #[cfg(not(esp32s2))]
427 unsafe {
428 interrupt::bind_interrupt(interrupt, handler.handler());
429 }
430
431 #[cfg(esp32s2)]
432 {
433 static mut HANDLERS: [Option<extern "C" fn()>; 3] = [None, None, None];
440
441 #[crate::ram]
442 unsafe extern "C" fn _handle_interrupt<const CH: u8>() {
443 if SYSTIMER::regs().int_raw().read().target(CH).bit_is_set() {
444 let handler = unsafe { HANDLERS[CH as usize] };
445 if let Some(handler) = handler {
446 handler();
447 }
448 }
449 }
450
451 unsafe {
452 HANDLERS[self.channel() as usize] = Some(handler.handler());
453 let handler = match self.channel() {
454 0 => _handle_interrupt::<0>,
455 1 => _handle_interrupt::<1>,
456 2 => _handle_interrupt::<2>,
457 _ => unreachable!(),
458 };
459 interrupt::bind_interrupt(interrupt, handler);
460 }
461 }
462 unwrap!(interrupt::enable(interrupt, handler.priority()));
463 }
464}
465
466#[derive(Copy, Clone)]
468enum ComparatorMode {
469 Period,
471
472 Target,
475}
476
477impl super::Timer for Alarm<'_> {
478 fn start(&self) {
479 self.set_enable(true);
480 }
481
482 fn stop(&self) {
483 self.set_enable(false);
484 }
485
486 fn reset(&self) {
487 #[cfg(esp32s2)]
488 SYSTIMER::regs()
490 .step()
491 .modify(|_, w| unsafe { w.xtal_step().bits(0x1) });
492
493 #[cfg(not(esp32s2))]
494 SYSTIMER::regs()
495 .conf()
496 .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit());
497 }
498
499 fn is_running(&self) -> bool {
500 self.is_enabled()
501 }
502
503 fn now(&self) -> Instant {
504 let ticks = self.unit.read_count();
508
509 let us = ticks / (SystemTimer::ticks_per_second() / 1_000_000);
510
511 Instant::from_ticks(us)
512 }
513
514 fn load_value(&self, value: Duration) -> Result<(), Error> {
515 let mode = self.mode();
516
517 let us = value.as_micros();
518 let ticks = us * (SystemTimer::ticks_per_second() / 1_000_000);
519
520 if matches!(mode, ComparatorMode::Period) {
521 if (ticks & !SystemTimer::PERIOD_MASK) != 0 {
527 return Err(Error::InvalidTimeout);
528 }
529
530 self.set_period(ticks as u32);
531
532 self.set_mode(ComparatorMode::Target);
535 self.set_mode(ComparatorMode::Period);
536 } else {
537 #[cfg(not(esp32s2))]
543 if (ticks & !SystemTimer::BIT_MASK) != 0 {
544 return Err(Error::InvalidTimeout);
545 }
546
547 let v = self.unit.read_count();
548 let t = v + ticks;
549
550 self.set_target(t);
551 }
552
553 Ok(())
554 }
555
556 fn enable_auto_reload(&self, auto_reload: bool) {
557 let mode = if auto_reload {
559 ComparatorMode::Period
560 } else {
561 ComparatorMode::Target
562 };
563 self.set_mode(mode)
564 }
565
566 fn enable_interrupt(&self, state: bool) {
567 lock(&INT_ENA_LOCK, || {
568 SYSTIMER::regs()
569 .int_ena()
570 .modify(|_, w| w.target(self.channel()).bit(state));
571 });
572 }
573
574 fn clear_interrupt(&self) {
575 SYSTIMER::regs()
576 .int_clr()
577 .write(|w| w.target(self.channel()).clear_bit_by_one());
578 }
579
580 fn is_interrupt_set(&self) -> bool {
581 SYSTIMER::regs()
582 .int_raw()
583 .read()
584 .target(self.channel())
585 .bit_is_set()
586 }
587
588 fn async_interrupt_handler(&self) -> InterruptHandler {
589 match self.channel() {
590 0 => asynch::target0_handler,
591 1 => asynch::target1_handler,
592 2 => asynch::target2_handler,
593 _ => unreachable!(),
594 }
595 }
596
597 fn peripheral_interrupt(&self) -> Interrupt {
598 match self.channel() {
599 0 => Interrupt::SYSTIMER_TARGET0,
600 1 => Interrupt::SYSTIMER_TARGET1,
601 2 => Interrupt::SYSTIMER_TARGET2,
602 _ => unreachable!(),
603 }
604 }
605
606 fn set_interrupt_handler(&self, handler: InterruptHandler) {
607 self.set_interrupt_handler(handler)
608 }
609
610 fn waker(&self) -> &AtomicWaker {
611 asynch::waker(self)
612 }
613}
614
615impl crate::private::Sealed for Alarm<'_> {}
616
617static CONF_LOCK: RawMutex = RawMutex::new();
618static INT_ENA_LOCK: RawMutex = RawMutex::new();
619
620mod asynch {
622 use core::marker::PhantomData;
623
624 use procmacros::handler;
625
626 use super::*;
627 use crate::asynch::AtomicWaker;
628
629 const NUM_ALARMS: usize = 3;
630 static WAKERS: [AtomicWaker; NUM_ALARMS] = [const { AtomicWaker::new() }; NUM_ALARMS];
631
632 pub(super) fn waker(alarm: &Alarm<'_>) -> &'static AtomicWaker {
633 &WAKERS[alarm.channel() as usize]
634 }
635
636 #[inline]
637 fn handle_alarm(alarm: u8) {
638 Alarm {
639 comp: alarm,
640 unit: Unit::Unit0,
641 _lifetime: PhantomData,
642 }
643 .enable_interrupt(false);
644
645 WAKERS[alarm as usize].wake();
646 }
647
648 #[handler]
649 pub(crate) fn target0_handler() {
650 handle_alarm(0);
651 }
652
653 #[handler]
654 pub(crate) fn target1_handler() {
655 handle_alarm(1);
656 }
657
658 #[handler]
659 pub(crate) fn target2_handler() {
660 handle_alarm(2);
661 }
662}
663
664#[cfg(soc_etm)]
665pub mod etm {
666 #![doc = crate::before_snippet!()]
680 use super::*;
715
716 pub struct Event {
718 id: u8,
719 }
720
721 impl Event {
722 pub fn new(alarm: &Alarm<'_>) -> Self {
724 Self {
725 id: 50 + alarm.channel(),
726 }
727 }
728 }
729
730 impl crate::private::Sealed for Event {}
731
732 impl crate::etm::EtmEvent for Event {
733 fn id(&self) -> u8 {
734 self.id
735 }
736 }
737
738 pub(super) fn enable_etm() {
739 SYSTIMER::regs().conf().modify(|_, w| w.etm_en().set_bit());
740 }
741}