FastArduino v1.10
C++ library to build fast but small Arduino/AVR projects
Loading...
Searching...
No Matches
watchdog.h
Go to the documentation of this file.
1// Copyright 2016-2023 Jean-Francois Poilpret
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
16
21#ifndef WATCHDOG_HH
22#define WATCHDOG_HH
23
24#include "boards/board.h"
25#include "boards/board_traits.h"
26#include <avr/interrupt.h>
27#include "interrupts.h"
28#include "events.h"
29
36#define REGISTER_WATCHDOG_CLOCK_ISR(EVENT) \
37 ISR(WDT_vect) \
38 { \
39 watchdog::isr_handler::watchdog_clock<EVENT>(); \
40 }
41
47#define REGISTER_WATCHDOG_RTT_ISR() \
48 ISR(WDT_vect) \
49 { \
50 watchdog::isr_handler::watchdog_rtt(); \
51 }
52
61#define REGISTER_WATCHDOG_ISR_METHOD(HANDLER, CALLBACK) \
62 ISR(WDT_vect) \
63 { \
64 watchdog::isr_handler::watchdog_method<HANDLER, CALLBACK>(); \
65 }
66
74#define REGISTER_WATCHDOG_ISR_FUNCTION(CALLBACK) \
75 ISR(WDT_vect) \
76 { \
77 watchdog::isr_handler::watchdog_function<CALLBACK>() : \
78 }
79
85#define REGISTER_WATCHDOG_ISR_EMPTY() EMPTY_INTERRUPT(WDT_vect)
86
93#define DECL_WATCHDOG_ISR_HANDLERS_FRIEND \
94 friend struct watchdog::isr_handler; \
95 friend void ::WDT_vect();
96
100namespace watchdog
101{
109 enum class TimeOut : uint8_t
110 {
112 TO_16ms = 0,
114 TO_32ms,
116 TO_64ms,
118 TO_125ms,
120 TO_250ms,
122 TO_500ms,
124 TO_1s,
126 TO_2s,
128 TO_4s,
130 TO_8s
131 };
132
145 {
146 public:
148 WatchdogSignal() = default;
149 WatchdogSignal(const WatchdogSignal&) = delete;
150 WatchdogSignal& operator=(const WatchdogSignal&) = delete;
152
160 {
161 uint8_t config = bits::BV8(WDIE) | (uint8_t(timeout) & MASK_WDP012) |
162 ((uint8_t(timeout) & MASK_WDP3) ? bits::BV8(WDP3) : 0);
163 synchronized begin_with_config(config);
164 }
165
169 void end()
170 {
171 synchronized
172 {
173 WDTCSR_ = bits::BV8(WDCE, WDE);
174 WDTCSR_ = 0;
175 }
176 }
177
178 protected:
180 void begin_with_config(uint8_t config) INLINE
181 {
182 __asm__ __volatile__("wdr");
183 MCUSR_ |= 1 << WDRF;
184 WDTCSR_ = bits::BV8(WDCE, WDE);
185 WDTCSR_ = config;
186 }
187
188 static constexpr const uint8_t MASK_WDP012 = bits::BV8(WDP0, WDP1, WDP2);
189 static constexpr const uint8_t MASK_WDP3 = 0x08U;
191
192 private:
193 using REG8 = board_traits::REG8;
194 static constexpr const REG8 MCUSR_{MCUSR};
195 static constexpr const REG8 WDTCSR_{WDTCSR};
196 };
197
204 {
205 public:
212 {
214 }
215
223 {
224 uint16_t ms_per_tick = bits::BV16(uint8_t(timeout) + 4);
225 uint8_t config = bits::BV8(WDIE) | (uint8_t(timeout) & MASK_WDP012) |
226 ((uint8_t(timeout) & MASK_WDP3) ? bits::BV8(WDP3) : 0);
227
228 synchronized
229 {
230 begin_with_config(config);
231 millis_per_tick_ = ms_per_tick;
232 millis_ = 0;
233 }
234 }
235
242 uint32_t millis() const
243 {
244 synchronized return millis_;
245 }
246
251 void reset()
252 {
253 synchronized millis_ = 0;
254 }
255
268 void delay(uint32_t ms)
269 {
270 uint32_t limit = millis() + ms;
271 while (millis() < limit)
272 {
273 time::yield();
274 }
275 }
276
277 protected:
279 // This constructor is used by subclass to avoid calling register_handler()
280 explicit WatchdogRTT(bool dummy UNUSED) {}
281
282 void on_tick()
283 {
284 millis_ += millis_per_tick_;
285 }
287
288 private:
289 volatile uint32_t millis_ = 0UL;
290 uint16_t millis_per_tick_ = 0U;
291
292 friend struct isr_handler;
293 };
294
301 template<typename EVENT> class Watchdog : public WatchdogRTT
302 {
303 static_assert(events::Event_trait<EVENT>::IS_EVENT, "EVENT type must be an events::Event<T>");
304
305 public:
316 explicit Watchdog(containers::Queue<EVENT>& event_queue) : WatchdogRTT{true}, event_queue_{event_queue}
317 {
319 }
320
321 private:
322 void on_tick()
323 {
324 WatchdogRTT::on_tick();
325 event_queue_.push_(EVENT{events::Type::WDT_TIMER});
326 }
327
328 containers::Queue<EVENT>& event_queue_;
329
330 friend struct isr_handler;
331 };
332
334 struct isr_handler
335 {
336 template<typename EVENT> static void watchdog_clock()
337 {
338 interrupt::HandlerHolder<watchdog::Watchdog<EVENT>>::handler()->on_tick();
339 }
340
341 static void watchdog_rtt()
342 {
343 interrupt::HandlerHolder<watchdog::WatchdogRTT>::handler()->on_tick();
344 }
345
346 template<typename HANDLER, void (HANDLER::*CALLBACK)()> static void watchdog_method()
347 {
348 interrupt::CallbackHandler<void (HANDLER::*)(), CALLBACK>::call();
349 }
350
351 template<void (*CALLBACK)()> static void watchdog_function()
352 {
353 interrupt::CallbackHandler<void (*)(), CALLBACK>::call();
354 }
355 };
357}
358
359#endif /* WATCHDOG_HH */
Queue of type T_ items.
Definition: queue.h:59
bool push_(TREF item)
Push item to the end of this queue, provided there is still available space in its ring buffer.
Simple API to use watchdog timer as a clock for events generation.
Definition: watchdog.h:302
Watchdog(containers::Queue< EVENT > &event_queue)
Construct a new watchdog-based clock that will, for each watchdog timeout, add an event to the given ...
Definition: watchdog.h:316
Simple API to use watchdog timer as a real-time clock.
Definition: watchdog.h:204
uint32_t millis() const
Get the number of milliseconds that elapsed since begin() was called.
Definition: watchdog.h:242
void reset()
Reset current counter to 0.
Definition: watchdog.h:251
WatchdogRTT()
Construct a new watchdog-based clock that will count elapsed milliseconds since it was started with b...
Definition: watchdog.h:211
void delay(uint32_t ms)
Delay program execution for the given amount of milliseconds.
Definition: watchdog.h:268
void begin(TimeOut timeout=TimeOut::TO_16ms)
Start the watchdog clock with the given timeout period.
Definition: watchdog.h:222
Simple API to handle watchdog signals.
Definition: watchdog.h:145
void end()
Stop this watchdog timer.
Definition: watchdog.h:169
void begin(TimeOut timeout=TimeOut::TO_16ms)
Start the watchdog timer with the given timeout period.
Definition: watchdog.h:159
#define INLINE
Specific GCC attribute to force the compiler to always inline code of a given function.
Definition: defines.h:57
#define UNUSED
Specific GCC attribute to declare an argument or variable unused, so that the compiler does not emit ...
Definition: defines.h:45
Support for events management.
General API for handling AVR interrupt vectors.
static constexpr uint8_t BV8(uint8_t bit)
Create a uint8_t bitmask for the given bit number.
Definition: bits.h:41
static constexpr uint16_t BV16(uint8_t bit)
Create a uint16_t bitmask for the given bit number.
Definition: bits.h:148
const uint8_t WDT_TIMER
Type of events generated by watchdog::Watchdog for each watchdog timeout interrupt.
Definition: events.h:105
void register_handler(Handler &handler)
Register a class instance containing methods that shall be called back by an ISR.
Definition: interrupts.h:185
void yield()
Utility method used by many FastArduino API in order to "yield" some processor time; concretely it ju...
Definition: time.cpp:22
Defines the simple API for Watchdog timer management.
Definition: watchdog.h:101
TimeOut
Defines the watchdog timeout period; watchdog interrupts will be triggered at the selected period.
Definition: watchdog.h:110
@ TO_8s
Watchdog timeout 8 seconds.
@ TO_16ms
Watchdog timeout 16 ms.
@ TO_32ms
Watchdog timeout 32 ms.
@ TO_64ms
Watchdog timeout 64 ms.
@ TO_1s
Watchdog timeout 1 second.
@ TO_125ms
Watchdog timeout 125 ms.
@ TO_2s
Watchdog timeout 2 seconds.
@ TO_250ms
Watchdog timeout 250 ms.
@ TO_4s
Watchdog timeout 4 seconds.
@ TO_500ms
Watchdog timeout 500 ms.