1#![cfg_attr(esp32s2, doc = "64-bit")]
6#![cfg_attr(not(esp32s2), doc = "52-bit")]
7use core::fmt::Debug;
21
22use super::{Error, Timer as _};
23use crate::{
24 asynch::AtomicWaker,
25 interrupt::{self, InterruptHandler},
26 peripheral::Peripheral,
27 peripherals::{Interrupt, SYSTIMER},
28 sync::{lock, RawMutex},
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 {
48 pub alarm0: Alarm,
50
51 pub alarm1: Alarm,
53
54 pub alarm2: Alarm,
56}
57
58impl SystemTimer {
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) -> Self {
100 PeripheralClockControl::enable(PeripheralEnable::Systimer);
102
103 #[cfg(soc_etm)]
104 etm::enable_etm();
105
106 Self {
107 alarm0: Alarm::new(0),
108 alarm1: Alarm::new(1),
109 alarm2: Alarm::new(2),
110 }
111 }
112
113 pub fn unit_value(unit: Unit) -> u64 {
115 unit.read_count()
120 }
121
122 #[cfg(not(esp32s2))]
123 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) {
148 unit.set_count(value)
149 }
150}
151
152#[cfg_attr(esp32s2, doc = "64-bit")]
154#[cfg_attr(not(esp32s2), doc = "52-bit")]
155#[derive(Copy, Clone, Debug, PartialEq, Eq)]
157#[cfg_attr(feature = "defmt", derive(defmt::Format))]
158pub enum Unit {
159 Unit0 = 0,
161 #[cfg(not(esp32s2))]
162 Unit1 = 1,
164}
165
166impl Unit {
167 #[inline]
168 fn channel(&self) -> u8 {
169 *self as _
170 }
171
172 #[cfg(not(esp32s2))]
173 fn configure(&self, config: UnitConfig) {
174 lock(&CONF_LOCK, || {
175 SYSTIMER::regs().conf().modify(|_, w| match config {
176 UnitConfig::Disabled => match self.channel() {
177 0 => w.timer_unit0_work_en().clear_bit(),
178 1 => w.timer_unit1_work_en().clear_bit(),
179 _ => unreachable!(),
180 },
181 UnitConfig::DisabledIfCpuIsStalled(cpu) => match self.channel() {
182 0 => {
183 w.timer_unit0_work_en().set_bit();
184 w.timer_unit0_core0_stall_en().bit(cpu == Cpu::ProCpu);
185 w.timer_unit0_core1_stall_en().bit(cpu != Cpu::ProCpu)
186 }
187 1 => {
188 w.timer_unit1_work_en().set_bit();
189 w.timer_unit1_core0_stall_en().bit(cpu == Cpu::ProCpu);
190 w.timer_unit1_core1_stall_en().bit(cpu != Cpu::ProCpu)
191 }
192 _ => unreachable!(),
193 },
194 UnitConfig::Enabled => match self.channel() {
195 0 => {
196 w.timer_unit0_work_en().set_bit();
197 w.timer_unit0_core0_stall_en().clear_bit();
198 w.timer_unit0_core1_stall_en().clear_bit()
199 }
200 1 => {
201 w.timer_unit1_work_en().set_bit();
202 w.timer_unit1_core0_stall_en().clear_bit();
203 w.timer_unit1_core1_stall_en().clear_bit()
204 }
205 _ => unreachable!(),
206 },
207 });
208 });
209 }
210
211 fn set_count(&self, value: u64) {
212 let systimer = SYSTIMER::regs();
213 #[cfg(not(esp32s2))]
214 {
215 let unitload = systimer.unitload(self.channel() as _);
216 let unit_load = systimer.unit_load(self.channel() as _);
217
218 unitload.hi().write(|w| w.load_hi().set((value << 32) as _));
219 unitload
220 .lo()
221 .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _));
222
223 unit_load.write(|w| w.load().set_bit());
224 }
225 #[cfg(esp32s2)]
226 {
227 systimer
228 .load_hi()
229 .write(|w| w.load_hi().set((value << 32) as _));
230 systimer
231 .load_lo()
232 .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _));
233
234 systimer.load().write(|w| w.load().set_bit());
235 }
236 }
237
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)]
268#[cfg_attr(feature = "defmt", derive(defmt::Format))]
269pub struct Alarm {
270 comp: u8,
271 unit: Unit,
272}
273
274impl Alarm {
275 const fn new(comp: u8) -> Self {
276 Alarm {
277 comp,
278 unit: Unit::Unit0,
279 }
280 }
281
282 #[inline]
284 fn channel(&self) -> u8 {
285 self.comp
286 }
287
288 fn set_enable(&self, enable: bool) {
291 lock(&CONF_LOCK, || {
292 #[cfg(not(esp32s2))]
293 SYSTIMER::regs().conf().modify(|_, w| match self.channel() {
294 0 => w.target0_work_en().bit(enable),
295 1 => w.target1_work_en().bit(enable),
296 2 => w.target2_work_en().bit(enable),
297 _ => unreachable!(),
298 });
299 });
300
301 #[cfg(esp32s2)]
304 SYSTIMER::regs()
305 .target_conf(self.channel() as usize)
306 .modify(|_r, w| w.work_en().bit(enable));
307 }
308
309 fn is_enabled(&self) -> bool {
312 #[cfg(not(esp32s2))]
313 match self.channel() {
314 0 => SYSTIMER::regs().conf().read().target0_work_en().bit(),
315 1 => SYSTIMER::regs().conf().read().target1_work_en().bit(),
316 2 => SYSTIMER::regs().conf().read().target2_work_en().bit(),
317 _ => unreachable!(),
318 }
319
320 #[cfg(esp32s2)]
321 SYSTIMER::regs()
322 .target_conf(self.channel() as usize)
323 .read()
324 .work_en()
325 .bit()
326 }
327
328 #[cfg(not(esp32s2))]
330 pub fn set_unit(&self, unit: Unit) {
331 SYSTIMER::regs()
332 .target_conf(self.channel() as usize)
333 .modify(|_, w| w.timer_unit_sel().bit(matches!(unit, Unit::Unit1)));
334 }
335
336 fn set_mode(&self, mode: ComparatorMode) {
338 let is_period_mode = match mode {
339 ComparatorMode::Period => true,
340 ComparatorMode::Target => false,
341 };
342 SYSTIMER::regs()
343 .target_conf(self.channel() as usize)
344 .modify(|_, w| w.period_mode().bit(is_period_mode));
345 }
346
347 fn mode(&self) -> ComparatorMode {
350 if SYSTIMER::regs()
351 .target_conf(self.channel() as usize)
352 .read()
353 .period_mode()
354 .bit()
355 {
356 ComparatorMode::Period
357 } else {
358 ComparatorMode::Target
359 }
360 }
361
362 fn set_period(&self, value: u32) {
365 let systimer = SYSTIMER::regs();
366 let tconf = systimer.target_conf(self.channel() as usize);
367 unsafe { tconf.modify(|_, w| w.period().bits(value)) };
368 #[cfg(not(esp32s2))]
369 {
370 let comp_load = systimer.comp_load(self.channel() as usize);
371 comp_load.write(|w| w.load().set_bit());
372 }
373 }
374
375 fn set_target(&self, value: u64) {
377 let systimer = SYSTIMER::regs();
378 let target = systimer.trgt(self.channel() as usize);
379 target.hi().write(|w| w.hi().set((value >> 32) as u32));
380 target
381 .lo()
382 .write(|w| w.lo().set((value & 0xFFFF_FFFF) as u32));
383 #[cfg(not(esp32s2))]
384 {
385 let comp_load = systimer.comp_load(self.channel() as usize);
386 comp_load.write(|w| w.load().set_bit());
387 }
388 }
389
390 fn set_interrupt_handler(&self, handler: InterruptHandler) {
392 let interrupt = match self.channel() {
393 0 => Interrupt::SYSTIMER_TARGET0,
394 1 => Interrupt::SYSTIMER_TARGET1,
395 2 => Interrupt::SYSTIMER_TARGET2,
396 _ => unreachable!(),
397 };
398
399 for core in crate::system::Cpu::other() {
400 crate::interrupt::disable(core, interrupt);
401 }
402
403 #[cfg(not(esp32s2))]
404 unsafe {
405 interrupt::bind_interrupt(interrupt, handler.handler());
406 }
407
408 #[cfg(esp32s2)]
409 {
410 static mut HANDLERS: [Option<extern "C" fn()>; 3] = [None, None, None];
417
418 #[crate::ram]
419 unsafe extern "C" fn _handle_interrupt<const CH: u8>() {
420 if SYSTIMER::regs().int_raw().read().target(CH).bit_is_set() {
421 let handler = unsafe { HANDLERS[CH as usize] };
422 if let Some(handler) = handler {
423 handler();
424 }
425 }
426 }
427
428 unsafe {
429 HANDLERS[self.channel() as usize] = Some(handler.handler());
430 let handler = match self.channel() {
431 0 => _handle_interrupt::<0>,
432 1 => _handle_interrupt::<1>,
433 2 => _handle_interrupt::<2>,
434 _ => unreachable!(),
435 };
436 interrupt::bind_interrupt(interrupt, handler);
437 }
438 }
439 unwrap!(interrupt::enable(interrupt, handler.priority()));
440 }
441}
442
443#[derive(Copy, Clone)]
445enum ComparatorMode {
446 Period,
448
449 Target,
452}
453
454impl super::Timer for Alarm {
455 fn start(&self) {
456 self.set_enable(true);
457 }
458
459 fn stop(&self) {
460 self.set_enable(false);
461 }
462
463 fn reset(&self) {
464 #[cfg(esp32s2)]
465 SYSTIMER::regs()
467 .step()
468 .modify(|_, w| unsafe { w.xtal_step().bits(0x1) });
469
470 #[cfg(not(esp32s2))]
471 SYSTIMER::regs()
472 .conf()
473 .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit());
474 }
475
476 fn is_running(&self) -> bool {
477 self.is_enabled()
478 }
479
480 fn now(&self) -> Instant {
481 let ticks = self.unit.read_count();
485
486 let us = ticks / (SystemTimer::ticks_per_second() / 1_000_000);
487
488 Instant::from_ticks(us)
489 }
490
491 fn load_value(&self, value: Duration) -> Result<(), Error> {
492 let mode = self.mode();
493
494 let us = value.as_micros();
495 let ticks = us * (SystemTimer::ticks_per_second() / 1_000_000);
496
497 if matches!(mode, ComparatorMode::Period) {
498 if (ticks & !SystemTimer::PERIOD_MASK) != 0 {
504 return Err(Error::InvalidTimeout);
505 }
506
507 self.set_period(ticks as u32);
508
509 self.set_mode(ComparatorMode::Target);
512 self.set_mode(ComparatorMode::Period);
513 } else {
514 #[cfg(not(esp32s2))]
520 if (ticks & !SystemTimer::BIT_MASK) != 0 {
521 return Err(Error::InvalidTimeout);
522 }
523
524 let v = self.unit.read_count();
525 let t = v + ticks;
526
527 self.set_target(t);
528 }
529
530 Ok(())
531 }
532
533 fn enable_auto_reload(&self, auto_reload: bool) {
534 let mode = if auto_reload {
536 ComparatorMode::Period
537 } else {
538 ComparatorMode::Target
539 };
540 self.set_mode(mode)
541 }
542
543 fn enable_interrupt(&self, state: bool) {
544 lock(&INT_ENA_LOCK, || {
545 SYSTIMER::regs()
546 .int_ena()
547 .modify(|_, w| w.target(self.channel()).bit(state));
548 });
549 }
550
551 fn clear_interrupt(&self) {
552 SYSTIMER::regs()
553 .int_clr()
554 .write(|w| w.target(self.channel()).clear_bit_by_one());
555 }
556
557 fn is_interrupt_set(&self) -> bool {
558 SYSTIMER::regs()
559 .int_raw()
560 .read()
561 .target(self.channel())
562 .bit_is_set()
563 }
564
565 fn async_interrupt_handler(&self) -> InterruptHandler {
566 match self.channel() {
567 0 => asynch::target0_handler,
568 1 => asynch::target1_handler,
569 2 => asynch::target2_handler,
570 _ => unreachable!(),
571 }
572 }
573
574 fn peripheral_interrupt(&self) -> Interrupt {
575 match self.channel() {
576 0 => Interrupt::SYSTIMER_TARGET0,
577 1 => Interrupt::SYSTIMER_TARGET1,
578 2 => Interrupt::SYSTIMER_TARGET2,
579 _ => unreachable!(),
580 }
581 }
582
583 fn set_interrupt_handler(&self, handler: InterruptHandler) {
584 self.set_interrupt_handler(handler)
585 }
586
587 fn waker(&self) -> &AtomicWaker {
588 asynch::waker(self)
589 }
590}
591
592impl Peripheral for Alarm {
593 type P = Self;
594
595 #[inline]
596 unsafe fn clone_unchecked(&self) -> Self::P {
597 Alarm {
598 comp: self.comp,
599 unit: self.unit,
600 }
601 }
602}
603
604impl crate::private::Sealed for Alarm {}
605
606static CONF_LOCK: RawMutex = RawMutex::new();
607static INT_ENA_LOCK: RawMutex = RawMutex::new();
608
609mod asynch {
611 use procmacros::handler;
612
613 use super::*;
614 use crate::asynch::AtomicWaker;
615
616 const NUM_ALARMS: usize = 3;
617 static WAKERS: [AtomicWaker; NUM_ALARMS] = [const { AtomicWaker::new() }; NUM_ALARMS];
618
619 pub(super) fn waker(alarm: &Alarm) -> &AtomicWaker {
620 &WAKERS[alarm.channel() as usize]
621 }
622
623 #[inline]
624 fn handle_alarm(alarm: u8) {
625 Alarm {
626 comp: alarm,
627 unit: Unit::Unit0,
628 }
629 .enable_interrupt(false);
630
631 WAKERS[alarm as usize].wake();
632 }
633
634 #[handler]
635 pub(crate) fn target0_handler() {
636 handle_alarm(0);
637 }
638
639 #[handler]
640 pub(crate) fn target1_handler() {
641 handle_alarm(1);
642 }
643
644 #[handler]
645 pub(crate) fn target2_handler() {
646 handle_alarm(2);
647 }
648}
649
650#[cfg(soc_etm)]
651pub mod etm {
652 #![doc = crate::before_snippet!()]
666 use super::*;
701
702 pub struct Event {
704 id: u8,
705 }
706
707 impl Event {
708 pub fn new(alarm: &Alarm) -> Self {
710 Self {
711 id: 50 + alarm.channel(),
712 }
713 }
714 }
715
716 impl crate::private::Sealed for Event {}
717
718 impl crate::etm::EtmEvent for Event {
719 fn id(&self) -> u8 {
720 self.id
721 }
722 }
723
724 pub(super) fn enable_etm() {
725 SYSTIMER::regs().conf().modify(|_, w| w.etm_en().set_bit());
726 }
727}