Skip to main content

esp_idf_hal/
reset.rs

1//! Reset reasons
2use esp_idf_sys::*;
3
4/// Reset reasons
5#[doc(alias = "esp_reset_reason_t")]
6#[derive(Copy, Clone, Eq, PartialEq, Debug)]
7pub enum ResetReason {
8    /// Software restart via `esp_restart()`
9    Software,
10    /// Reset by external pin
11    ExternalPin,
12    /// Reset due to other watchdogs
13    Watchdog,
14    /// Reset over SDIO
15    Sdio,
16    /// Software reset due to exception/panic
17    Panic,
18    /// Reset (software or hardware) due to interrupt watchdog
19    InterruptWatchdog,
20    /// Reset due to power-on event
21    PowerOn,
22    /// Reset reason can not be determined
23    Unknown,
24    /// Brownout reset (software or hardware)
25    Brownout,
26    /// Reset due to task watchdog
27    TaskWatchdog,
28    /// Reset after exiting deep sleep mode
29    DeepSleep,
30    /// Reset by USB peripheral (introduced in IDF v5.1.4)
31    #[cfg(not(any(
32        esp_idf_version_major = "4",
33        all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
34        esp_idf_version_full = "5.1.0",
35        esp_idf_version_full = "5.1.1",
36        esp_idf_version_full = "5.1.2",
37        esp_idf_version_full = "5.1.3",
38    )))]
39    USBPeripheral,
40    /// Reset by JTAG (introduced in IDF v5.1.4)
41    #[cfg(not(any(
42        esp_idf_version_major = "4",
43        all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
44        esp_idf_version_full = "5.1.0",
45        esp_idf_version_full = "5.1.1",
46        esp_idf_version_full = "5.1.2",
47        esp_idf_version_full = "5.1.3",
48    )))]
49    JTAG,
50    /// Reset due to efuse error (introduced in IDF v5.2.2)
51    #[cfg(not(any(
52        esp_idf_version_major = "4",
53        all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
54        all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
55        esp_idf_version_full = "5.2.0",
56        esp_idf_version_full = "5.2.1",
57    )))]
58    EfuseError,
59    /// Reset due to power glitch detected (introduced in IDF v5.2.2)
60    #[cfg(not(any(
61        esp_idf_version_major = "4",
62        all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
63        all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
64        esp_idf_version_full = "5.2.0",
65        esp_idf_version_full = "5.2.1",
66    )))]
67    PowerGlitch,
68    /// Reset due to CPU lock up (introduced in IDF v5.2.2)
69    #[cfg(not(any(
70        esp_idf_version_major = "4",
71        all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
72        all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
73        esp_idf_version_full = "5.2.0",
74        esp_idf_version_full = "5.2.1",
75    )))]
76    CPULockup,
77}
78
79impl From<esp_reset_reason_t> for ResetReason {
80    #[allow(non_upper_case_globals)]
81    fn from(value: esp_reset_reason_t) -> Self {
82        match value {
83            esp_reset_reason_t_ESP_RST_SW => Self::Software,
84            esp_reset_reason_t_ESP_RST_EXT => Self::ExternalPin,
85            esp_reset_reason_t_ESP_RST_WDT => Self::Watchdog,
86            esp_reset_reason_t_ESP_RST_SDIO => Self::Sdio,
87            esp_reset_reason_t_ESP_RST_PANIC => Self::Panic,
88            esp_reset_reason_t_ESP_RST_INT_WDT => Self::InterruptWatchdog,
89            esp_reset_reason_t_ESP_RST_POWERON => Self::PowerOn,
90            esp_reset_reason_t_ESP_RST_UNKNOWN => Self::Unknown,
91            esp_reset_reason_t_ESP_RST_BROWNOUT => Self::Brownout,
92            esp_reset_reason_t_ESP_RST_TASK_WDT => Self::TaskWatchdog,
93            esp_reset_reason_t_ESP_RST_DEEPSLEEP => Self::DeepSleep,
94            #[cfg(not(any(
95                esp_idf_version_major = "4",
96                all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
97                esp_idf_version_full = "5.1.0",
98                esp_idf_version_full = "5.1.1",
99                esp_idf_version_full = "5.1.2",
100                esp_idf_version_full = "5.1.3",
101            )))]
102            esp_reset_reason_t_ESP_RST_USB => Self::USBPeripheral,
103            #[cfg(not(any(
104                esp_idf_version_major = "4",
105                esp_idf_version = "5.0",
106                esp_idf_version_full = "5.1.0",
107                esp_idf_version_full = "5.1.1",
108                esp_idf_version_full = "5.1.2",
109                esp_idf_version_full = "5.1.3",
110            )))]
111            esp_reset_reason_t_ESP_RST_JTAG => Self::JTAG,
112            #[cfg(not(any(
113                esp_idf_version_major = "4",
114                esp_idf_version = "5.0",
115                esp_idf_version = "5.1",
116                esp_idf_version_full = "5.2.0",
117                esp_idf_version_full = "5.2.1",
118            )))]
119            esp_reset_reason_t_ESP_RST_EFUSE => Self::EfuseError,
120            #[cfg(not(any(
121                esp_idf_version_major = "4",
122                esp_idf_version = "5.0",
123                esp_idf_version = "5.1",
124                esp_idf_version_full = "5.2.0",
125                esp_idf_version_full = "5.2.1",
126            )))]
127            esp_reset_reason_t_ESP_RST_PWR_GLITCH => Self::PowerGlitch,
128            #[cfg(not(any(
129                esp_idf_version_major = "4",
130                esp_idf_version = "5.0",
131                esp_idf_version = "5.1",
132                esp_idf_version_full = "5.2.0",
133                esp_idf_version_full = "5.2.1",
134            )))]
135            esp_reset_reason_t_ESP_RST_CPU_LOCKUP => Self::CPULockup,
136            _ => unreachable!(),
137        }
138    }
139}
140
141impl ResetReason {
142    /// Get the reason for the last reset
143    #[doc(alias = "esp_reset_reason")]
144    pub fn get() -> Self {
145        // SAFETY: `esp_reset_reason()` reads from static memory that is initialized when
146        // constructors run and never modified after that point. We would only see
147        // uninitialized/partially initialized data if we run before main() (and before
148        // constructors running).
149        let rr = unsafe { esp_reset_reason() };
150        rr.into()
151    }
152}
153
154/// Wakeup reasons
155#[doc(alias = "esp_sleep_source_t")]
156#[derive(Copy, Clone, Eq, PartialEq, Debug)]
157pub enum WakeupReason {
158    Unknown,
159    ULP,
160    Button,
161    Timer,
162    Other(u32),
163}
164
165impl From<esp_sleep_source_t> for WakeupReason {
166    #[allow(non_upper_case_globals)]
167    fn from(value: esp_sleep_source_t) -> Self {
168        match value {
169            esp_sleep_source_t_ESP_SLEEP_WAKEUP_UNDEFINED => Self::Unknown,
170            esp_sleep_source_t_ESP_SLEEP_WAKEUP_EXT0 => Self::Button,
171            esp_sleep_source_t_ESP_SLEEP_WAKEUP_EXT1 => Self::Button,
172            esp_sleep_source_t_ESP_SLEEP_WAKEUP_ULP => Self::ULP,
173            esp_sleep_source_t_ESP_SLEEP_WAKEUP_COCPU => Self::ULP,
174            esp_sleep_source_t_ESP_SLEEP_WAKEUP_TIMER => Self::Timer,
175            other => Self::Other(other),
176        }
177    }
178}
179
180impl WakeupReason {
181    /// Get the reason for the wakeup
182    #[doc(alias = "esp_sleep_get_wakeup_cause")]
183    pub fn get() -> Self {
184        let wr = unsafe { esp_sleep_get_wakeup_cause() };
185        wr.into()
186    }
187}
188
189pub fn restart() -> ! {
190    unsafe { esp_restart() }
191}