esp32/
rtc_cntl.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Low Power Management driver.

use kernel::platform::watchdog::WatchDog;
use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
use kernel::utilities::StaticRef;

pub const RTC_CNTL_BASE: StaticRef<RtcCntlRegisters> =
    unsafe { StaticRef::new(0x6000_8000 as *const RtcCntlRegisters) };

register_structs! {
    pub RtcCntlRegisters {
        (0x000 => options0: ReadWrite<u32>),
        (0x004 => slp_timer0: ReadWrite<u32>),
        (0x008 => slp_timer1: ReadWrite<u32>),
        (0x00C => time_update: ReadWrite<u32>),
        (0x010 => time_low0: ReadWrite<u32>),
        (0x014 => time_high0: ReadWrite<u32>),
        (0x018 => state0: ReadWrite<u32>),
        (0x01C => timer1: ReadWrite<u32>),
        (0x020 => timer2: ReadWrite<u32>),
        (0x024 => timer3: ReadWrite<u32>),
        (0x028 => timer4: ReadWrite<u32>),
        (0x02C => timer5: ReadWrite<u32>),
        (0x030 => timer6: ReadWrite<u32>),
        (0x034 => ana_conf: ReadWrite<u32>),
        (0x038 => reset_state: ReadWrite<u32>),
        (0x03C => wakeup_state: ReadWrite<u32>),
        (0x040 => int_ena: ReadWrite<u32>),
        (0x044 => int_raw: ReadWrite<u32>),
        (0x048 => int_st: ReadWrite<u32>),
        (0x04C => int_clr: ReadWrite<u32>),
        (0x050 => store0: ReadWrite<u32>),
        (0x054 => store1: ReadWrite<u32>),
        (0x058 => store2: ReadWrite<u32>),
        (0x05C => store3: ReadWrite<u32>),
        (0x060 => ext_xtl_conf: ReadWrite<u32>),
        (0x064 => ext_wakeup_conf: ReadWrite<u32>),
        (0x068 => slp_reject_conf: ReadWrite<u32>),
        (0x06C => cpu_period_conf: ReadWrite<u32>),
        (0x070 => clk_conf: ReadWrite<u32, CLK_CONF::Register>),
        (0x074 => slow_clk_conf: ReadWrite<u32>),
        (0x078 => sdio_conf: ReadWrite<u32>),
        (0x07C => bias_conf: ReadWrite<u32>),
        (0x080 => vreg: ReadWrite<u32>),
        (0x084 => pwc: ReadWrite<u32>),
        (0x088 => dig_pwc: ReadWrite<u32>),
        (0x08C => dig_iso: ReadWrite<u32>),
        (0x090 => wdtconfig0: ReadWrite<u32, WDTCONFIG0::Register>),
        (0x094 => wdtconfig1: ReadWrite<u32>),
        (0x098 => wdtconfig2: ReadWrite<u32>),
        (0x09C => wdtconfig3: ReadWrite<u32>),
        (0x0A0 => wdtconfig4: ReadWrite<u32>),
        (0x0A4 => wdtfeed: ReadWrite<u32>),
        (0x0A8 => wdtprotect: ReadWrite<u32>),
        (0x0AC => swd_conf: ReadWrite<u32, SWD_CONF::Register>),
        (0x0B0 => swd_wprotect: ReadWrite<u32>),
        (0x0B4 => sw_cpu_stall: ReadWrite<u32>),
        (0x0B8 => store4: ReadWrite<u32>),
        (0x0BC => store5: ReadWrite<u32>),
        (0x0C0 => store6: ReadWrite<u32>),
        (0x0C4 => store7: ReadWrite<u32>),
        (0x0C8 => low_power_st: ReadWrite<u32>),
        (0x0CC => daig0: ReadWrite<u32>),
        (0x0D0 => pad_hold: ReadWrite<u32>),
        (0x0D4 => _reserved0),
        (0x10C => fib_sel: ReadWrite<u32, FIB_SEL::Register>),
        (0x110 => @END),
    }
}

register_bitfields![u32,
    CLK_CONF [
        DIG_FOSC_EN OFFSET(10) NUMBITS(1) [],
    ],
    WDTCONFIG0 [
        CHIP_RESET_EN OFFSET(8) NUMBITS(1) [],
        PAUSE_INSLEEP OFFSET(9) NUMBITS(1) [],
        APPCPU_RESET_EN OFFSET(10) NUMBITS(1) [],
        PROCPU_RESET_EN OFFSET(11) NUMBITS(1) [],
        FLASHBOOT_MOD_EN OFFSET(12) NUMBITS(1) [],
        SYS_RESET_LENGTH OFFSET(13) NUMBITS(3) [],
        CPU_RESET_LENGTH OFFSET(16) NUMBITS(3) [],
        STG3 OFFSET(19) NUMBITS(3) [],
        STG2 OFFSET(22) NUMBITS(3) [],
        STG1 OFFSET(25) NUMBITS(3) [],
        STG0 OFFSET(28) NUMBITS(3) [],
        EN OFFSET(31) NUMBITS(1) [],
    ],
    SWD_CONF [
        AUTO_FEED OFFSET(31) NUMBITS(1) [],
    ],
    FIB_SEL [
        FIB_SEL OFFSET(0) NUMBITS(3) [
            GLITCH_RST = 1,
            BOR_RST = 2,
            SUPER_WDT_RST = 3,
        ],
    ],
];

pub struct RtcCntl {
    registers: StaticRef<RtcCntlRegisters>,
}

impl RtcCntl {
    pub const fn new(base: StaticRef<RtcCntlRegisters>) -> RtcCntl {
        Self { registers: base }
    }

    /// Enable WDT config writes
    fn enable_wdt_access(&self) {
        self.registers.wdtprotect.set(0x50d8_3aa1);
    }

    /// Disable WDT config writes
    fn disable_wdt_access(&self) {
        self.registers.wdtprotect.set(0);
    }

    pub fn disable_wdt(&self) {
        self.enable_wdt_access();

        self.registers
            .wdtconfig0
            .modify(WDTCONFIG0::EN::CLEAR + WDTCONFIG0::FLASHBOOT_MOD_EN::CLEAR);
        if self
            .registers
            .wdtconfig0
            .is_set(WDTCONFIG0::FLASHBOOT_MOD_EN)
        {
            panic!("Can't disable RTC CNTL WDT");
        }

        self.disable_wdt_access();
    }

    /// Enable SW WDT config writes
    fn enable_sw_wdt_access(&self) {
        self.registers.swd_wprotect.set(0x8F1D_312A);
    }

    /// Disable SW WDT config writes
    fn disable_sw_wdt_access(&self) {
        self.registers.swd_wprotect.set(0);
    }

    pub fn disable_super_wdt(&self) {
        self.registers.fib_sel.modify(FIB_SEL::FIB_SEL::BOR_RST);

        self.enable_sw_wdt_access();
        self.registers.swd_conf.modify(SWD_CONF::AUTO_FEED::SET);
        self.disable_sw_wdt_access();
    }

    pub fn enable_fosc(&self) {
        self.registers.clk_conf.modify(CLK_CONF::DIG_FOSC_EN::SET);
    }
}

impl WatchDog for RtcCntl {
    fn setup(&self) {}

    fn tickle(&self) {}

    fn suspend(&self) {}

    fn resume(&self) {
        self.tickle();
    }
}