1
//! # System Timer (SYSTIMER)
2
//!
3
//! ## Overview
4
//! The System Timer is a
5
#![cfg_attr(esp32s2, doc = "64-bit")]
6
#![cfg_attr(not(esp32s2), doc = "52-bit")]
7
//! timer which can be used, for example, to generate tick interrupts for an
8
//! operating system, or simply as a general-purpose timer.
9
//!
10
//! ## Configuration
11
//!
12
//! The timer consists of two counters, `Unit0` and `Unit1`. The counter values
13
//! can be monitored by 3 [`Alarm`]s
14
//!
15
//! It is recommended to pass the [`Alarm`]s into a high level driver like
16
//! [`OneShotTimer`](super::OneShotTimer) and
17
//! [`PeriodicTimer`](super::PeriodicTimer). Using the System timer directly is
18
//! only possible through the low level [`Timer`](crate::timer::Timer) trait.
19

            
20
use core::{fmt::Debug, marker::PhantomData, num::NonZeroU32};
21

            
22
use esp_sync::RawMutex;
23

            
24
use super::{Error, Timer as _};
25
use 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
// System Timer is only clocked by XTAL divided by 2 or 2.5 (or RC_FAST_CLK which is not supported
34
// yet). Some XTAL options (most, in fact) divided by this value may not be an integer multiple of
35
// 1_000_000. Because the timer API works with microseconds, we need to correct for this. To avoid
36
// u64 division as much as possible, we use the two highest bits of the divisor to determine the
37
// division method.
38
// - If these flags are 0b00, we divide by the divisor.
39
// - If these flags are 0b01, we multiply by a constant before dividing by the divisor to improve
40
//   accuracy.
41
// - If these flags are 0b10, we shift the timestamp by the lower bits.
42
//
43
// Apart from the S2, the System Timer clock divider outputs a 16MHz timer clock when using
44
// the "default" XTAL configuration, so this method will commonly use the shifting based
45
// division.
46
//
47
// On a 26MHz C2, the divider outputs 10.4MHz. On a 32MHz C3, the divider outputs 12.8MHz.
48
//
49
// Time is unreliable before `init_timestamp_scaler` is called.
50
//
51
// Because a single crate version can have "rt" enabled, `ESP_HAL_SYSTIMER_CORRECTION` needs
52
// to be shared between versions. This aspect of this driver must be therefore kept stable.
53
#[unsafe(no_mangle)]
54
#[cfg(feature = "rt")]
55
static mut ESP_HAL_SYSTIMER_CORRECTION: NonZeroU32 = NonZeroU32::new(SHIFT_TIMESTAMP_FLAG).unwrap(); // Shift-by-0 = no-op
56

            
57
#[cfg(not(feature = "rt"))]
58
unsafe extern "Rust" {
59
    static mut ESP_HAL_SYSTIMER_CORRECTION: NonZeroU32;
60
}
61

            
62
const SHIFT_TIMESTAMP_FLAG: u32 = 0x8000_0000;
63
const SHIFT_MASK: u32 = 0x0000_FFFF;
64
// If the tick rate is not an integer number of microseconds: Since the divider is 2.5,
65
// and we assume XTAL is an integer number of MHz, we can multiply by 5, then divide by
66
// 5 to improve accuracy. On H2 the divider is 2, so we can multiply by 2, then divide by
67
// 2.
68
const UNEVEN_DIVIDER_FLAG: u32 = 0x4000_0000;
69
const UNEVEN_MULTIPLIER: u32 = if cfg!(esp32h2) { 2 } else { 5 };
70
const UNEVEN_DIVIDER_MASK: u32 = 0x0000_FFFF;
71

            
72
/// The configuration of a unit.
73
#[derive(Copy, Clone)]
74
pub enum UnitConfig {
75
    /// Unit is not counting.
76
    Disabled,
77

            
78
    /// Unit is counting unless the Cpu is stalled.
79
    DisabledIfCpuIsStalled(Cpu),
80

            
81
    /// Unit is counting.
82
    Enabled,
83
}
84

            
85
/// System Timer driver.
86
pub struct SystemTimer<'d> {
87
    /// Alarm 0.
88
    pub alarm0: Alarm<'d>,
89

            
90
    /// Alarm 1.
91
    pub alarm1: Alarm<'d>,
92

            
93
    /// Alarm 2.
94
    pub alarm2: Alarm<'d>,
95
}
96

            
97
impl<'d> SystemTimer<'d> {
98
    cfg_select! {
99
        esp32s2 => {
100
            /// Bitmask to be applied to the raw register value.
101
            pub const BIT_MASK: u64 = u64::MAX;
102
            // Bitmask to be applied to the raw period register value.
103
            const PERIOD_MASK: u64 = 0x1FFF_FFFF;
104
        }
105
        _ => {
106
            /// Bitmask to be applied to the raw register value.
107
            pub const BIT_MASK: u64 = 0xF_FFFF_FFFF_FFFF;
108
            // Bitmask to be applied to the raw period register value.
109
            const PERIOD_MASK: u64 = 0x3FF_FFFF;
110
        }
111
    }
112

            
113
    /// One-time initialization for the timestamp conversion/scaling.
114
    #[cfg(feature = "rt")]
115
    pub(crate) fn init_timestamp_scaler() {
116
        // Maximum tick rate is 80MHz (S2), which fits in a u32, so let's narrow the type.
117
        let systimer_rate = Self::ticks_per_second();
118

            
119
        // Select the optimal way to divide timestamps.
120
325
        let packed_rate_and_method = if systimer_rate.is_multiple_of(1_000_000) {
121
325
            let ticks_per_us = systimer_rate as u32 / 1_000_000;
122
325
            if ticks_per_us.is_power_of_two() {
123
                // Turn the division into a shift
124
325
                SHIFT_TIMESTAMP_FLAG | (ticks_per_us.ilog2() & SHIFT_MASK)
125
            } else {
126
                // We need to divide by an integer :(
127
                ticks_per_us
128
            }
129
        } else {
130
            // The rate is not a multiple of 1 MHz, we need to scale it up to prevent precision
131
            // loss.
132
            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
        // Safety: we only ever write ESP_HAL_SYSTIMER_CORRECTION in `init_timestamp_scaler`, which
137
        // is called once and only once during startup, from `time_init`.
138
        unsafe {
139
            let correction_ptr = &raw mut ESP_HAL_SYSTIMER_CORRECTION;
140
325
            *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
        // Safety: we only ever write ESP_HAL_SYSTIMER_CORRECTION in `init_timestamp_scaler`, which
147
        // is called once and only once during startup.
148
5735911
        let correction = unsafe { ESP_HAL_SYSTIMER_CORRECTION };
149

            
150
        let correction = correction.get();
151
5735911
        match correction & (SHIFT_TIMESTAMP_FLAG | UNEVEN_DIVIDER_FLAG) {
152
5735911
            v if v == SHIFT_TIMESTAMP_FLAG => ticks >> (correction & SHIFT_MASK),
153
            v if v == UNEVEN_DIVIDER_FLAG => {
154
                // Not only that, but we need to multiply the timestamp first otherwise
155
                // we'd count slower than the timer.
156
                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
        // Safety: we only ever write ESP_HAL_SYSTIMER_CORRECTION in `init_timestamp_scaler`, which
172
        // is called once and only once during startup.
173
16
        let correction = unsafe { ESP_HAL_SYSTIMER_CORRECTION };
174

            
175
        let correction = correction.get();
176
16
        match correction & (SHIFT_TIMESTAMP_FLAG | UNEVEN_DIVIDER_FLAG) {
177
16
            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
                // Not only that, but we need to divide the timestamp first otherwise
183
                // we'd return a slightly too-big value.
184
                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
    /// Returns the tick frequency of the underlying timer unit.
195
    #[inline]
196
    pub fn ticks_per_second() -> u64 {
197
        // FIXME: this requires a critical section. We can probably do better, if we can formulate
198
        // invariants well.
199
        cfg_select! {
200
            esp32c5 => {
201
                // Assuming SYSTIMER runs from XTAL, the hardware always runs at 16 MHz.
202
                16_000_000
203
            }
204
            _ => {
205
                cfg_select! {
206
                    esp32s2 => crate::soc::clocks::apb_clk_frequency() as u64,
207
                    any(esp32h2, esp32h4) => (crate::soc::clocks::xtal_clk_frequency() / 2) as u64,
208
325
                    _ => (crate::soc::clocks::xtal_clk_frequency() * 10 / 25) as u64,
209
                }
210
            }
211
        }
212
    }
213

            
214
    /// Creates a new instance.
215
8
    pub fn new(_systimer: SYSTIMER<'d>) -> Self {
216
        // Don't reset Systimer as it will break `time::Instant::now`, only enable it
217
8
        if PeripheralClockControl::enable(PeripheralEnable::Systimer) {
218
            PeripheralClockControl::reset(PeripheralEnable::Systimer);
219
        } else {
220
            // Refcount was more than 0. Decrement to avoid overflow because we don't handle
221
            // dropping the driver.
222
            PeripheralClockControl::disable(PeripheralEnable::Systimer);
223
        }
224

            
225
        #[cfg(etm_driver_supported)]
226
        etm::enable_etm();
227

            
228
8
        Self {
229
            alarm0: Alarm::new(Comparator::Comparator0),
230
            alarm1: Alarm::new(Comparator::Comparator1),
231
            alarm2: Alarm::new(Comparator::Comparator2),
232
        }
233
8
    }
234

            
235
    /// Returns the current count of the given unit in the System Timer.
236
    #[inline]
237
    pub fn unit_value(unit: Unit) -> u64 {
238
        // This should be safe to access from multiple contexts
239
        // worst case scenario the second accessor ends up reading
240
        // an older time stamp
241

            
242
        unit.read_count()
243
    }
244

            
245
    #[cfg(not(esp32s2))]
246
    /// Configures when this counter can run.
247
    /// It can be configured to stall or continue running when CPU stalls
248
    /// or enters on-chip-debugging mode.
249
    ///
250
    /// # Safety
251
    ///
252
    /// - Disabling a `Unit` while [`Alarm`]s are using it will affect the [`Alarm`]s operation
253
    /// - Disabling Unit0 will affect [`Instant::now`].
254
    pub unsafe fn configure_unit(unit: Unit, config: UnitConfig) {
255
        unit.configure(config)
256
    }
257

            
258
    /// Sets the value of the counter immediately. If the unit is at work,
259
    /// the counter will continue to count up from the new reloaded value.
260
    ///
261
    /// This can be used to load back the sleep time recorded by RTC timer
262
    /// via software after Light-sleep
263
    ///
264
    /// # Safety
265
    ///
266
    /// - Modifying a unit's count while [`Alarm`]s are using it may cause unexpected behavior
267
    /// - Any modification of the unit0 count will affect [`Instant::now`]
268
2
    pub unsafe fn set_unit_value(unit: Unit, value: u64) {
269
        unit.set_count(value)
270
2
    }
271
}
272

            
273
/// A
274
#[cfg_attr(esp32s2, doc = "64-bit")]
275
#[cfg_attr(not(esp32s2), doc = "52-bit")]
276
/// counter.
277
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
278
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
279
pub enum Unit {
280
    /// Unit 0
281
    Unit0 = 0,
282
    #[cfg(not(esp32s2))]
283
    /// Unit 1
284
    Unit1 = 1,
285
}
286

            
287
impl 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
        // This can be a shared reference as long as this type isn't Sync.
360

            
361
        let channel = self.channel() as usize;
362
        let systimer = SYSTIMER::regs();
363

            
364
        systimer.unit_op(channel).write(|w| w.update().set_bit());
365
5735911
        while !systimer.unit_op(channel).read().value_valid().bit_is_set() {}
366

            
367
        // Read LO, HI, then LO again, check that LO returns the same value.
368
        // This accounts for the case when an interrupt may happen between reading
369
        // HI and LO values (or the other core updates the counter mid-read), and this
370
        // function may get called from the ISR. In this case, the repeated read
371
        // will return consistent values.
372
        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
5735911
            if lo == lo_prev {
380
14
                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))]
388
enum Comparator {
389
    Comparator0,
390
    Comparator1,
391
    Comparator2,
392
}
393

            
394
/// An alarm unit.
395
#[derive(Debug)]
396
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
397
pub struct Alarm<'d> {
398
    comp: Comparator,
399
    unit: Unit,
400
    _lifetime: PhantomData<&'d mut ()>,
401
}
402

            
403
impl Alarm<'_> {
404
    const fn new(comp: Comparator) -> Self {
405
        Alarm {
406
            comp,
407
            unit: Unit::Unit0,
408
            _lifetime: PhantomData,
409
        }
410
    }
411

            
412
    /// Unsafely clone this peripheral reference.
413
    ///
414
    /// # Safety
415
    ///
416
    /// The caller must ensure that only one instance of this type is used at a
417
    /// time.
418
    pub unsafe fn clone_unchecked(&self) -> Self {
419
        Self {
420
12
            comp: self.comp,
421
12
            unit: self.unit,
422
            _lifetime: PhantomData,
423
        }
424
    }
425

            
426
    /// Creates a new peripheral reference with a shorter lifetime.
427
    ///
428
    /// Use this method to keep working with the peripheral after dropping the
429
    /// driver that consumes this.
430
    ///
431
    /// See [Peripheral singleton] section for more information.
432
    ///
433
    /// [Peripheral singleton]: crate#peripheral-singletons
434
    pub fn reborrow(&mut self) -> Alarm<'_> {
435
        unsafe { self.clone_unchecked() }
436
    }
437

            
438
    /// Returns the comparator's number.
439
    #[inline]
440
    fn channel(&self) -> u8 {
441
16
        self.comp as u8
442
    }
443

            
444
    /// Enables or disables the comparator. If enabled, this means
445
    /// it generates interrupts based on its configuration.
446
    fn set_enable(&self, enable: bool) {
447
        CONF_LOCK.lock(|| {
448
            #[cfg(not(esp32s2))]
449
16
            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
        // Note: The ESP32-S2 doesn't require a lock because each
458
        // comparator's enable bit in a different register.
459
        #[cfg(esp32s2)]
460
        SYSTIMER::regs()
461
            .target_conf(self.channel() as usize)
462
            .modify(|_r, w| w.work_en().bit(enable));
463
    }
464

            
465
    /// Returns whether the comparator has been enabled. This means
466
    /// it will generate interrupt based on its configuration.
467
    fn is_enabled(&self) -> bool {
468
        #[cfg(not(esp32s2))]
469
16
        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
    /// Sets the unit this comparator uses as a reference count.
485
    #[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
    /// Sets the mode of the comparator to be either target or periodic.
493
    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
    /// Returns the current mode of the comparator, which is either target or
504
    /// periodic.
505
    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
    /// Sets how often the comparator should generate an interrupt when in
519
    /// periodic mode.
520
    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
    /// Sets when the comparator should generate an interrupt in target mode.
532
    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
    /// Sets the interrupt handler for this comparator.
547
    fn set_interrupt_handler(&self, handler: InterruptHandler) {
548
7
        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
            // ESP32-S2 Systimer interrupts are edge triggered. Our interrupt
565
            // handler calls each of the handlers, regardless of which one triggered the
566
            // interrupt. This mess registers an intermediate handler that
567
            // checks if an interrupt is active before calling the associated
568
            // handler functions.
569

            
570
            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
/// The modes of a comparator.
601
#[derive(Copy, Clone)]
602
enum ComparatorMode {
603
    /// The comparator will generate interrupts periodically.
604
    Period,
605

            
606
    /// The comparator will generate an interrupt when the unit reaches the
607
    /// target.
608
    Target,
609
}
610

            
611
impl super::Timer for Alarm<'_> {
612
16
    fn start(&self) {
613
16
        self.set_enable(true);
614
16
    }
615

            
616
12
    fn stop(&self) {
617
12
        self.set_enable(false);
618
12
    }
619

            
620
16
    fn reset(&self) {
621
        #[cfg(esp32s2)]
622
        // Run at XTAL freq, not 80 * XTAL freq:
623
        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
16
    }
632

            
633
16
    fn is_running(&self) -> bool {
634
16
        self.is_enabled()
635
16
    }
636

            
637
    fn now(&self) -> Instant {
638
        // This should be safe to access from multiple contexts; worst case
639
        // scenario the second accessor ends up reading an older time stamp.
640

            
641
        let ticks = self.unit.read_count();
642

            
643
        let us = SystemTimer::ticks_to_us(ticks);
644

            
645
        Instant::from_ticks(us)
646
    }
647

            
648
16
    fn load_value(&self, value: Duration) -> Result<(), Error> {
649
16
        let mode = self.mode();
650

            
651
        let us = value.as_micros();
652
        let ticks = SystemTimer::us_to_ticks(us);
653

            
654
16
        if matches!(mode, ComparatorMode::Period) {
655
            // Period mode
656

            
657
            // The `SYSTIMER_TARGETx_PERIOD` field is 26-bits wide (or
658
            // 29-bits on the ESP32-S2), so we must ensure that the provided
659
            // value is not too wide:
660
2
            if (ticks & !SystemTimer::PERIOD_MASK) != 0 {
661
                return Err(Error::InvalidTimeout);
662
            }
663

            
664
            self.set_period(ticks as u32);
665

            
666
            // Clear and then set SYSTIMER_TARGETx_PERIOD_MODE to configure COMPx into
667
            // period mode
668
            self.set_mode(ComparatorMode::Target);
669
            self.set_mode(ComparatorMode::Period);
670
        } else {
671
            // Target mode
672

            
673
            // The counters/comparators are 52-bits wide (except on ESP32-S2,
674
            // which is 64-bits), so we must ensure that the provided value
675
            // is not too wide:
676
            #[cfg(not(esp32s2))]
677
14
            if (ticks & !SystemTimer::BIT_MASK) != 0 {
678
                return Err(Error::InvalidTimeout);
679
            }
680

            
681
14
            let v = self.unit.read_count();
682
14
            let t = v + ticks;
683

            
684
            self.set_target(t);
685
        }
686

            
687
        Ok(())
688
14
    }
689

            
690
16
    fn enable_auto_reload(&self, auto_reload: bool) {
691
        // If `auto_reload` is true use Period Mode, otherwise use Target Mode:
692
        let mode = if auto_reload {
693
            ComparatorMode::Period
694
        } else {
695
            ComparatorMode::Target
696
        };
697
16
        self.set_mode(mode)
698
16
    }
699

            
700
4
    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
4
    }
707

            
708
35
    fn clear_interrupt(&self) {
709
        SYSTIMER::regs()
710
            .int_clr()
711
            .write(|w| w.target(self.channel()).clear_bit_by_one());
712
35
    }
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
4
        self.set_interrupt_handler(handler)
742
4
    }
743

            
744
    fn waker(&self) -> &AtomicWaker {
745
        asynch::waker(self)
746
    }
747
}
748

            
749
impl crate::private::Sealed for Alarm<'_> {}
750

            
751
static CONF_LOCK: RawMutex = RawMutex::new();
752
static INT_ENA_LOCK: RawMutex = RawMutex::new();
753

            
754
// Async functionality of the system timer.
755
mod 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
16
        &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
12
        WAKERS[comp as usize].wake();
780
    }
781

            
782
    #[handler]
783
12
    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)]
799
pub mod etm {
800
    #![cfg_attr(docsrs, procmacros::doc_replace)]
801
    //! # Event Task Matrix Function
802
    //!
803
    //! ## Overview
804
    //!
805
    //! The system timer supports the Event Task Matrix (ETM) function, which
806
    //! allows the system timer’s ETM events to trigger any peripherals’ ETM
807
    //! tasks.
808
    //!
809
    //! The system timer can generate the following ETM events:
810
    //! - SYSTIMER_EVT_CNT_CMPx: Indicates the alarm pulses generated by COMPx
811
    //! ## Example
812
    //! ```rust, no_run
813
    //! # {before_snippet}
814
    //! # use esp_hal::timer::systimer::{etm::Event, SystemTimer};
815
    //! # use esp_hal::timer::PeriodicTimer;
816
    //! # use esp_hal::etm::Etm;
817
    //! # use esp_hal::gpio::{
818
    //! #     etm::{Channels, OutputConfig},
819
    //! #     Level,
820
    //! #     Pull,
821
    //! # };
822
    //! let syst = SystemTimer::new(peripherals.SYSTIMER);
823
    //! let etm = Etm::new(peripherals.ETM);
824
    //! let gpio_ext = Channels::new(peripherals.GPIO_SD);
825
    //! let alarm0 = syst.alarm0;
826
    //! let mut led = peripherals.GPIO1;
827
    //!
828
    //! let timer_event = Event::new(&alarm0);
829
    //! let led_task = gpio_ext.channel0_task.toggle(
830
    //!     led,
831
    //!     OutputConfig {
832
    //!         open_drain: false,
833
    //!         pull: Pull::None,
834
    //!         initial_state: Level::High,
835
    //!     },
836
    //! );
837
    //!
838
    //! let _configured_etm_channel = etm.channel0.setup(&timer_event, &led_task);
839
    //!
840
    //! let timer = PeriodicTimer::new(alarm0);
841
    //! // configure the timer as usual
842
    //! // when it fires it will toggle the GPIO
843
    //! # {after_snippet}
844
    //! ```
845

            
846
    use super::*;
847

            
848
    /// An ETM controlled SYSTIMER event.
849
    pub struct Event {
850
        id: u8,
851
    }
852

            
853
    impl Event {
854
        /// Creates an ETM event from the given [Alarm].
855
        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
}