libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
esp_watchdog.cpp
1#include "esp_watchdog.hpp"
2
3#include <cstdint>
4
5#include "esp_private/periph_ctrl.h"
6#include "hal/mwdt_ll.h"
7#include "hal/timer_ll.h"
8#include "soc/rtc.h"
9
10namespace LibXR
11{
12namespace
13{
14
15constexpr uint32_t MWDT_TICK_US = 500;
16constexpr uint32_t MWDT_TICKS_PER_MS = 1000 / MWDT_TICK_US;
17
18bool GetMwdtGroupInfo(wdt_inst_t instance, int* group_id, periph_module_t* periph)
19{
20 if (instance == WDT_MWDT0)
21 {
22 *group_id = 0;
23 *periph = PERIPH_TIMG0_MODULE;
24 return true;
25 }
26
27#if SOC_TIMER_GROUPS >= 2
28 if (instance == WDT_MWDT1)
29 {
30 *group_id = 1;
31 *periph = PERIPH_TIMG1_MODULE;
32 return true;
33 }
34#endif
35
36 return false;
37}
38
39} // namespace
40
41ESP32Watchdog::ESP32Watchdog(uint32_t timeout_ms, uint32_t feed_ms)
42{
43 (void)SetConfig({timeout_ms, feed_ms});
44 (void)Start();
45}
46
47bool ESP32Watchdog::IsInstanceSupported(wdt_inst_t instance)
48{
49 switch (instance)
50 {
51 case WDT_MWDT0:
52 return true;
53#if SOC_TIMER_GROUPS >= 2
54 case WDT_MWDT1:
55 return true;
56#endif
57 case WDT_RWDT:
58 return true;
59 default:
60 return false;
61 }
62}
63
64ErrorCode ESP32Watchdog::InitializeHardware()
65{
66 if (initialized_)
67 {
68 return ErrorCode::OK;
69 }
70
71 if (!IsInstanceSupported(instance_))
72 {
74 }
75
76 if (instance_ != WDT_RWDT)
77 {
78 int group_id = 0;
79 periph_module_t periph = PERIPH_TIMG0_MODULE;
80 if (!GetMwdtGroupInfo(instance_, &group_id, &periph))
81 {
83 }
84
85 PERIPH_RCC_ACQUIRE_ATOMIC(periph, ref_count)
86 {
87 if (ref_count == 0)
88 {
89 timer_ll_enable_bus_clock(group_id, true);
90 timer_ll_reset_register(group_id);
91 }
92 }
93 }
94
95 const uint32_t prescaler = instance_ == WDT_RWDT ? 0U : MWDT_LL_DEFAULT_CLK_PRESCALER;
96 wdt_hal_init(&hal_, instance_, prescaler, false);
97 initialized_ = true;
98 return ErrorCode::OK;
99}
100
101ErrorCode ESP32Watchdog::ApplyConfiguration()
102{
103 if (!initialized_)
104 {
105 return ErrorCode::INIT_ERR;
106 }
107
108 uint64_t ticks64 = 0U;
109 if (instance_ == WDT_RWDT)
110 {
111 const uint32_t slow_clock_hz = rtc_clk_slow_freq_get_hz();
112 if (slow_clock_hz == 0U)
113 {
114 return ErrorCode::INIT_ERR;
115 }
116 ticks64 = static_cast<uint64_t>(timeout_ms_) * slow_clock_hz / 1000U;
117 }
118 else
119 {
120 ticks64 = static_cast<uint64_t>(timeout_ms_) * MWDT_TICKS_PER_MS;
121 }
122 if ((ticks64 == 0) || (ticks64 > UINT32_MAX))
123 {
125 }
126
127 const uint32_t stage0_ticks = static_cast<uint32_t>(ticks64);
128
129 wdt_hal_write_protect_disable(&hal_);
130 wdt_hal_config_stage(&hal_, WDT_STAGE0, stage0_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
131 wdt_hal_config_stage(&hal_, WDT_STAGE1, 0, WDT_STAGE_ACTION_OFF);
132 wdt_hal_config_stage(&hal_, WDT_STAGE2, 0, WDT_STAGE_ACTION_OFF);
133 wdt_hal_config_stage(&hal_, WDT_STAGE3, 0, WDT_STAGE_ACTION_OFF);
134 wdt_hal_write_protect_enable(&hal_);
135
136 return ErrorCode::OK;
137}
138
140{
141 if ((config.timeout_ms == 0) || (config.feed_ms == 0) ||
142 (config.feed_ms > config.timeout_ms))
143 {
144 return ErrorCode::ARG_ERR;
145 }
146
147 timeout_ms_ = config.timeout_ms;
149
150 ErrorCode ret = InitializeHardware();
151 if (ret != ErrorCode::OK)
152 {
153 return ret;
154 }
155
156 return ApplyConfiguration();
157}
158
160{
161 if (!initialized_ || !started_)
162 {
163 return ErrorCode::INIT_ERR;
164 }
165
166 wdt_hal_write_protect_disable(&hal_);
167 wdt_hal_feed(&hal_);
168 wdt_hal_write_protect_enable(&hal_);
169 return ErrorCode::OK;
170}
171
173{
174 ErrorCode ret = InitializeHardware();
175 if (ret != ErrorCode::OK)
176 {
177 return ret;
178 }
179
180 ret = ApplyConfiguration();
181 if (ret != ErrorCode::OK)
182 {
183 return ret;
184 }
185
186 wdt_hal_write_protect_disable(&hal_);
187 wdt_hal_enable(&hal_);
188 wdt_hal_feed(&hal_);
189 wdt_hal_write_protect_enable(&hal_);
190
191 auto_feed_ = true;
192 started_ = true;
193 return ErrorCode::OK;
194}
195
197{
198 if (!initialized_)
199 {
200 return ErrorCode::INIT_ERR;
201 }
202
203 wdt_hal_write_protect_disable(&hal_);
204 wdt_hal_disable(&hal_);
205 wdt_hal_write_protect_enable(&hal_);
206
207 auto_feed_ = false;
208 started_ = false;
209 return ErrorCode::OK;
210}
211
212} // namespace LibXR
ErrorCode Start() override
启动看门狗 / Start the watchdog
ErrorCode Stop() override
停止看门狗 / Stop the watchdog
ErrorCode Feed() override
立即手动喂狗 Feed the watchdog immediately
ErrorCode SetConfig(const Configuration &config) override
初始化硬件并设置超时时间 Initialize hardware and set overflow time
uint32_t auto_feed_interval_ms
自动喂狗间隔
Definition watchdog.hpp:112
bool auto_feed_
是否自动喂狗
Definition watchdog.hpp:113
uint32_t timeout_ms_
溢出时间
Definition watchdog.hpp:111
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ INIT_ERR
初始化错误 / Initialization error
@ NOT_SUPPORT
不支持 / Not supported
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
看门狗配置结构体 Configuration for the watchdog
Definition watchdog.hpp:28
uint32_t feed_ms
自动喂狗周期 / Auto feed interval (ms, < timeout_ms)
Definition watchdog.hpp:30
uint32_t timeout_ms
看门狗溢出时间 / Watchdog overflow time (ms)
Definition watchdog.hpp:29