1
#![cfg_attr(docsrs, procmacros::doc_replace)]
2
//! # Timer Group (TIMG)
3
//!
4
//! ## Overview
5
//!
6
//! The Timer Group (TIMG) peripherals contain one or more general-purpose
7
//! timers, plus one or more watchdog timers.
8
//!
9
//! The general-purpose timers are based on a 16-bit pre-scaler and a 54-bit
10
//! auto-reload-capable up-down counter.
11
//!
12
//! ## Configuration
13
//!
14
//! The timers have configurable alarms, which are triggered when the internal
15
//! counter of the timers reaches a specific target value. The timers are
16
//! clocked using the APB clock source.
17
//!
18
//! Typically, a general-purpose timer can be used in scenarios such as:
19
//!
20
//! - Generate period alarms; trigger events periodically
21
//! - Generate one-shot alarms; trigger events once
22
//! - Free-running; fetching a high-resolution timestamp on demand
23
//!
24
//! ## Examples
25
//!
26
//! ### General-purpose Timer
27
//!
28
//! ```rust, no_run
29
//! # {before_snippet}
30
//! use esp_hal::timer::{Timer, timg::TimerGroup};
31
//!
32
//! let timg0 = TimerGroup::new(peripherals.TIMG0);
33
//! let timer0 = timg0.timer0;
34
//!
35
//! // Get the current timestamp, in microseconds:
36
//! let now = timer0.now();
37
//!
38
//! // Wait for timeout:
39
//! timer0.load_value(Duration::from_secs(1));
40
//! timer0.start();
41
//!
42
//! while !timer0.is_interrupt_set() {
43
//!     // Wait
44
//! }
45
//!
46
//! timer0.clear_interrupt();
47
//! # {after_snippet}
48
//! ```
49
//!
50
//! ### Watchdog Timer
51
//! ```rust, no_run
52
//! # {before_snippet}
53
//! use esp_hal::timer::{
54
//!     Timer,
55
//!     timg::{MwdtStage, TimerGroup},
56
//! };
57
//!
58
//! let timg0 = TimerGroup::new(peripherals.TIMG0);
59
//! let mut wdt = timg0.wdt;
60
//!
61
//! wdt.set_timeout(MwdtStage::Stage0, Duration::from_millis(5_000));
62
//! wdt.enable();
63
//!
64
//! loop {
65
//!     wdt.feed();
66
//! }
67
//! # }
68
//! ```
69
use core::marker::PhantomData;
70

            
71
use super::Error;
72
#[cfg(timergroup_timg1)]
73
use crate::peripherals::TIMG1;
74
#[cfg(soc_has_clock_node_timg_function_clock)]
75
use crate::soc::clocks::TimgFunctionClockConfig;
76
#[cfg(soc_has_clock_node_timg_wdt_clock)]
77
use crate::soc::clocks::TimgWdtClockConfig;
78
use crate::{
79
    asynch::AtomicWaker,
80
    interrupt::{self, InterruptConfigurable, InterruptHandler},
81
    pac::timg0::RegisterBlock,
82
    peripherals::{Interrupt, TIMG0},
83
    private::Sealed,
84
    soc::clocks,
85
    system::PeripheralClockControl,
86
    time::{Duration, Instant, Rate},
87
};
88

            
89
const NUM_TIMG: usize = 1 + cfg!(timergroup_timg1) as usize;
90

            
91
cfg_select! {
92
    // We need no locks when a TIMG has a single timer, and we don't need locks for ESP32
93
    // and S2 where the effective interrupt enable register (config) is not shared between
94
    // the timers.
95
    all(timergroup_timg_has_timer1, not(any(esp32, esp32s2))) => {
96
        use esp_sync::RawMutex;
97
        static INT_ENA_LOCK: [RawMutex; NUM_TIMG] = [const { RawMutex::new() }; NUM_TIMG];
98
    }
99
    _ => {}
100
}
101

            
102
#[procmacros::doc_replace(
103
    "timers" => {
104
        cfg(timergroup_timg_has_timer1) => "2 timers",
105
        _ => "a general purpose timer",
106
    }
107
)]
108
/// A timer group consisting of __timers__ and a watchdog timer.
109
pub struct TimerGroup<'d, T>
110
where
111
    T: TimerGroupInstance + 'd,
112
{
113
    _timer_group: PhantomData<T>,
114
    /// Timer 0
115
    pub timer0: Timer<'d>,
116
    /// Timer 1
117
    #[cfg(timergroup_timg_has_timer1)]
118
    pub timer1: Timer<'d>,
119
    /// Watchdog timer
120
    pub wdt: Wdt<T>,
121
}
122

            
123
#[doc(hidden)]
124
pub trait TimerGroupInstance {
125
    fn id() -> u8;
126
    fn register_block() -> *const RegisterBlock;
127
    #[cfg(soc_has_clock_node_timg_function_clock)]
128
    fn clock_instance() -> clocks::TimgInstance;
129
    fn peripheral() -> crate::system::Peripheral;
130
    fn wdt_interrupt() -> Interrupt;
131
}
132

            
133
#[cfg(timergroup_timg0)]
134
impl TimerGroupInstance for TIMG0<'_> {
135
    fn id() -> u8 {
136
        0
137
    }
138

            
139
    #[inline(always)]
140
    fn register_block() -> *const RegisterBlock {
141
        Self::regs()
142
    }
143

            
144
    #[cfg(soc_has_clock_node_timg_function_clock)]
145
    fn clock_instance() -> clocks::TimgInstance {
146
        clocks::TimgInstance::Timg0
147
    }
148

            
149
    fn peripheral() -> crate::system::Peripheral {
150
        crate::system::Peripheral::Timg0
151
    }
152

            
153
    fn wdt_interrupt() -> Interrupt {
154
        Interrupt::TG0_WDT_LEVEL
155
    }
156
}
157

            
158
#[cfg(timergroup_timg1)]
159
impl TimerGroupInstance for crate::peripherals::TIMG1<'_> {
160
    fn id() -> u8 {
161
        1
162
    }
163

            
164
    #[inline(always)]
165
    fn register_block() -> *const RegisterBlock {
166
        Self::regs()
167
    }
168

            
169
    #[cfg(soc_has_clock_node_timg_function_clock)]
170
    fn clock_instance() -> clocks::TimgInstance {
171
        clocks::TimgInstance::Timg1
172
    }
173

            
174
    fn peripheral() -> crate::system::Peripheral {
175
        crate::system::Peripheral::Timg1
176
    }
177

            
178
    fn wdt_interrupt() -> Interrupt {
179
        Interrupt::TG1_WDT_LEVEL
180
    }
181
}
182

            
183
impl<'d, T> TimerGroup<'d, T>
184
where
185
    T: TimerGroupInstance + 'd,
186
{
187
    /// Creates a new instance of [`TimerGroup`] in blocking mode.
188
39
    pub fn new(_timer_group: T) -> Self {
189
        // TODO: use PeripheralGuard
190
74
        if PeripheralClockControl::enable(T::peripheral()) {
191
4
            PeripheralClockControl::reset(T::peripheral());
192
        } else {
193
            // Refcount was more than 0. Decrement to avoid overflow because we don't handle
194
            // dropping the driver.
195
74
            PeripheralClockControl::disable(T::peripheral());
196
        }
197

            
198
        #[cfg(soc_has_clock_node_timg_function_clock)]
199
        clocks::ClockTree::with(|clocks| {
200
            let clock = T::clock_instance();
201
74
            clock.configure_function_clock(clocks, TimgFunctionClockConfig::default());
202
74
            clock.request_function_clock(clocks);
203
        });
204

            
205
        Self {
206
            _timer_group: PhantomData,
207
            timer0: Timer {
208
                timer: TimerId::Timer0,
209
                tg: T::id(),
210
                register_block: T::register_block(),
211
                _lifetime: PhantomData,
212
            },
213
            #[cfg(timergroup_timg_has_timer1)]
214
            timer1: Timer {
215
                timer: TimerId::Timer1,
216
                tg: T::id(),
217
                register_block: T::register_block(),
218
                _lifetime: PhantomData,
219
            },
220
            wdt: Wdt::new(),
221
        }
222
39
    }
223
}
224

            
225
impl super::Timer for Timer<'_> {
226
    fn start(&self) {
227
443
        self.set_counter_active(false);
228
        self.set_alarm_active(false);
229

            
230
        self.reset_counter();
231
        self.set_counter_decrementing(false);
232

            
233
        self.set_counter_active(true);
234
        self.set_alarm_active(true);
235
443
    }
236

            
237
    fn stop(&self) {
238
426
        self.set_counter_active(false);
239
426
    }
240

            
241
    fn reset(&self) {
242
495
        self.reset_counter()
243
495
    }
244

            
245
    fn is_running(&self) -> bool {
246
495
        self.is_counter_active()
247
495
    }
248

            
249
    fn now(&self) -> Instant {
250
        self.now()
251
    }
252

            
253
495
    fn load_value(&self, value: Duration) -> Result<(), Error> {
254
495
        self.load_value(value)
255
443
    }
256

            
257
    fn enable_auto_reload(&self, auto_reload: bool) {
258
495
        self.set_auto_reload(auto_reload)
259
495
    }
260

            
261
    fn enable_interrupt(&self, state: bool) {
262
88
        self.set_interrupt_enabled(state);
263
64
    }
264

            
265
    fn clear_interrupt(&self) {
266
853
        self.clear_interrupt()
267
853
    }
268

            
269
    fn is_interrupt_set(&self) -> bool {
270
48
        self.is_interrupt_set()
271
    }
272

            
273
    fn async_interrupt_handler(&self) -> InterruptHandler {
274
6
        match (self.timer_group(), self.timer_number()) {
275
            (0, 0) => asynch::timg0_timer0_handler,
276
            #[cfg(timergroup_timg_has_timer1)]
277
            (0, 1) => asynch::timg0_timer1_handler,
278
            #[cfg(timergroup_timg1)]
279
            (1, 0) => asynch::timg1_timer0_handler,
280
            #[cfg(all(timergroup_timg_has_timer1, timergroup_timg1))]
281
            (1, 1) => asynch::timg1_timer1_handler,
282
            _ => unreachable!(),
283
        }
284
    }
285

            
286
    fn peripheral_interrupt(&self) -> Interrupt {
287
        match (self.timer_group(), self.timer_number()) {
288
            (0, 0) => Interrupt::TG0_T0_LEVEL,
289
            #[cfg(timergroup_timg_has_timer1)]
290
            (0, 1) => Interrupt::TG0_T1_LEVEL,
291
            #[cfg(timergroup_timg1)]
292
            (1, 0) => Interrupt::TG1_T0_LEVEL,
293
            #[cfg(all(timergroup_timg_has_timer1, timergroup_timg1))]
294
            (1, 1) => Interrupt::TG1_T1_LEVEL,
295
            _ => unreachable!(),
296
        }
297
    }
298

            
299
    fn set_interrupt_handler(&self, handler: InterruptHandler) {
300
        self.set_interrupt_handler(handler)
301
    }
302

            
303
    fn waker(&self) -> &AtomicWaker {
304
        asynch::waker(self)
305
    }
306
}
307

            
308
/// A timer within a Timer Group.
309
#[derive(Debug)]
310
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
311
pub struct Timer<'d> {
312
    register_block: *const RegisterBlock,
313
    _lifetime: PhantomData<&'d mut ()>,
314
    timer: TimerId,
315
    tg: u8,
316
}
317

            
318
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
319
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
320
enum TimerId {
321
    Timer0,
322
    #[cfg(timergroup_timg_has_timer1)]
323
    Timer1,
324
}
325

            
326
impl Sealed for Timer<'_> {}
327
unsafe impl Send for Timer<'_> {}
328

            
329
/// Timer peripheral instance
330
impl Timer<'_> {
331
    /// Unsafely clone this peripheral reference.
332
    ///
333
    /// # Safety
334
    ///
335
    /// The caller must ensure that only one instance of this type is used at a
336
    /// time.
337
    pub unsafe fn clone_unchecked(&self) -> Self {
338
        Self {
339
24
            register_block: self.register_block,
340
            timer: self.timer,
341
24
            tg: self.tg,
342
            _lifetime: PhantomData,
343
        }
344
    }
345

            
346
    /// Creates a new peripheral reference with a shorter lifetime.
347
    ///
348
    /// Use this method to keep working with the peripheral after dropping the
349
    /// driver that consumes this.
350
    ///
351
    /// See [Peripheral singleton] section for more information.
352
    ///
353
    /// [Peripheral singleton]: crate#peripheral-singletons
354
    pub fn reborrow(&mut self) -> Timer<'_> {
355
        unsafe { self.clone_unchecked() }
356
    }
357

            
358
64
    pub(crate) fn set_interrupt_handler(&self, handler: InterruptHandler) {
359
64
        let interrupt = match (self.timer_group(), self.timer_number()) {
360
            (0, 0) => Interrupt::TG0_T0_LEVEL,
361
            #[cfg(timergroup_timg_has_timer1)]
362
            (0, 1) => Interrupt::TG0_T1_LEVEL,
363
            #[cfg(timergroup_timg1)]
364
            (1, 0) => Interrupt::TG1_T0_LEVEL,
365
            #[cfg(all(timergroup_timg_has_timer1, timergroup_timg1))]
366
            (1, 1) => Interrupt::TG1_T1_LEVEL,
367
            _ => unreachable!(),
368
        };
369

            
370
        for core in crate::system::Cpu::other() {
371
            crate::interrupt::disable(core, interrupt);
372
        }
373
        interrupt::bind_handler(interrupt, handler);
374
64
    }
375

            
376
    fn register_block(&self) -> &RegisterBlock {
377
        unsafe { &*self.register_block }
378
    }
379

            
380
    fn timer_group(&self) -> u8 {
381
112
        self.tg
382
    }
383

            
384
    fn timer_number(&self) -> u8 {
385
        self.timer as u8
386
    }
387

            
388
    fn t(&self) -> &crate::pac::timg0::T {
389
        self.register_block().t(self.timer_number().into())
390
    }
391

            
392
    fn reset_counter(&self) {
393
        let t = self.t();
394

            
395
        t.loadlo().write(|w| unsafe { w.load_lo().bits(0) });
396
        t.loadhi().write(|w| unsafe { w.load_hi().bits(0) });
397

            
398
        t.load().write(|w| unsafe { w.load().bits(1) });
399
    }
400

            
401
    fn set_counter_active(&self, state: bool) {
402
        self.t().config().modify(|_, w| w.en().bit(state));
403
    }
404

            
405
    fn is_counter_active(&self) -> bool {
406
        self.t().config().read().en().bit_is_set()
407
    }
408

            
409
    fn set_counter_decrementing(&self, decrementing: bool) {
410
        self.t()
411
            .config()
412
            .modify(|_, w| w.increase().bit(!decrementing));
413
    }
414

            
415
    fn set_auto_reload(&self, auto_reload: bool) {
416
        self.t()
417
            .config()
418
            .modify(|_, w| w.autoreload().bit(auto_reload));
419
    }
420

            
421
    fn set_alarm_active(&self, state: bool) {
422
        self.t().config().modify(|_, w| w.alarm_en().bit(state));
423
    }
424

            
425
    fn source_frequency(&self) -> Rate {
426
        cfg_select! {
427
            soc_has_clock_node_timg_function_clock => {
428
495
                let timg = match self.timer_group() {
429
                    0 => crate::soc::clocks::TimgInstance::Timg0,
430
                    #[cfg(soc_has_timg1)]
431
                    1 => crate::soc::clocks::TimgInstance::Timg1,
432
                    _ => unreachable!(),
433
                };
434
                let hz = timg.function_clock_frequency();
435
            }
436
            _ => {
437
                let hz = crate::soc::clocks::apb_clk_frequency();
438
            }
439
        }
440
        Rate::from_hz(hz)
441
    }
442

            
443
    fn load_value(&self, value: Duration) -> Result<(), Error> {
444
        let clk_src = self.source_frequency();
445
        let Some(ticks) = timeout_to_ticks(value, clk_src, self.divider()) else {
446
            return Err(Error::InvalidTimeout);
447
        };
448

            
449
        // The counter is 54-bits wide, so we must ensure that the provided
450
        // value is not too wide:
451
        if (ticks & !0x3F_FFFF_FFFF_FFFF) != 0 {
452
            return Err(Error::InvalidTimeout);
453
        }
454

            
455
        let high = (ticks >> 32) as u32;
456
        let low = (ticks & 0xFFFF_FFFF) as u32;
457

            
458
        let t = self.t();
459

            
460
        t.alarmlo().write(|w| unsafe { w.alarm_lo().bits(low) });
461
        t.alarmhi().write(|w| unsafe { w.alarm_hi().bits(high) });
462

            
463
        Ok(())
464
    }
465

            
466
    fn clear_interrupt(&self) {
467
        self.register_block()
468
            .int_clr()
469
            .write(|w| w.t(self.timer as _).clear_bit_by_one());
470
        let periodic = self.t().config().read().autoreload().bit_is_set();
471
        self.set_alarm_active(periodic);
472
    }
473

            
474
    fn now(&self) -> Instant {
475
        let t = self.t();
476

            
477
        t.update().write(|w| w.update().set_bit());
478
        while t.update().read().update().bit_is_set() {
479
            // Wait for the update to complete
480
        }
481

            
482
        let value_lo = t.lo().read().bits() as u64;
483
        let value_hi = t.hi().read().bits() as u64;
484

            
485
        let ticks = (value_hi << 32) | value_lo;
486
        let clk_src = self.source_frequency();
487
        let micros = ticks_to_timeout(ticks, clk_src, self.divider());
488

            
489
        Instant::from_ticks(micros)
490
    }
491

            
492
    fn divider(&self) -> u32 {
493
        let t = self.t();
494

            
495
        // From the ESP32 TRM, "11.2.1 16­-bit Prescaler and Clock Selection":
496
        //
497
        // "The prescaler can divide the APB clock by a factor from 2 to 65536.
498
        // Specifically, when TIMGn_Tx_DIVIDER is either 1 or 2, the clock divisor is 2;
499
        // when TIMGn_Tx_DIVIDER is 0, the clock divisor is 65536. Any other value will
500
        // cause the clock to be divided by exactly that value."
501
495
        match t.config().read().divider().bits() {
502
            0 => 65536,
503
            1 | 2 => 2,
504
            n => n as u32,
505
        }
506
    }
507

            
508
    fn is_interrupt_set(&self) -> bool {
509
        self.register_block()
510
            .int_raw()
511
            .read()
512
            .t(self.timer as _)
513
            .bit_is_set()
514
    }
515

            
516
    fn set_interrupt_enabled(&self, state: bool) {
517
        cfg_select! {
518
            any(esp32, esp32s2) => {
519
                // On ESP32 and S2, the `int_ena` register is ineffective - interrupts fire even
520
                // without int_ena enabling them. We use level interrupts so that we have a status
521
                // bit available.
522
                self.t().config().modify(|_, w| w.level_int_en().bit(state));
523
            }
524
            timergroup_timg_has_timer1 => {
525
                INT_ENA_LOCK[self.timer_group() as usize].lock(|| {
526
                    self.register_block()
527
                        .int_ena()
528
                        .modify(|_, w| w.t(self.timer_number()).bit(state));
529
                });
530
            }
531
            _ => {
532
                self.register_block()
533
                    .int_ena()
534
                    .modify(|_, w| w.t(0).bit(state));
535
            }
536
        }
537
    }
538
}
539

            
540
fn ticks_to_timeout(ticks: u64, clock: Rate, divider: u32) -> u64 {
541
    // 1_000_000 is used to get rid of `float` calculations
542
    let period: u64 = 1_000_000 * 1_000_000 / (clock.as_hz() as u64 / divider as u64);
543

            
544
    ticks * period / 1_000_000
545
}
546

            
547
fn timeout_to_ticks(timeout: Duration, clock: Rate, divider: u32) -> Option<u64> {
548
    let micros = timeout.as_micros();
549
495
    let ticks_per_sec = (clock.as_hz() / divider) as u64;
550

            
551
443
    micros.checked_mul(ticks_per_sec).map(|n| n / 1_000_000)
552
}
553

            
554
/// Behavior of the MWDT stage if it times out.
555
#[allow(unused)]
556
#[derive(Debug, Clone, Copy)]
557
pub enum MwdtStageAction {
558
    /// No effect on the system.
559
    Off         = 0,
560
    /// Triggers an interrupt.
561
    Interrupt   = 1,
562
    /// Resets the CPU core.
563
    ResetCpu    = 2,
564
    /// Resets the main system, power management unit and RTC peripherals.
565
    ResetSystem = 3,
566
}
567

            
568
/// MWDT stages.
569
///
570
/// Timer stages allow for a timer to have a series of different timeout values
571
/// and corresponding expiry action.
572
#[derive(Debug, Clone, Copy)]
573
pub enum MwdtStage {
574
    /// MWDT stage 0.
575
    Stage0,
576
    /// MWDT stage 1.
577
    Stage1,
578
    /// MWDT stage 2.
579
    Stage2,
580
    /// MWDT stage 3.
581
    Stage3,
582
}
583

            
584
/// Watchdog timer
585
pub struct Wdt<TG> {
586
    phantom: PhantomData<TG>,
587
}
588

            
589
/// Watchdog driver
590
impl<TG> Wdt<TG>
591
where
592
    TG: TimerGroupInstance,
593
{
594
    /// Creates a new instance of [`Wdt`].
595
    pub fn new() -> Self {
596
        let mut this = Self {
597
            phantom: PhantomData,
598
        };
599

            
600
        this.set_write_protection(false);
601
        #[cfg(soc_has_clock_node_timg_wdt_clock)]
602
        clocks::ClockTree::with(|clocks| {
603
325
            TG::clock_instance().configure_wdt_clock(clocks, TimgWdtClockConfig::default())
604
        });
605
        this.set_write_protection(true);
606

            
607
        this
608
    }
609

            
610
    /// Enables the watchdog timer instance.
611
    pub fn enable(&mut self) {
612
        // SAFETY: The `TG` instance being modified is owned by `self`, which is behind
613
        //         a mutable reference.
614
        unsafe { self.set_wdt_enabled(true) };
615
    }
616

            
617
    /// Disables the watchdog timer instance.
618
    pub fn disable(&mut self) {
619
        // SAFETY: The `TG` instance being modified is owned by `self`, which is behind
620
        //         a mutable reference.
621
        unsafe { self.set_wdt_enabled(false) };
622
    }
623

            
624
    /// Forcibly enable or disable the watchdog timer
625
    ///
626
    /// # Safety
627
    ///
628
    /// This bypasses the usual ownership rules for the peripheral, so users
629
    /// must take care to ensure that no driver instance is active for the
630
    /// timer.
631
    pub unsafe fn set_wdt_enabled(&mut self, enabled: bool) {
632
        let reg_block = unsafe { &*TG::register_block() };
633

            
634
        self.set_write_protection(false);
635

            
636
        #[cfg(soc_has_clock_node_timg_wdt_clock)]
637
        if enabled {
638
1
            clocks::ClockTree::with(|clocks| TG::clock_instance().request_wdt_clock(clocks));
639
        }
640

            
641
        reg_block
642
            .wdtconfig0()
643
            .modify(|_, w| w.wdt_en().bit(enabled));
644
        if enabled {
645
            reg_block.wdtconfig0().modify(|_, w| unsafe {
646
                w.wdt_flashboot_mod_en().bit(false);
647
                w.wdt_stg0().bits(MwdtStageAction::ResetSystem as u8);
648
                w.wdt_cpu_reset_length().bits(7);
649
                w.wdt_sys_reset_length().bits(7);
650
                w.wdt_stg1().bits(MwdtStageAction::Off as u8);
651
                w.wdt_stg2().bits(MwdtStageAction::Off as u8);
652
                w.wdt_stg3().bits(MwdtStageAction::Off as u8)
653
            });
654
        }
655

            
656
        #[cfg(timergroup_wdt_has_conf_update)]
657
        reg_block
658
            .wdtconfig0()
659
            .modify(|_, w| w.wdt_conf_update_en().set_bit());
660

            
661
        #[cfg(soc_has_clock_node_timg_wdt_clock)]
662
        if !enabled {
663
1
            clocks::ClockTree::with(|clocks| TG::clock_instance().release_wdt_clock(clocks));
664
        }
665

            
666
        self.set_write_protection(true);
667
    }
668

            
669
    /// Feeds the watchdog timer.
670
    pub fn feed(&mut self) {
671
        let reg_block = unsafe { &*TG::register_block() };
672

            
673
        self.set_write_protection(false);
674

            
675
        reg_block.wdtfeed().write(|w| unsafe { w.bits(1) });
676

            
677
        self.set_write_protection(true);
678
    }
679

            
680
    fn set_write_protection(&mut self, enable: bool) {
681
        let reg_block = unsafe { &*TG::register_block() };
682

            
683
        let wkey = if enable { 0u32 } else { 0x50D8_3AA1u32 };
684

            
685
        reg_block
686
            .wdtwprotect()
687
            .write(|w| unsafe { w.wdt_wkey().bits(wkey) });
688
    }
689

            
690
    /// Sets the timeout, in microseconds, of the watchdog timer.
691
    pub fn set_timeout(&mut self, stage: MwdtStage, timeout: Duration) {
692
        cfg_select! {
693
            soc_has_clock_node_timg_wdt_clock => {
694
1
                let clk_src = Rate::from_hz(TG::clock_instance().wdt_clock_frequency());
695
            }
696
            _ => {
697
                let clk_src = Rate::from_hz(clocks::apb_clk_frequency());
698
            }
699
        }
700

            
701
1
        let timeout_ticks = timeout.as_micros() * clk_src.as_mhz() as u64;
702

            
703
        let reg_block = unsafe { &*TG::register_block() };
704

            
705
1
        let (prescaler, timeout) = if timeout_ticks > u32::MAX as u64 {
706
            let prescaler = timeout_ticks
707
                .div_ceil(u32::MAX as u64 + 1)
708
                .min(u16::MAX as u64) as u16;
709
            let timeout = timeout_ticks
710
                .div_ceil(prescaler as u64)
711
                .min(u32::MAX as u64);
712
            (prescaler, timeout as u32)
713
        } else {
714
            (1, timeout_ticks as u32)
715
        };
716

            
717
        self.set_write_protection(false);
718

            
719
        reg_block.wdtconfig1().write(|w| unsafe {
720
            #[cfg(timergroup_timg_has_divcnt_rst)]
721
            w.wdt_divcnt_rst().set_bit();
722
            w.wdt_clk_prescale().bits(prescaler)
723
        });
724

            
725
        let config_register = match stage {
726
            MwdtStage::Stage0 => reg_block.wdtconfig2(),
727
            MwdtStage::Stage1 => reg_block.wdtconfig3(),
728
            MwdtStage::Stage2 => reg_block.wdtconfig4(),
729
            MwdtStage::Stage3 => reg_block.wdtconfig5(),
730
        };
731

            
732
        config_register.write(|w| unsafe { w.hold().bits(timeout) });
733

            
734
        #[cfg(timergroup_wdt_has_conf_update)]
735
        reg_block
736
            .wdtconfig0()
737
            .modify(|_, w| w.wdt_conf_update_en().set_bit());
738

            
739
        self.set_write_protection(true);
740
    }
741

            
742
    /// Sets the stage action of the MWDT for a specific stage.
743
    ///
744
    /// Modifies MWDT behavior only if a custom bootloader with the following modifications is
745
    /// used:
746
    /// - `ESP_TASK_WDT_EN` parameter **disabled**
747
    /// - `ESP_INT_WDT` parameter **disabled**
748
    pub fn set_stage_action(&mut self, stage: MwdtStage, action: MwdtStageAction) {
749
        let reg_block = unsafe { &*TG::register_block() };
750

            
751
        self.set_write_protection(false);
752

            
753
        reg_block.wdtconfig0().modify(|_, w| unsafe {
754
            match stage {
755
                MwdtStage::Stage0 => w.wdt_stg0().bits(action as u8),
756
                MwdtStage::Stage1 => w.wdt_stg1().bits(action as u8),
757
                MwdtStage::Stage2 => w.wdt_stg2().bits(action as u8),
758
                MwdtStage::Stage3 => w.wdt_stg3().bits(action as u8),
759
            }
760
        });
761

            
762
        #[cfg(timergroup_wdt_has_conf_update)]
763
        reg_block
764
            .wdtconfig0()
765
            .modify(|_, w| w.wdt_conf_update_en().set_bit());
766

            
767
        self.set_write_protection(true);
768
    }
769
}
770

            
771
impl<TG> crate::private::Sealed for Wdt<TG> where TG: TimerGroupInstance {}
772

            
773
impl<TG> InterruptConfigurable for Wdt<TG>
774
where
775
    TG: TimerGroupInstance,
776
{
777
    fn set_interrupt_handler(&mut self, handler: interrupt::InterruptHandler) {
778
        let interrupt = TG::wdt_interrupt();
779
        interrupt::bind_handler(interrupt, handler);
780
    }
781
}
782

            
783
impl<TG> Default for Wdt<TG>
784
where
785
    TG: TimerGroupInstance,
786
{
787
    fn default() -> Self {
788
        Self::new()
789
    }
790
}
791

            
792
// Async functionality of the timer groups.
793
mod asynch {
794
    use procmacros::handler;
795

            
796
    use super::*;
797
    use crate::asynch::AtomicWaker;
798

            
799
    const NUM_WAKERS: usize = {
800
        let timer_per_group = 1 + cfg!(timergroup_timg_has_timer1) as usize;
801
        NUM_TIMG * timer_per_group
802
    };
803

            
804
    static WAKERS: [AtomicWaker; NUM_WAKERS] = [const { AtomicWaker::new() }; NUM_WAKERS];
805

            
806
    pub(super) fn waker(timer: &Timer<'_>) -> &'static AtomicWaker {
807
        let index = (timer.timer_number() << 1) | timer.timer_group();
808
48
        &WAKERS[index as usize]
809
    }
810

            
811
    #[inline]
812
    fn handle_irq(timer: Timer<'_>) {
813
        timer.set_interrupt_enabled(false);
814
12
        waker(&timer).wake();
815
    }
816

            
817
    // INT_ENA means that when the interrupt occurs, it will show up in the
818
    // INT_ST. Clearing INT_ENA that it won't show up on INT_ST but if
819
    // interrupt is already there, it won't clear it - that's why we need to
820
    // clear the INT_CLR as well.
821
    #[handler]
822
12
    pub(crate) fn timg0_timer0_handler() {
823
        handle_irq(Timer {
824
            register_block: TIMG0::regs(),
825
            _lifetime: PhantomData,
826
            timer: TimerId::Timer0,
827
            tg: 0,
828
        });
829
    }
830

            
831
    #[cfg(timergroup_timg1)]
832
    #[handler]
833
12
    pub(crate) fn timg1_timer0_handler() {
834
        handle_irq(Timer {
835
            register_block: TIMG1::regs(),
836
            _lifetime: PhantomData,
837
            timer: TimerId::Timer0,
838
            tg: 1,
839
        });
840
    }
841

            
842
    #[cfg(timergroup_timg_has_timer1)]
843
    #[handler]
844
    pub(crate) fn timg0_timer1_handler() {
845
        handle_irq(Timer {
846
            register_block: TIMG0::regs(),
847
            _lifetime: PhantomData,
848
            timer: TimerId::Timer1,
849
            tg: 0,
850
        });
851
    }
852

            
853
    #[cfg(all(timergroup_timg1, timergroup_timg_has_timer1))]
854
    #[handler]
855
    pub(crate) fn timg1_timer1_handler() {
856
        handle_irq(Timer {
857
            register_block: TIMG1::regs(),
858
            _lifetime: PhantomData,
859
            timer: TimerId::Timer1,
860
            tg: 1,
861
        });
862
    }
863
}
864

            
865
/// Event Task Matrix
866
#[cfg(etm_driver_supported)]
867
pub mod etm {
868
    use super::*;
869
    use crate::etm::{EtmEvent, EtmTask};
870

            
871
    /// Event Task Matrix event for a timer.
872
    pub struct Event {
873
        id: u8,
874
    }
875

            
876
    /// Event Task Matrix task for a timer.
877
    pub struct Task {
878
        id: u8,
879
    }
880

            
881
    impl EtmEvent for Event {
882
        fn id(&self) -> u8 {
883
            self.id
884
        }
885
    }
886

            
887
    impl Sealed for Event {}
888

            
889
    impl EtmTask for Task {
890
        fn id(&self) -> u8 {
891
            self.id
892
        }
893
    }
894

            
895
    impl Sealed for Task {}
896

            
897
    /// General purpose timer ETM events.
898
    pub trait Events {
899
        /// ETM event triggered on alarm
900
        fn on_alarm(&self) -> Event;
901
    }
902

            
903
    /// General purpose timer ETM tasks
904
    pub trait Tasks {
905
        /// ETM task to start the counter
906
        fn cnt_start(&self) -> Task;
907

            
908
        /// ETM task to stop the counter
909
        fn cnt_stop(&self) -> Task;
910

            
911
        /// ETM task to reload the counter
912
        fn cnt_reload(&self) -> Task;
913

            
914
        /// ETM task to capture the counter
915
        fn cnt_cap(&self) -> Task;
916

            
917
        /// ETM task to load the counter with the value stored when the last
918
        /// `now()` was called
919
        fn alarm_start(&self) -> Task;
920
    }
921

            
922
    impl Events for Timer<'_> {
923
        fn on_alarm(&self) -> Event {
924
            Event {
925
                id: 48 + self.timer_group(),
926
            }
927
        }
928
    }
929

            
930
    impl Tasks for Timer<'_> {
931
        fn cnt_start(&self) -> Task {
932
            Task {
933
                id: 88 + self.timer_group(),
934
            }
935
        }
936

            
937
        fn alarm_start(&self) -> Task {
938
            Task {
939
                id: 90 + self.timer_group(),
940
            }
941
        }
942

            
943
        fn cnt_stop(&self) -> Task {
944
            Task {
945
                id: 92 + self.timer_group(),
946
            }
947
        }
948

            
949
        fn cnt_reload(&self) -> Task {
950
            Task {
951
                id: 94 + self.timer_group(),
952
            }
953
        }
954

            
955
        fn cnt_cap(&self) -> Task {
956
            Task {
957
                id: 96 + self.timer_group(),
958
            }
959
        }
960
    }
961
}