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_select! {
99 esp32s2 => {
100 pub const BIT_MASK: u64 = u64::MAX;
102 const PERIOD_MASK: u64 = 0x1FFF_FFFF;
104 }
105 _ => {
106 pub const BIT_MASK: u64 = 0xF_FFFF_FFFF_FFFF;
108 const PERIOD_MASK: u64 = 0x3FF_FFFF;
110 }
111 }
112
113 #[cfg(feature = "rt")]
115 pub(crate) fn init_timestamp_scaler() {
116 let systimer_rate = Self::ticks_per_second();
118
119 let packed_rate_and_method = if systimer_rate.is_multiple_of(1_000_000) {
121 let ticks_per_us = systimer_rate as u32 / 1_000_000;
122 if ticks_per_us.is_power_of_two() {
123 SHIFT_TIMESTAMP_FLAG | (ticks_per_us.ilog2() & SHIFT_MASK)
125 } else {
126 ticks_per_us
128 }
129 } else {
130 let multiplied_ticks_per_us = (systimer_rate * UNEVEN_MULTIPLIER as u64) / 1_000_000;
133 UNEVEN_DIVIDER_FLAG | (multiplied_ticks_per_us as u32)
134 };
135
136 unsafe {
139 let correction_ptr = &raw mut ESP_HAL_SYSTIMER_CORRECTION;
140 *correction_ptr = unwrap!(NonZeroU32::new(packed_rate_and_method));
141 }
142 }
143
144 #[inline]
145 pub(crate) fn ticks_to_us(ticks: u64) -> u64 {
146 let correction = unsafe { ESP_HAL_SYSTIMER_CORRECTION };
149
150 let correction = correction.get();
151 match correction & (SHIFT_TIMESTAMP_FLAG | UNEVEN_DIVIDER_FLAG) {
152 v if v == SHIFT_TIMESTAMP_FLAG => ticks >> (correction & SHIFT_MASK),
153 v if v == UNEVEN_DIVIDER_FLAG => {
154 let multiplied = if UNEVEN_MULTIPLIER.is_power_of_two() {
157 ticks << UNEVEN_MULTIPLIER.ilog2()
158 } else {
159 ticks * UNEVEN_MULTIPLIER as u64
160 };
161
162 let divider = correction & UNEVEN_DIVIDER_MASK;
163 multiplied / divider as u64
164 }
165 _ => ticks / correction as u64,
166 }
167 }
168
169 #[inline]
170 pub(crate) fn us_to_ticks(us: u64) -> u64 {
171 let correction = unsafe { ESP_HAL_SYSTIMER_CORRECTION };
174
175 let correction = correction.get();
176 match correction & (SHIFT_TIMESTAMP_FLAG | UNEVEN_DIVIDER_FLAG) {
177 v if v == SHIFT_TIMESTAMP_FLAG => us << (correction & SHIFT_MASK),
178 v if v == UNEVEN_DIVIDER_FLAG => {
179 let multiplier = correction & UNEVEN_DIVIDER_MASK;
180 let multiplied = us * multiplier as u64;
181
182 if UNEVEN_MULTIPLIER.is_power_of_two() {
185 multiplied >> UNEVEN_MULTIPLIER.ilog2()
186 } else {
187 multiplied / UNEVEN_MULTIPLIER as u64
188 }
189 }
190 _ => us * correction as u64,
191 }
192 }
193
194 #[inline]
196 pub fn ticks_per_second() -> u64 {
197 cfg_select! {
200 esp32c5 => {
201 16_000_000
203 }
204 _ => {
205 cfg_select! {
206 esp32s2 => crate::soc::clocks::apb_clk_frequency() as u64,
207 esp32h2 => (crate::soc::clocks::xtal_clk_frequency() / 2) as u64,
208 _ => (crate::soc::clocks::xtal_clk_frequency() * 10 / 25) as u64,
209 }
210 }
211 }
212 }
213
214 pub fn new(_systimer: SYSTIMER<'d>) -> Self {
216 if PeripheralClockControl::enable(PeripheralEnable::Systimer) {
218 PeripheralClockControl::reset(PeripheralEnable::Systimer);
219 } else {
220 PeripheralClockControl::disable(PeripheralEnable::Systimer);
223 }
224
225 #[cfg(etm_driver_supported)]
226 etm::enable_etm();
227
228 Self {
229 alarm0: Alarm::new(Comparator::Comparator0),
230 alarm1: Alarm::new(Comparator::Comparator1),
231 alarm2: Alarm::new(Comparator::Comparator2),
232 }
233 }
234
235 #[inline]
237 pub fn unit_value(unit: Unit) -> u64 {
238 unit.read_count()
243 }
244
245 #[cfg(not(esp32s2))]
246 pub unsafe fn configure_unit(unit: Unit, config: UnitConfig) {
255 unit.configure(config)
256 }
257
258 pub unsafe fn set_unit_value(unit: Unit, value: u64) {
269 unit.set_count(value)
270 }
271}
272
273#[cfg_attr(esp32s2, doc = "64-bit")]
275#[cfg_attr(not(esp32s2), doc = "52-bit")]
276#[derive(Copy, Clone, Debug, PartialEq, Eq)]
278#[cfg_attr(feature = "defmt", derive(defmt::Format))]
279pub enum Unit {
280 Unit0 = 0,
282 #[cfg(not(esp32s2))]
283 Unit1 = 1,
285}
286
287impl Unit {
288 #[inline]
289 fn channel(&self) -> u8 {
290 *self as _
291 }
292
293 #[cfg(not(esp32s2))]
294 fn configure(&self, config: UnitConfig) {
295 CONF_LOCK.lock(|| {
296 SYSTIMER::regs().conf().modify(|_, w| match config {
297 UnitConfig::Disabled => match self.channel() {
298 0 => w.timer_unit0_work_en().clear_bit(),
299 1 => w.timer_unit1_work_en().clear_bit(),
300 _ => unreachable!(),
301 },
302 UnitConfig::DisabledIfCpuIsStalled(cpu) => match self.channel() {
303 0 => {
304 w.timer_unit0_work_en().set_bit();
305 w.timer_unit0_core0_stall_en().bit(cpu == Cpu::ProCpu);
306 w.timer_unit0_core1_stall_en().bit(cpu != Cpu::ProCpu)
307 }
308 1 => {
309 w.timer_unit1_work_en().set_bit();
310 w.timer_unit1_core0_stall_en().bit(cpu == Cpu::ProCpu);
311 w.timer_unit1_core1_stall_en().bit(cpu != Cpu::ProCpu)
312 }
313 _ => unreachable!(),
314 },
315 UnitConfig::Enabled => match self.channel() {
316 0 => {
317 w.timer_unit0_work_en().set_bit();
318 w.timer_unit0_core0_stall_en().clear_bit();
319 w.timer_unit0_core1_stall_en().clear_bit()
320 }
321 1 => {
322 w.timer_unit1_work_en().set_bit();
323 w.timer_unit1_core0_stall_en().clear_bit();
324 w.timer_unit1_core1_stall_en().clear_bit()
325 }
326 _ => unreachable!(),
327 },
328 });
329 });
330 }
331
332 fn set_count(&self, value: u64) {
333 let systimer = SYSTIMER::regs();
334
335 let value_lo = (value & 0xFFFF_FFFF) as _;
336 let value_hi = (value >> 32) as _;
337
338 cfg_select! {
339 esp32s2 => {
340 systimer.load_hi().write(|w| w.load_hi().set(value_hi));
341 systimer.load_lo().write(|w| w.load_lo().set(value_lo));
342
343 systimer.load().write(|w| w.load().set_bit());
344 }
345 _ => {
346 let unitload = systimer.unitload(self.channel() as _);
347 let unit_load = systimer.unit_load(self.channel() as _);
348
349 unitload.hi().write(|w| w.load_hi().set(value_hi));
350 unitload.lo().write(|w| w.load_lo().set(value_lo));
351
352 unit_load.write(|w| w.load().set_bit());
353 }
354 }
355 }
356
357 #[inline]
358 fn read_count(&self) -> u64 {
359 let channel = self.channel() as usize;
362 let systimer = SYSTIMER::regs();
363
364 systimer.unit_op(channel).write(|w| w.update().set_bit());
365 while !systimer.unit_op(channel).read().value_valid().bit_is_set() {}
366
367 let unit_value = systimer.unit_value(channel);
373 let mut lo_prev = unit_value.lo().read().bits();
374 loop {
375 let lo = lo_prev;
376 let hi = unit_value.hi().read().bits();
377 lo_prev = unit_value.lo().read().bits();
378
379 if lo == lo_prev {
380 return ((hi as u64) << 32) | lo as u64;
381 }
382 }
383 }
384}
385
386#[derive(Debug, Clone, Copy, PartialEq, Eq)]
387#[cfg_attr(feature = "defmt", derive(defmt::Format))]
388enum Comparator {
389 Comparator0,
390 Comparator1,
391 Comparator2,
392}
393
394#[derive(Debug)]
396#[cfg_attr(feature = "defmt", derive(defmt::Format))]
397pub struct Alarm<'d> {
398 comp: Comparator,
399 unit: Unit,
400 _lifetime: PhantomData<&'d mut ()>,
401}
402
403impl Alarm<'_> {
404 const fn new(comp: Comparator) -> Self {
405 Alarm {
406 comp,
407 unit: Unit::Unit0,
408 _lifetime: PhantomData,
409 }
410 }
411
412 pub unsafe fn clone_unchecked(&self) -> Self {
419 Self {
420 comp: self.comp,
421 unit: self.unit,
422 _lifetime: PhantomData,
423 }
424 }
425
426 pub fn reborrow(&mut self) -> Alarm<'_> {
435 unsafe { self.clone_unchecked() }
436 }
437
438 #[inline]
440 fn channel(&self) -> u8 {
441 self.comp as u8
442 }
443
444 fn set_enable(&self, enable: bool) {
447 CONF_LOCK.lock(|| {
448 #[cfg(not(esp32s2))]
449 SYSTIMER::regs().conf().modify(|_, w| match self.channel() {
450 0 => w.target0_work_en().bit(enable),
451 1 => w.target1_work_en().bit(enable),
452 2 => w.target2_work_en().bit(enable),
453 _ => unreachable!(),
454 });
455 });
456
457 #[cfg(esp32s2)]
460 SYSTIMER::regs()
461 .target_conf(self.channel() as usize)
462 .modify(|_r, w| w.work_en().bit(enable));
463 }
464
465 fn is_enabled(&self) -> bool {
468 #[cfg(not(esp32s2))]
469 match self.channel() {
470 0 => SYSTIMER::regs().conf().read().target0_work_en().bit(),
471 1 => SYSTIMER::regs().conf().read().target1_work_en().bit(),
472 2 => SYSTIMER::regs().conf().read().target2_work_en().bit(),
473 _ => unreachable!(),
474 }
475
476 #[cfg(esp32s2)]
477 SYSTIMER::regs()
478 .target_conf(self.channel() as usize)
479 .read()
480 .work_en()
481 .bit()
482 }
483
484 #[cfg(not(esp32s2))]
486 pub fn set_unit(&self, unit: Unit) {
487 SYSTIMER::regs()
488 .target_conf(self.channel() as usize)
489 .modify(|_, w| w.timer_unit_sel().bit(matches!(unit, Unit::Unit1)));
490 }
491
492 fn set_mode(&self, mode: ComparatorMode) {
494 let is_period_mode = match mode {
495 ComparatorMode::Period => true,
496 ComparatorMode::Target => false,
497 };
498 SYSTIMER::regs()
499 .target_conf(self.channel() as usize)
500 .modify(|_, w| w.period_mode().bit(is_period_mode));
501 }
502
503 fn mode(&self) -> ComparatorMode {
506 if SYSTIMER::regs()
507 .target_conf(self.channel() as usize)
508 .read()
509 .period_mode()
510 .bit()
511 {
512 ComparatorMode::Period
513 } else {
514 ComparatorMode::Target
515 }
516 }
517
518 fn set_period(&self, value: u32) {
521 let systimer = SYSTIMER::regs();
522 let tconf = systimer.target_conf(self.channel() as usize);
523 unsafe { tconf.modify(|_, w| w.period().bits(value)) };
524 #[cfg(not(esp32s2))]
525 {
526 let comp_load = systimer.comp_load(self.channel() as usize);
527 comp_load.write(|w| w.load().set_bit());
528 }
529 }
530
531 fn set_target(&self, value: u64) {
533 let systimer = SYSTIMER::regs();
534 let target = systimer.trgt(self.channel() as usize);
535 target.hi().write(|w| w.hi().set((value >> 32) as u32));
536 target
537 .lo()
538 .write(|w| w.lo().set((value & 0xFFFF_FFFF) as u32));
539 #[cfg(not(esp32s2))]
540 {
541 let comp_load = systimer.comp_load(self.channel() as usize);
542 comp_load.write(|w| w.load().set_bit());
543 }
544 }
545
546 fn set_interrupt_handler(&self, handler: InterruptHandler) {
548 let interrupt = match self.channel() {
549 0 => Interrupt::SYSTIMER_TARGET0,
550 1 => Interrupt::SYSTIMER_TARGET1,
551 2 => Interrupt::SYSTIMER_TARGET2,
552 _ => unreachable!(),
553 };
554
555 for core in crate::system::Cpu::other() {
556 crate::interrupt::disable(core, interrupt);
557 }
558
559 #[cfg(not(esp32s2))]
560 interrupt::bind_handler(interrupt, handler);
561
562 #[cfg(esp32s2)]
563 {
564 static mut HANDLERS: [Option<crate::interrupt::IsrCallback>; 3] = [None, None, None];
571
572 #[crate::ram]
573 extern "C" fn _handle_interrupt<const CH: u8>() {
574 if SYSTIMER::regs().int_raw().read().target(CH).bit_is_set() {
575 let handler = unsafe { HANDLERS[CH as usize] };
576 if let Some(handler) = handler {
577 (handler.callback())();
578 }
579 }
580 }
581
582 let priority = handler.priority();
583 unsafe {
584 HANDLERS[self.channel() as usize] = Some(handler.handler());
585 }
586 let handler = match self.channel() {
587 0 => _handle_interrupt::<0>,
588 1 => _handle_interrupt::<1>,
589 2 => _handle_interrupt::<2>,
590 _ => unreachable!(),
591 };
592 interrupt::bind_handler(
593 interrupt,
594 crate::interrupt::InterruptHandler::new(handler, priority),
595 );
596 }
597 }
598}
599
600#[derive(Copy, Clone)]
602enum ComparatorMode {
603 Period,
605
606 Target,
609}
610
611impl super::Timer for Alarm<'_> {
612 fn start(&self) {
613 self.set_enable(true);
614 }
615
616 fn stop(&self) {
617 self.set_enable(false);
618 }
619
620 fn reset(&self) {
621 #[cfg(esp32s2)]
622 SYSTIMER::regs()
624 .step()
625 .modify(|_, w| unsafe { w.xtal_step().bits(0x1) });
626
627 #[cfg(not(esp32s2))]
628 SYSTIMER::regs()
629 .conf()
630 .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit());
631 }
632
633 fn is_running(&self) -> bool {
634 self.is_enabled()
635 }
636
637 fn now(&self) -> Instant {
638 let ticks = self.unit.read_count();
642
643 let us = SystemTimer::ticks_to_us(ticks);
644
645 Instant::from_ticks(us)
646 }
647
648 fn load_value(&self, value: Duration) -> Result<(), Error> {
649 let mode = self.mode();
650
651 let us = value.as_micros();
652 let ticks = SystemTimer::us_to_ticks(us);
653
654 if matches!(mode, ComparatorMode::Period) {
655 if (ticks & !SystemTimer::PERIOD_MASK) != 0 {
661 return Err(Error::InvalidTimeout);
662 }
663
664 self.set_period(ticks as u32);
665
666 self.set_mode(ComparatorMode::Target);
669 self.set_mode(ComparatorMode::Period);
670 } else {
671 #[cfg(not(esp32s2))]
677 if (ticks & !SystemTimer::BIT_MASK) != 0 {
678 return Err(Error::InvalidTimeout);
679 }
680
681 let v = self.unit.read_count();
682 let t = v + ticks;
683
684 self.set_target(t);
685 }
686
687 Ok(())
688 }
689
690 fn enable_auto_reload(&self, auto_reload: bool) {
691 let mode = if auto_reload {
693 ComparatorMode::Period
694 } else {
695 ComparatorMode::Target
696 };
697 self.set_mode(mode)
698 }
699
700 fn enable_interrupt(&self, state: bool) {
701 INT_ENA_LOCK.lock(|| {
702 SYSTIMER::regs()
703 .int_ena()
704 .modify(|_, w| w.target(self.channel()).bit(state));
705 });
706 }
707
708 fn clear_interrupt(&self) {
709 SYSTIMER::regs()
710 .int_clr()
711 .write(|w| w.target(self.channel()).clear_bit_by_one());
712 }
713
714 fn is_interrupt_set(&self) -> bool {
715 SYSTIMER::regs()
716 .int_raw()
717 .read()
718 .target(self.channel())
719 .bit_is_set()
720 }
721
722 fn async_interrupt_handler(&self) -> InterruptHandler {
723 match self.channel() {
724 0 => asynch::target0_handler,
725 1 => asynch::target1_handler,
726 2 => asynch::target2_handler,
727 _ => unreachable!(),
728 }
729 }
730
731 fn peripheral_interrupt(&self) -> Interrupt {
732 match self.channel() {
733 0 => Interrupt::SYSTIMER_TARGET0,
734 1 => Interrupt::SYSTIMER_TARGET1,
735 2 => Interrupt::SYSTIMER_TARGET2,
736 _ => unreachable!(),
737 }
738 }
739
740 fn set_interrupt_handler(&self, handler: InterruptHandler) {
741 self.set_interrupt_handler(handler)
742 }
743
744 fn waker(&self) -> &AtomicWaker {
745 asynch::waker(self)
746 }
747}
748
749impl crate::private::Sealed for Alarm<'_> {}
750
751static CONF_LOCK: RawMutex = RawMutex::new();
752static INT_ENA_LOCK: RawMutex = RawMutex::new();
753
754mod asynch {
756 use core::marker::PhantomData;
757
758 use procmacros::handler;
759
760 use super::*;
761 use crate::asynch::AtomicWaker;
762
763 const NUM_ALARMS: usize = 3;
764 static WAKERS: [AtomicWaker; NUM_ALARMS] = [const { AtomicWaker::new() }; NUM_ALARMS];
765
766 pub(super) fn waker(alarm: &Alarm<'_>) -> &'static AtomicWaker {
767 &WAKERS[alarm.channel() as usize]
768 }
769
770 #[inline]
771 fn handle_alarm(comp: Comparator) {
772 Alarm {
773 comp,
774 unit: Unit::Unit0,
775 _lifetime: PhantomData,
776 }
777 .enable_interrupt(false);
778
779 WAKERS[comp as usize].wake();
780 }
781
782 #[handler]
783 pub(crate) fn target0_handler() {
784 handle_alarm(Comparator::Comparator0);
785 }
786
787 #[handler]
788 pub(crate) fn target1_handler() {
789 handle_alarm(Comparator::Comparator1);
790 }
791
792 #[handler]
793 pub(crate) fn target2_handler() {
794 handle_alarm(Comparator::Comparator2);
795 }
796}
797
798#[cfg(etm_driver_supported)]
799pub mod etm {
800 #![cfg_attr(docsrs, procmacros::doc_replace)]
801 use super::*;
847
848 pub struct Event {
850 id: u8,
851 }
852
853 impl Event {
854 pub fn new(alarm: &Alarm<'_>) -> Self {
856 Self {
857 id: 50 + alarm.channel(),
858 }
859 }
860 }
861
862 impl crate::private::Sealed for Event {}
863
864 impl crate::etm::EtmEvent for Event {
865 fn id(&self) -> u8 {
866 self.id
867 }
868 }
869
870 pub(super) fn enable_etm() {
871 SYSTIMER::regs().conf().modify(|_, w| w.etm_en().set_bit());
872 }
873}