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_has_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) {
131 unit.configure(config)
132 }
133
134 pub unsafe fn set_unit_value(unit: Unit, value: u64) {
145 unit.set_count(value)
146 }
147}
148
149#[cfg_attr(esp32s2, doc = "64-bit")]
151#[cfg_attr(not(esp32s2), doc = "52-bit")]
152#[derive(Copy, Clone, Debug, PartialEq, Eq)]
154#[cfg_attr(feature = "defmt", derive(defmt::Format))]
155pub enum Unit {
156 Unit0 = 0,
158 #[cfg(not(esp32s2))]
159 Unit1 = 1,
161}
162
163impl Unit {
164 #[inline]
165 fn channel(&self) -> u8 {
166 *self as _
167 }
168
169 #[cfg(not(esp32s2))]
170 fn configure(&self, config: UnitConfig) {
171 lock(&CONF_LOCK, || {
172 SYSTIMER::regs().conf().modify(|_, w| match config {
173 UnitConfig::Disabled => match self.channel() {
174 0 => w.timer_unit0_work_en().clear_bit(),
175 1 => w.timer_unit1_work_en().clear_bit(),
176 _ => unreachable!(),
177 },
178 UnitConfig::DisabledIfCpuIsStalled(cpu) => match self.channel() {
179 0 => {
180 w.timer_unit0_work_en().set_bit();
181 w.timer_unit0_core0_stall_en().bit(cpu == Cpu::ProCpu);
182 w.timer_unit0_core1_stall_en().bit(cpu != Cpu::ProCpu)
183 }
184 1 => {
185 w.timer_unit1_work_en().set_bit();
186 w.timer_unit1_core0_stall_en().bit(cpu == Cpu::ProCpu);
187 w.timer_unit1_core1_stall_en().bit(cpu != Cpu::ProCpu)
188 }
189 _ => unreachable!(),
190 },
191 UnitConfig::Enabled => match self.channel() {
192 0 => {
193 w.timer_unit0_work_en().set_bit();
194 w.timer_unit0_core0_stall_en().clear_bit();
195 w.timer_unit0_core1_stall_en().clear_bit()
196 }
197 1 => {
198 w.timer_unit1_work_en().set_bit();
199 w.timer_unit1_core0_stall_en().clear_bit();
200 w.timer_unit1_core1_stall_en().clear_bit()
201 }
202 _ => unreachable!(),
203 },
204 });
205 });
206 }
207
208 fn set_count(&self, value: u64) {
209 let systimer = SYSTIMER::regs();
210 #[cfg(not(esp32s2))]
211 {
212 let unitload = systimer.unitload(self.channel() as _);
213 let unit_load = systimer.unit_load(self.channel() as _);
214
215 unitload.hi().write(|w| w.load_hi().set((value << 32) as _));
216 unitload
217 .lo()
218 .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _));
219
220 unit_load.write(|w| w.load().set_bit());
221 }
222 #[cfg(esp32s2)]
223 {
224 systimer
225 .load_hi()
226 .write(|w| w.load_hi().set((value << 32) as _));
227 systimer
228 .load_lo()
229 .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _));
230
231 systimer.load().write(|w| w.load().set_bit());
232 }
233 }
234
235 fn read_count(&self) -> u64 {
236 let channel = self.channel() as usize;
239 let systimer = SYSTIMER::regs();
240
241 systimer.unit_op(channel).write(|w| w.update().set_bit());
242 while !systimer.unit_op(channel).read().value_valid().bit_is_set() {}
243
244 let unit_value = systimer.unit_value(channel);
250 let mut lo_prev = unit_value.lo().read().bits();
251 loop {
252 let lo = lo_prev;
253 let hi = unit_value.hi().read().bits();
254 lo_prev = unit_value.lo().read().bits();
255
256 if lo == lo_prev {
257 return ((hi as u64) << 32) | lo as u64;
258 }
259 }
260 }
261}
262
263#[derive(Debug)]
265#[cfg_attr(feature = "defmt", derive(defmt::Format))]
266pub struct Alarm<'d> {
267 comp: u8,
268 unit: Unit,
269 _lifetime: PhantomData<&'d mut ()>,
270}
271
272impl Alarm<'_> {
273 const fn new(comp: u8) -> Self {
274 Alarm {
275 comp,
276 unit: Unit::Unit0,
277 _lifetime: PhantomData,
278 }
279 }
280
281 pub unsafe fn clone_unchecked(&self) -> Self {
288 Self {
289 comp: self.comp,
290 unit: self.unit,
291 _lifetime: PhantomData,
292 }
293 }
294
295 pub fn reborrow(&mut self) -> Alarm<'_> {
304 unsafe { self.clone_unchecked() }
305 }
306
307 #[inline]
309 fn channel(&self) -> u8 {
310 self.comp
311 }
312
313 fn set_enable(&self, enable: bool) {
316 lock(&CONF_LOCK, || {
317 #[cfg(not(esp32s2))]
318 SYSTIMER::regs().conf().modify(|_, w| match self.channel() {
319 0 => w.target0_work_en().bit(enable),
320 1 => w.target1_work_en().bit(enable),
321 2 => w.target2_work_en().bit(enable),
322 _ => unreachable!(),
323 });
324 });
325
326 #[cfg(esp32s2)]
329 SYSTIMER::regs()
330 .target_conf(self.channel() as usize)
331 .modify(|_r, w| w.work_en().bit(enable));
332 }
333
334 fn is_enabled(&self) -> bool {
337 #[cfg(not(esp32s2))]
338 match self.channel() {
339 0 => SYSTIMER::regs().conf().read().target0_work_en().bit(),
340 1 => SYSTIMER::regs().conf().read().target1_work_en().bit(),
341 2 => SYSTIMER::regs().conf().read().target2_work_en().bit(),
342 _ => unreachable!(),
343 }
344
345 #[cfg(esp32s2)]
346 SYSTIMER::regs()
347 .target_conf(self.channel() as usize)
348 .read()
349 .work_en()
350 .bit()
351 }
352
353 #[cfg(not(esp32s2))]
355 pub fn set_unit(&self, unit: Unit) {
356 SYSTIMER::regs()
357 .target_conf(self.channel() as usize)
358 .modify(|_, w| w.timer_unit_sel().bit(matches!(unit, Unit::Unit1)));
359 }
360
361 fn set_mode(&self, mode: ComparatorMode) {
363 let is_period_mode = match mode {
364 ComparatorMode::Period => true,
365 ComparatorMode::Target => false,
366 };
367 SYSTIMER::regs()
368 .target_conf(self.channel() as usize)
369 .modify(|_, w| w.period_mode().bit(is_period_mode));
370 }
371
372 fn mode(&self) -> ComparatorMode {
375 if SYSTIMER::regs()
376 .target_conf(self.channel() as usize)
377 .read()
378 .period_mode()
379 .bit()
380 {
381 ComparatorMode::Period
382 } else {
383 ComparatorMode::Target
384 }
385 }
386
387 fn set_period(&self, value: u32) {
390 let systimer = SYSTIMER::regs();
391 let tconf = systimer.target_conf(self.channel() as usize);
392 unsafe { tconf.modify(|_, w| w.period().bits(value)) };
393 #[cfg(not(esp32s2))]
394 {
395 let comp_load = systimer.comp_load(self.channel() as usize);
396 comp_load.write(|w| w.load().set_bit());
397 }
398 }
399
400 fn set_target(&self, value: u64) {
402 let systimer = SYSTIMER::regs();
403 let target = systimer.trgt(self.channel() as usize);
404 target.hi().write(|w| w.hi().set((value >> 32) as u32));
405 target
406 .lo()
407 .write(|w| w.lo().set((value & 0xFFFF_FFFF) as u32));
408 #[cfg(not(esp32s2))]
409 {
410 let comp_load = systimer.comp_load(self.channel() as usize);
411 comp_load.write(|w| w.load().set_bit());
412 }
413 }
414
415 fn set_interrupt_handler(&self, handler: InterruptHandler) {
417 let interrupt = match self.channel() {
418 0 => Interrupt::SYSTIMER_TARGET0,
419 1 => Interrupt::SYSTIMER_TARGET1,
420 2 => Interrupt::SYSTIMER_TARGET2,
421 _ => unreachable!(),
422 };
423
424 for core in crate::system::Cpu::other() {
425 crate::interrupt::disable(core, interrupt);
426 }
427
428 #[cfg(not(esp32s2))]
429 unsafe {
430 interrupt::bind_interrupt(interrupt, handler.handler());
431 }
432
433 #[cfg(esp32s2)]
434 {
435 static mut HANDLERS: [Option<extern "C" fn()>; 3] = [None, None, None];
442
443 #[crate::ram]
444 unsafe extern "C" fn _handle_interrupt<const CH: u8>() {
445 if SYSTIMER::regs().int_raw().read().target(CH).bit_is_set() {
446 let handler = unsafe { HANDLERS[CH as usize] };
447 if let Some(handler) = handler {
448 handler();
449 }
450 }
451 }
452
453 unsafe {
454 HANDLERS[self.channel() as usize] = Some(handler.handler());
455 let handler = match self.channel() {
456 0 => _handle_interrupt::<0>,
457 1 => _handle_interrupt::<1>,
458 2 => _handle_interrupt::<2>,
459 _ => unreachable!(),
460 };
461 interrupt::bind_interrupt(interrupt, handler);
462 }
463 }
464 unwrap!(interrupt::enable(interrupt, handler.priority()));
465 }
466}
467
468#[derive(Copy, Clone)]
470enum ComparatorMode {
471 Period,
473
474 Target,
477}
478
479impl super::Timer for Alarm<'_> {
480 fn start(&self) {
481 self.set_enable(true);
482 }
483
484 fn stop(&self) {
485 self.set_enable(false);
486 }
487
488 fn reset(&self) {
489 #[cfg(esp32s2)]
490 SYSTIMER::regs()
492 .step()
493 .modify(|_, w| unsafe { w.xtal_step().bits(0x1) });
494
495 #[cfg(not(esp32s2))]
496 SYSTIMER::regs()
497 .conf()
498 .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit());
499 }
500
501 fn is_running(&self) -> bool {
502 self.is_enabled()
503 }
504
505 fn now(&self) -> Instant {
506 let ticks = self.unit.read_count();
510
511 let us = ticks / (SystemTimer::ticks_per_second() / 1_000_000);
512
513 Instant::from_ticks(us)
514 }
515
516 fn load_value(&self, value: Duration) -> Result<(), Error> {
517 let mode = self.mode();
518
519 let us = value.as_micros();
520 let ticks = us * (SystemTimer::ticks_per_second() / 1_000_000);
521
522 if matches!(mode, ComparatorMode::Period) {
523 if (ticks & !SystemTimer::PERIOD_MASK) != 0 {
529 return Err(Error::InvalidTimeout);
530 }
531
532 self.set_period(ticks as u32);
533
534 self.set_mode(ComparatorMode::Target);
537 self.set_mode(ComparatorMode::Period);
538 } else {
539 #[cfg(not(esp32s2))]
545 if (ticks & !SystemTimer::BIT_MASK) != 0 {
546 return Err(Error::InvalidTimeout);
547 }
548
549 let v = self.unit.read_count();
550 let t = v + ticks;
551
552 self.set_target(t);
553 }
554
555 Ok(())
556 }
557
558 fn enable_auto_reload(&self, auto_reload: bool) {
559 let mode = if auto_reload {
561 ComparatorMode::Period
562 } else {
563 ComparatorMode::Target
564 };
565 self.set_mode(mode)
566 }
567
568 fn enable_interrupt(&self, state: bool) {
569 lock(&INT_ENA_LOCK, || {
570 SYSTIMER::regs()
571 .int_ena()
572 .modify(|_, w| w.target(self.channel()).bit(state));
573 });
574 }
575
576 fn clear_interrupt(&self) {
577 SYSTIMER::regs()
578 .int_clr()
579 .write(|w| w.target(self.channel()).clear_bit_by_one());
580 }
581
582 fn is_interrupt_set(&self) -> bool {
583 SYSTIMER::regs()
584 .int_raw()
585 .read()
586 .target(self.channel())
587 .bit_is_set()
588 }
589
590 fn async_interrupt_handler(&self) -> InterruptHandler {
591 match self.channel() {
592 0 => asynch::target0_handler,
593 1 => asynch::target1_handler,
594 2 => asynch::target2_handler,
595 _ => unreachable!(),
596 }
597 }
598
599 fn peripheral_interrupt(&self) -> Interrupt {
600 match self.channel() {
601 0 => Interrupt::SYSTIMER_TARGET0,
602 1 => Interrupt::SYSTIMER_TARGET1,
603 2 => Interrupt::SYSTIMER_TARGET2,
604 _ => unreachable!(),
605 }
606 }
607
608 fn set_interrupt_handler(&self, handler: InterruptHandler) {
609 self.set_interrupt_handler(handler)
610 }
611
612 fn waker(&self) -> &AtomicWaker {
613 asynch::waker(self)
614 }
615}
616
617impl crate::private::Sealed for Alarm<'_> {}
618
619static CONF_LOCK: RawMutex = RawMutex::new();
620static INT_ENA_LOCK: RawMutex = RawMutex::new();
621
622mod asynch {
624 use core::marker::PhantomData;
625
626 use procmacros::handler;
627
628 use super::*;
629 use crate::asynch::AtomicWaker;
630
631 const NUM_ALARMS: usize = 3;
632 static WAKERS: [AtomicWaker; NUM_ALARMS] = [const { AtomicWaker::new() }; NUM_ALARMS];
633
634 pub(super) fn waker(alarm: &Alarm<'_>) -> &'static AtomicWaker {
635 &WAKERS[alarm.channel() as usize]
636 }
637
638 #[inline]
639 fn handle_alarm(alarm: u8) {
640 Alarm {
641 comp: alarm,
642 unit: Unit::Unit0,
643 _lifetime: PhantomData,
644 }
645 .enable_interrupt(false);
646
647 WAKERS[alarm as usize].wake();
648 }
649
650 #[handler]
651 pub(crate) fn target0_handler() {
652 handle_alarm(0);
653 }
654
655 #[handler]
656 pub(crate) fn target1_handler() {
657 handle_alarm(1);
658 }
659
660 #[handler]
661 pub(crate) fn target2_handler() {
662 handle_alarm(2);
663 }
664}
665
666#[cfg(soc_has_etm)]
667pub mod etm {
668 #![cfg_attr(docsrs, procmacros::doc_replace)]
669 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}