1#![cfg_attr(esp32s2, doc = "64-bit")]
6#![cfg_attr(not(esp32s2), doc = "52-bit")]
7use core::{fmt::Debug, marker::PhantomData, num::NonZeroU32};
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#[unsafe(no_mangle)]
54#[cfg(feature = "rt")]
55static mut ESP_HAL_SYSTIMER_CORRECTION: NonZeroU32 = NonZeroU32::new(SHIFT_TIMESTAMP_FLAG).unwrap(); #[cfg(not(feature = "rt"))]
58unsafe extern "Rust" {
59 static mut ESP_HAL_SYSTIMER_CORRECTION: NonZeroU32;
60}
61
62const SHIFT_TIMESTAMP_FLAG: u32 = 0x8000_0000;
63const SHIFT_MASK: u32 = 0x0000_FFFF;
64const UNEVEN_DIVIDER_FLAG: u32 = 0x4000_0000;
69const UNEVEN_MULTIPLIER: u32 = if cfg!(esp32h2) { 2 } else { 5 };
70const UNEVEN_DIVIDER_MASK: u32 = 0x0000_FFFF;
71
72#[derive(Copy, Clone)]
74pub enum UnitConfig {
75 Disabled,
77
78 DisabledIfCpuIsStalled(Cpu),
80
81 Enabled,
83}
84
85pub struct SystemTimer<'d> {
87 pub alarm0: Alarm<'d>,
89
90 pub alarm1: Alarm<'d>,
92
93 pub alarm2: Alarm<'d>,
95}
96
97impl<'d> SystemTimer<'d> {
98 cfg_if::cfg_if! {
99 if #[cfg(esp32s2)] {
100 pub const BIT_MASK: u64 = u64::MAX;
102 const PERIOD_MASK: u64 = 0x1FFF_FFFF;
104 } else {
105 pub const BIT_MASK: u64 = 0xF_FFFF_FFFF_FFFF;
107 const PERIOD_MASK: u64 = 0x3FF_FFFF;
109 }
110 }
111
112 #[cfg(feature = "rt")]
114 pub(crate) fn init_timestamp_scaler() {
115 let systimer_rate = Self::ticks_per_second();
117
118 let packed_rate_and_method = if systimer_rate.is_multiple_of(1_000_000) {
120 let ticks_per_us = systimer_rate as u32 / 1_000_000;
121 if ticks_per_us.is_power_of_two() {
122 SHIFT_TIMESTAMP_FLAG | (ticks_per_us.ilog2() & SHIFT_MASK)
124 } else {
125 ticks_per_us
127 }
128 } else {
129 let multiplied_ticks_per_us = (systimer_rate * UNEVEN_MULTIPLIER as u64) / 1_000_000;
132 UNEVEN_DIVIDER_FLAG | (multiplied_ticks_per_us as u32)
133 };
134
135 unsafe {
138 let correction_ptr = &raw mut ESP_HAL_SYSTIMER_CORRECTION;
139 *correction_ptr = unwrap!(NonZeroU32::new(packed_rate_and_method));
140 }
141 }
142
143 #[inline]
144 pub(crate) fn ticks_to_us(ticks: u64) -> u64 {
145 let correction = unsafe { ESP_HAL_SYSTIMER_CORRECTION };
148
149 let correction = correction.get();
150 match correction & (SHIFT_TIMESTAMP_FLAG | UNEVEN_DIVIDER_FLAG) {
151 v if v == SHIFT_TIMESTAMP_FLAG => ticks >> (correction & SHIFT_MASK),
152 v if v == UNEVEN_DIVIDER_FLAG => {
153 let multiplied = if UNEVEN_MULTIPLIER.is_power_of_two() {
156 ticks << UNEVEN_MULTIPLIER.ilog2()
157 } else {
158 ticks * UNEVEN_MULTIPLIER as u64
159 };
160
161 let divider = correction & UNEVEN_DIVIDER_MASK;
162 multiplied / divider as u64
163 }
164 _ => ticks / correction as u64,
165 }
166 }
167
168 #[inline]
169 fn us_to_ticks(us: u64) -> u64 {
170 let correction = unsafe { ESP_HAL_SYSTIMER_CORRECTION };
173
174 let correction = correction.get();
175 match correction & (SHIFT_TIMESTAMP_FLAG | UNEVEN_DIVIDER_FLAG) {
176 v if v == SHIFT_TIMESTAMP_FLAG => us << (correction & SHIFT_MASK),
177 v if v == UNEVEN_DIVIDER_FLAG => {
178 let multiplier = correction & UNEVEN_DIVIDER_MASK;
179 let multiplied = us * multiplier as u64;
180
181 if UNEVEN_MULTIPLIER.is_power_of_two() {
184 multiplied >> UNEVEN_MULTIPLIER.ilog2()
185 } else {
186 multiplied / UNEVEN_MULTIPLIER as u64
187 }
188 }
189 _ => us * correction as u64,
190 }
191 }
192
193 #[inline]
195 pub fn ticks_per_second() -> u64 {
196 cfg_if::cfg_if! {
199 if #[cfg(esp32c5)] {
200 16_000_000
202 } else {
203 crate::soc::clocks::ClockTree::with(|clocks| {
204 cfg_if::cfg_if! {
205 if #[cfg(esp32s2)] {
206 crate::soc::clocks::apb_clk_frequency(clocks) as u64
207 } else if #[cfg(esp32h2)] {
208 (crate::soc::clocks::xtal_clk_frequency(clocks) / 2) as u64
211 } else {
212 (crate::soc::clocks::xtal_clk_frequency(clocks) * 10 / 25) as u64
215 }
216 }
217 })
218 }
219 }
220 }
221
222 pub fn new(_systimer: SYSTIMER<'d>) -> Self {
224 if PeripheralClockControl::enable(PeripheralEnable::Systimer) {
226 PeripheralClockControl::reset(PeripheralEnable::Systimer);
227 } else {
228 PeripheralClockControl::disable(PeripheralEnable::Systimer);
231 }
232
233 #[cfg(etm_driver_supported)]
234 etm::enable_etm();
235
236 Self {
237 alarm0: Alarm::new(Comparator::Comparator0),
238 alarm1: Alarm::new(Comparator::Comparator1),
239 alarm2: Alarm::new(Comparator::Comparator2),
240 }
241 }
242
243 #[inline]
245 pub fn unit_value(unit: Unit) -> u64 {
246 unit.read_count()
251 }
252
253 #[cfg(not(esp32s2))]
254 pub unsafe fn configure_unit(unit: Unit, config: UnitConfig) {
263 unit.configure(config)
264 }
265
266 pub unsafe fn set_unit_value(unit: Unit, value: u64) {
277 unit.set_count(value)
278 }
279}
280
281#[cfg_attr(esp32s2, doc = "64-bit")]
283#[cfg_attr(not(esp32s2), doc = "52-bit")]
284#[derive(Copy, Clone, Debug, PartialEq, Eq)]
286#[cfg_attr(feature = "defmt", derive(defmt::Format))]
287pub enum Unit {
288 Unit0 = 0,
290 #[cfg(not(esp32s2))]
291 Unit1 = 1,
293}
294
295impl Unit {
296 #[inline]
297 fn channel(&self) -> u8 {
298 *self as _
299 }
300
301 #[cfg(not(esp32s2))]
302 fn configure(&self, config: UnitConfig) {
303 CONF_LOCK.lock(|| {
304 SYSTIMER::regs().conf().modify(|_, w| match config {
305 UnitConfig::Disabled => match self.channel() {
306 0 => w.timer_unit0_work_en().clear_bit(),
307 1 => w.timer_unit1_work_en().clear_bit(),
308 _ => unreachable!(),
309 },
310 UnitConfig::DisabledIfCpuIsStalled(cpu) => match self.channel() {
311 0 => {
312 w.timer_unit0_work_en().set_bit();
313 w.timer_unit0_core0_stall_en().bit(cpu == Cpu::ProCpu);
314 w.timer_unit0_core1_stall_en().bit(cpu != Cpu::ProCpu)
315 }
316 1 => {
317 w.timer_unit1_work_en().set_bit();
318 w.timer_unit1_core0_stall_en().bit(cpu == Cpu::ProCpu);
319 w.timer_unit1_core1_stall_en().bit(cpu != Cpu::ProCpu)
320 }
321 _ => unreachable!(),
322 },
323 UnitConfig::Enabled => match self.channel() {
324 0 => {
325 w.timer_unit0_work_en().set_bit();
326 w.timer_unit0_core0_stall_en().clear_bit();
327 w.timer_unit0_core1_stall_en().clear_bit()
328 }
329 1 => {
330 w.timer_unit1_work_en().set_bit();
331 w.timer_unit1_core0_stall_en().clear_bit();
332 w.timer_unit1_core1_stall_en().clear_bit()
333 }
334 _ => unreachable!(),
335 },
336 });
337 });
338 }
339
340 fn set_count(&self, value: u64) {
341 let systimer = SYSTIMER::regs();
342 #[cfg(not(esp32s2))]
343 {
344 let unitload = systimer.unitload(self.channel() as _);
345 let unit_load = systimer.unit_load(self.channel() as _);
346
347 unitload.hi().write(|w| w.load_hi().set((value << 32) as _));
348 unitload
349 .lo()
350 .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _));
351
352 unit_load.write(|w| w.load().set_bit());
353 }
354 #[cfg(esp32s2)]
355 {
356 systimer
357 .load_hi()
358 .write(|w| w.load_hi().set((value << 32) as _));
359 systimer
360 .load_lo()
361 .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _));
362
363 systimer.load().write(|w| w.load().set_bit());
364 }
365 }
366
367 #[inline]
368 fn read_count(&self) -> u64 {
369 let channel = self.channel() as usize;
372 let systimer = SYSTIMER::regs();
373
374 systimer.unit_op(channel).write(|w| w.update().set_bit());
375 while !systimer.unit_op(channel).read().value_valid().bit_is_set() {}
376
377 let unit_value = systimer.unit_value(channel);
383 let mut lo_prev = unit_value.lo().read().bits();
384 loop {
385 let lo = lo_prev;
386 let hi = unit_value.hi().read().bits();
387 lo_prev = unit_value.lo().read().bits();
388
389 if lo == lo_prev {
390 return ((hi as u64) << 32) | lo as u64;
391 }
392 }
393 }
394}
395
396#[derive(Debug, Clone, Copy, PartialEq, Eq)]
397#[cfg_attr(feature = "defmt", derive(defmt::Format))]
398enum Comparator {
399 Comparator0,
400 Comparator1,
401 Comparator2,
402}
403
404#[derive(Debug)]
406#[cfg_attr(feature = "defmt", derive(defmt::Format))]
407pub struct Alarm<'d> {
408 comp: Comparator,
409 unit: Unit,
410 _lifetime: PhantomData<&'d mut ()>,
411}
412
413impl Alarm<'_> {
414 const fn new(comp: Comparator) -> Self {
415 Alarm {
416 comp,
417 unit: Unit::Unit0,
418 _lifetime: PhantomData,
419 }
420 }
421
422 pub unsafe fn clone_unchecked(&self) -> Self {
429 Self {
430 comp: self.comp,
431 unit: self.unit,
432 _lifetime: PhantomData,
433 }
434 }
435
436 pub fn reborrow(&mut self) -> Alarm<'_> {
445 unsafe { self.clone_unchecked() }
446 }
447
448 #[inline]
450 fn channel(&self) -> u8 {
451 self.comp as u8
452 }
453
454 fn set_enable(&self, enable: bool) {
457 CONF_LOCK.lock(|| {
458 #[cfg(not(esp32s2))]
459 SYSTIMER::regs().conf().modify(|_, w| match self.channel() {
460 0 => w.target0_work_en().bit(enable),
461 1 => w.target1_work_en().bit(enable),
462 2 => w.target2_work_en().bit(enable),
463 _ => unreachable!(),
464 });
465 });
466
467 #[cfg(esp32s2)]
470 SYSTIMER::regs()
471 .target_conf(self.channel() as usize)
472 .modify(|_r, w| w.work_en().bit(enable));
473 }
474
475 fn is_enabled(&self) -> bool {
478 #[cfg(not(esp32s2))]
479 match self.channel() {
480 0 => SYSTIMER::regs().conf().read().target0_work_en().bit(),
481 1 => SYSTIMER::regs().conf().read().target1_work_en().bit(),
482 2 => SYSTIMER::regs().conf().read().target2_work_en().bit(),
483 _ => unreachable!(),
484 }
485
486 #[cfg(esp32s2)]
487 SYSTIMER::regs()
488 .target_conf(self.channel() as usize)
489 .read()
490 .work_en()
491 .bit()
492 }
493
494 #[cfg(not(esp32s2))]
496 pub fn set_unit(&self, unit: Unit) {
497 SYSTIMER::regs()
498 .target_conf(self.channel() as usize)
499 .modify(|_, w| w.timer_unit_sel().bit(matches!(unit, Unit::Unit1)));
500 }
501
502 fn set_mode(&self, mode: ComparatorMode) {
504 let is_period_mode = match mode {
505 ComparatorMode::Period => true,
506 ComparatorMode::Target => false,
507 };
508 SYSTIMER::regs()
509 .target_conf(self.channel() as usize)
510 .modify(|_, w| w.period_mode().bit(is_period_mode));
511 }
512
513 fn mode(&self) -> ComparatorMode {
516 if SYSTIMER::regs()
517 .target_conf(self.channel() as usize)
518 .read()
519 .period_mode()
520 .bit()
521 {
522 ComparatorMode::Period
523 } else {
524 ComparatorMode::Target
525 }
526 }
527
528 fn set_period(&self, value: u32) {
531 let systimer = SYSTIMER::regs();
532 let tconf = systimer.target_conf(self.channel() as usize);
533 unsafe { tconf.modify(|_, w| w.period().bits(value)) };
534 #[cfg(not(esp32s2))]
535 {
536 let comp_load = systimer.comp_load(self.channel() as usize);
537 comp_load.write(|w| w.load().set_bit());
538 }
539 }
540
541 fn set_target(&self, value: u64) {
543 let systimer = SYSTIMER::regs();
544 let target = systimer.trgt(self.channel() as usize);
545 target.hi().write(|w| w.hi().set((value >> 32) as u32));
546 target
547 .lo()
548 .write(|w| w.lo().set((value & 0xFFFF_FFFF) as u32));
549 #[cfg(not(esp32s2))]
550 {
551 let comp_load = systimer.comp_load(self.channel() as usize);
552 comp_load.write(|w| w.load().set_bit());
553 }
554 }
555
556 fn set_interrupt_handler(&self, handler: InterruptHandler) {
558 let interrupt = match self.channel() {
559 0 => Interrupt::SYSTIMER_TARGET0,
560 1 => Interrupt::SYSTIMER_TARGET1,
561 2 => Interrupt::SYSTIMER_TARGET2,
562 _ => unreachable!(),
563 };
564
565 for core in crate::system::Cpu::other() {
566 crate::interrupt::disable(core, interrupt);
567 }
568
569 #[cfg(not(esp32s2))]
570 interrupt::bind_handler(interrupt, handler);
571
572 #[cfg(esp32s2)]
573 {
574 static mut HANDLERS: [Option<crate::interrupt::IsrCallback>; 3] = [None, None, None];
581
582 #[crate::ram]
583 extern "C" fn _handle_interrupt<const CH: u8>() {
584 if SYSTIMER::regs().int_raw().read().target(CH).bit_is_set() {
585 let handler = unsafe { HANDLERS[CH as usize] };
586 if let Some(handler) = handler {
587 (handler.callback())();
588 }
589 }
590 }
591
592 let priority = handler.priority();
593 unsafe {
594 HANDLERS[self.channel() as usize] = Some(handler.handler());
595 }
596 let handler = match self.channel() {
597 0 => _handle_interrupt::<0>,
598 1 => _handle_interrupt::<1>,
599 2 => _handle_interrupt::<2>,
600 _ => unreachable!(),
601 };
602 interrupt::bind_handler(
603 interrupt,
604 crate::interrupt::InterruptHandler::new(handler, priority),
605 );
606 }
607 }
608}
609
610#[derive(Copy, Clone)]
612enum ComparatorMode {
613 Period,
615
616 Target,
619}
620
621impl super::Timer for Alarm<'_> {
622 fn start(&self) {
623 self.set_enable(true);
624 }
625
626 fn stop(&self) {
627 self.set_enable(false);
628 }
629
630 fn reset(&self) {
631 #[cfg(esp32s2)]
632 SYSTIMER::regs()
634 .step()
635 .modify(|_, w| unsafe { w.xtal_step().bits(0x1) });
636
637 #[cfg(not(esp32s2))]
638 SYSTIMER::regs()
639 .conf()
640 .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit());
641 }
642
643 fn is_running(&self) -> bool {
644 self.is_enabled()
645 }
646
647 fn now(&self) -> Instant {
648 let ticks = self.unit.read_count();
652
653 let us = SystemTimer::ticks_to_us(ticks);
654
655 Instant::from_ticks(us)
656 }
657
658 fn load_value(&self, value: Duration) -> Result<(), Error> {
659 let mode = self.mode();
660
661 let us = value.as_micros();
662 let ticks = SystemTimer::us_to_ticks(us);
663
664 if matches!(mode, ComparatorMode::Period) {
665 if (ticks & !SystemTimer::PERIOD_MASK) != 0 {
671 return Err(Error::InvalidTimeout);
672 }
673
674 self.set_period(ticks as u32);
675
676 self.set_mode(ComparatorMode::Target);
679 self.set_mode(ComparatorMode::Period);
680 } else {
681 #[cfg(not(esp32s2))]
687 if (ticks & !SystemTimer::BIT_MASK) != 0 {
688 return Err(Error::InvalidTimeout);
689 }
690
691 let v = self.unit.read_count();
692 let t = v + ticks;
693
694 self.set_target(t);
695 }
696
697 Ok(())
698 }
699
700 fn enable_auto_reload(&self, auto_reload: bool) {
701 let mode = if auto_reload {
703 ComparatorMode::Period
704 } else {
705 ComparatorMode::Target
706 };
707 self.set_mode(mode)
708 }
709
710 fn enable_interrupt(&self, state: bool) {
711 INT_ENA_LOCK.lock(|| {
712 SYSTIMER::regs()
713 .int_ena()
714 .modify(|_, w| w.target(self.channel()).bit(state));
715 });
716 }
717
718 fn clear_interrupt(&self) {
719 SYSTIMER::regs()
720 .int_clr()
721 .write(|w| w.target(self.channel()).clear_bit_by_one());
722 }
723
724 fn is_interrupt_set(&self) -> bool {
725 SYSTIMER::regs()
726 .int_raw()
727 .read()
728 .target(self.channel())
729 .bit_is_set()
730 }
731
732 fn async_interrupt_handler(&self) -> InterruptHandler {
733 match self.channel() {
734 0 => asynch::target0_handler,
735 1 => asynch::target1_handler,
736 2 => asynch::target2_handler,
737 _ => unreachable!(),
738 }
739 }
740
741 fn peripheral_interrupt(&self) -> Interrupt {
742 match self.channel() {
743 0 => Interrupt::SYSTIMER_TARGET0,
744 1 => Interrupt::SYSTIMER_TARGET1,
745 2 => Interrupt::SYSTIMER_TARGET2,
746 _ => unreachable!(),
747 }
748 }
749
750 fn set_interrupt_handler(&self, handler: InterruptHandler) {
751 self.set_interrupt_handler(handler)
752 }
753
754 fn waker(&self) -> &AtomicWaker {
755 asynch::waker(self)
756 }
757}
758
759impl crate::private::Sealed for Alarm<'_> {}
760
761static CONF_LOCK: RawMutex = RawMutex::new();
762static INT_ENA_LOCK: RawMutex = RawMutex::new();
763
764mod asynch {
766 use core::marker::PhantomData;
767
768 use procmacros::handler;
769
770 use super::*;
771 use crate::asynch::AtomicWaker;
772
773 const NUM_ALARMS: usize = 3;
774 static WAKERS: [AtomicWaker; NUM_ALARMS] = [const { AtomicWaker::new() }; NUM_ALARMS];
775
776 pub(super) fn waker(alarm: &Alarm<'_>) -> &'static AtomicWaker {
777 &WAKERS[alarm.channel() as usize]
778 }
779
780 #[inline]
781 fn handle_alarm(comp: Comparator) {
782 Alarm {
783 comp,
784 unit: Unit::Unit0,
785 _lifetime: PhantomData,
786 }
787 .enable_interrupt(false);
788
789 WAKERS[comp as usize].wake();
790 }
791
792 #[handler]
793 pub(crate) fn target0_handler() {
794 handle_alarm(Comparator::Comparator0);
795 }
796
797 #[handler]
798 pub(crate) fn target1_handler() {
799 handle_alarm(Comparator::Comparator1);
800 }
801
802 #[handler]
803 pub(crate) fn target2_handler() {
804 handle_alarm(Comparator::Comparator2);
805 }
806}
807
808#[cfg(etm_driver_supported)]
809pub mod etm {
810 #![cfg_attr(docsrs, procmacros::doc_replace)]
811 use super::*;
857
858 pub struct Event {
860 id: u8,
861 }
862
863 impl Event {
864 pub fn new(alarm: &Alarm<'_>) -> Self {
866 Self {
867 id: 50 + alarm.channel(),
868 }
869 }
870 }
871
872 impl crate::private::Sealed for Event {}
873
874 impl crate::etm::EtmEvent for Event {
875 fn id(&self) -> u8 {
876 self.id
877 }
878 }
879
880 pub(super) fn enable_etm() {
881 SYSTIMER::regs().conf().modify(|_, w| w.etm_en().set_bit());
882 }
883}