Skip to content

Commit a15c111

Browse files
authored
Merge pull request #7718 from microdev1/watchdog-rp
Update WatchDog implementation
2 parents a3c9320 + 27fd60d commit a15c111

File tree

23 files changed

+317
-254
lines changed

23 files changed

+317
-254
lines changed

locale/circuitpython.pot

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ msgstr ""
196196
msgid "%q must be <= %d"
197197
msgstr ""
198198

199+
#: ports/espressif/common-hal/watchdog/WatchDogTimer.c
200+
msgid "%q must be <= %u"
201+
msgstr ""
202+
199203
#: py/argcheck.c
200204
msgid "%q must be >= %d"
201205
msgstr ""
@@ -1164,10 +1168,6 @@ msgstr ""
11641168
msgid "Initial set pin state conflicts with initial out pin state"
11651169
msgstr ""
11661170

1167-
#: ports/espressif/common-hal/watchdog/WatchDogTimer.c
1168-
msgid "Initialization failed due to lack of memory"
1169-
msgstr ""
1170-
11711171
#: shared-bindings/bitops/__init__.c
11721172
#, c-format
11731173
msgid "Input buffer length (%d) must be a multiple of the strand count (%d)"
@@ -1802,11 +1802,6 @@ msgstr ""
18021802
msgid "Pull not used when direction is output."
18031803
msgstr ""
18041804

1805-
#: ports/atmel-samd/common-hal/watchdog/WatchDogTimer.c
1806-
#: ports/raspberrypi/common-hal/watchdog/WatchDogTimer.c
1807-
msgid "RAISE mode is not implemented"
1808-
msgstr ""
1809-
18101805
#: ports/raspberrypi/common-hal/countio/Counter.c
18111806
msgid "RISE_AND_FALL not available on this chip"
18121807
msgstr ""
@@ -2308,20 +2303,10 @@ msgstr ""
23082303
msgid "WARNING: Your code filename has two extensions\n"
23092304
msgstr ""
23102305

2311-
#: ports/atmel-samd/common-hal/watchdog/WatchDogTimer.c
23122306
#: ports/nrf/common-hal/watchdog/WatchDogTimer.c
2313-
#: ports/raspberrypi/common-hal/watchdog/WatchDogTimer.c
23142307
msgid "WatchDogTimer cannot be deinitialized once mode is set to RESET"
23152308
msgstr ""
23162309

2317-
#: shared-bindings/watchdog/WatchDogTimer.c
2318-
msgid "WatchDogTimer is not currently running"
2319-
msgstr ""
2320-
2321-
#: shared-bindings/watchdog/WatchDogTimer.c
2322-
msgid "WatchDogTimer.mode cannot be changed once set to WatchDogMode.RESET"
2323-
msgstr ""
2324-
23252310
#: py/builtinhelp.c
23262311
#, c-format
23272312
msgid ""
@@ -4078,10 +4063,7 @@ msgstr ""
40784063
msgid "syntax error in uctypes descriptor"
40794064
msgstr ""
40804065

4081-
#: ports/atmel-samd/common-hal/watchdog/WatchDogTimer.c
4082-
#: ports/espressif/common-hal/watchdog/WatchDogTimer.c
40834066
#: ports/nrf/common-hal/watchdog/WatchDogTimer.c
4084-
#: ports/raspberrypi/common-hal/watchdog/WatchDogTimer.c
40854067
msgid "timeout duration exceeded the maximum supported value"
40864068
msgstr ""
40874069

@@ -4283,10 +4265,6 @@ msgstr ""
42834265
msgid "value out of range of target"
42844266
msgstr ""
42854267

4286-
#: ports/espressif/common-hal/watchdog/WatchDogTimer.c
4287-
msgid "watchdog not initialized"
4288-
msgstr ""
4289-
42904268
#: shared-bindings/is31fl3741/FrameBuffer.c
42914269
msgid "width must be greater than zero"
42924270
msgstr ""

main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,12 @@ void supervisor_execution_status(void) {
241241
}
242242
#endif
243243

244+
#if CIRCUITPY_WATCHDOG
245+
pyexec_result_t *pyexec_result(void) {
246+
return &_exec_result;
247+
}
248+
#endif
249+
244250
// Look for the first file that exists in the list of filenames, using mp_import_stat().
245251
// Return its index. If no file found, return -1.
246252
STATIC const char *first_existing_file_in_list(const char *const *filenames, size_t n_filenames) {

ports/atmel-samd/common-hal/watchdog/WatchDogTimer.c

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,76 +30,95 @@
3030

3131
#include "shared-bindings/watchdog/__init__.h"
3232
#include "shared-bindings/watchdog/WatchDogTimer.h"
33+
#include "shared-bindings/microcontroller/__init__.h"
34+
3335
#include "common-hal/watchdog/WatchDogTimer.h"
3436

3537
#include "component/wdt.h"
3638

39+
#define SYNC_CTRL_WRITE while (WDT->SYNCBUSY.reg) {}
40+
41+
static void watchdog_disable(void) {
42+
// disable watchdog
43+
WDT->CTRLA.reg = 0;
44+
SYNC_CTRL_WRITE
45+
}
46+
47+
static void watchdog_enable(watchdog_watchdogtimer_obj_t *self) {
48+
// disable watchdog for config
49+
watchdog_disable();
50+
51+
int wdt_cycles = (int)(self->timeout * 1024);
52+
if (wdt_cycles < 8) {
53+
wdt_cycles = 8;
54+
}
55+
56+
// ceil(log2(n)) = 32 - __builtin_clz(n - 1) when n > 1 (if int is 32 bits)
57+
int log2_wdt_cycles = (sizeof(int) * CHAR_BIT) - __builtin_clz(wdt_cycles - 1);
58+
int setting = log2_wdt_cycles - 3; // CYC8_Val is 0
59+
60+
OSC32KCTRL->OSCULP32K.bit.EN1K = 1; // Enable out 1K (for WDT)
61+
62+
WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt
63+
WDT->CONFIG.bit.PER = setting; // Set period for chip reset
64+
WDT->CTRLA.bit.WEN = 0; // Disable window mode
65+
SYNC_CTRL_WRITE
66+
common_hal_watchdog_feed(self); // Clear watchdog interval
67+
WDT->CTRLA.bit.ENABLE = 1; // Start watchdog now!
68+
SYNC_CTRL_WRITE
69+
}
70+
3771
void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self) {
3872
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
3973
}
4074

4175
void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self) {
42-
if (self->mode == WATCHDOGMODE_RESET) {
43-
mp_raise_RuntimeError(translate("WatchDogTimer cannot be deinitialized once mode is set to RESET"));
44-
} else {
45-
self->mode = WATCHDOGMODE_NONE;
76+
if (self->mode == WATCHDOGMODE_NONE) {
77+
return;
4678
}
79+
watchdog_disable();
80+
self->mode = WATCHDOGMODE_NONE;
4781
}
4882

4983
mp_float_t common_hal_watchdog_get_timeout(watchdog_watchdogtimer_obj_t *self) {
5084
return self->timeout;
5185
}
5286

53-
STATIC void setup_wdt(watchdog_watchdogtimer_obj_t *self, int setting) {
54-
OSC32KCTRL->OSCULP32K.bit.EN1K = 1; // Enable out 1K (for WDT)
55-
56-
// disable watchdog for config
57-
WDT->CTRLA.reg = 0;
58-
while (WDT->SYNCBUSY.reg) { // Sync CTRL write
59-
}
60-
61-
WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt
62-
WDT->CONFIG.bit.PER = setting; // Set period for chip reset
63-
WDT->CTRLA.bit.WEN = 0; // Disable window mode
64-
while (WDT->SYNCBUSY.reg) { // Sync CTRL write
65-
}
66-
common_hal_watchdog_feed(self); // Clear watchdog interval
67-
WDT->CTRLA.bit.ENABLE = 1; // Start watchdog now!
68-
while (WDT->SYNCBUSY.reg) {
69-
}
70-
}
71-
7287
void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self, mp_float_t new_timeout) {
73-
int wdt_cycles = (int)(new_timeout * 1024);
74-
if (wdt_cycles < 8) {
75-
wdt_cycles = 8;
76-
}
77-
if (wdt_cycles > 16384) {
78-
mp_raise_ValueError(translate("timeout duration exceeded the maximum supported value"));
88+
if (!(self->timeout < new_timeout || self->timeout > new_timeout)) {
89+
return;
7990
}
80-
// ceil(log2(n)) = 32 - __builtin_clz(n - 1) when n > 1 (if int is 32 bits)
81-
int log2_wdt_cycles = (sizeof(int) * CHAR_BIT) - __builtin_clz(wdt_cycles - 1);
82-
int setting = log2_wdt_cycles - 3; // CYC8_Val is 0
83-
float timeout = (8 << setting) / 1024.f;
91+
92+
mp_arg_validate_int_max(new_timeout, 16, MP_QSTR_timeout);
93+
self->timeout = new_timeout;
8494

8595
if (self->mode == WATCHDOGMODE_RESET) {
86-
setup_wdt(self, setting);
96+
watchdog_enable(self);
8797
}
88-
self->timeout = timeout;
8998
}
9099

91100
watchdog_watchdogmode_t common_hal_watchdog_get_mode(watchdog_watchdogtimer_obj_t *self) {
92101
return self->mode;
93102
}
94103

95104
void common_hal_watchdog_set_mode(watchdog_watchdogtimer_obj_t *self, watchdog_watchdogmode_t new_mode) {
96-
if (self->mode != new_mode) {
97-
if (new_mode == WATCHDOGMODE_RAISE) {
98-
mp_raise_NotImplementedError(translate("RAISE mode is not implemented"));
99-
} else if (new_mode == WATCHDOGMODE_NONE) {
105+
if (self->mode == new_mode) {
106+
return;
107+
}
108+
109+
switch (new_mode) {
110+
case WATCHDOGMODE_NONE:
100111
common_hal_watchdog_deinit(self);
101-
}
102-
self->mode = new_mode;
103-
common_hal_watchdog_set_timeout(self, self->timeout);
112+
break;
113+
case WATCHDOGMODE_RAISE:
114+
mp_raise_NotImplementedError(NULL);
115+
break;
116+
case WATCHDOGMODE_RESET:
117+
watchdog_enable(self);
118+
break;
119+
default:
120+
return;
104121
}
122+
123+
self->mode = new_mode;
105124
}

ports/atmel-samd/common-hal/watchdog/WatchDogTimer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H
2929

3030
#include "py/obj.h"
31+
32+
#include "shared-module/watchdog/__init__.h"
33+
3134
#include "shared-bindings/watchdog/WatchDogMode.h"
3235
#include "shared-bindings/watchdog/WatchDogTimer.h"
3336

@@ -37,7 +40,4 @@ struct _watchdog_watchdogtimer_obj_t {
3740
watchdog_watchdogmode_t mode;
3841
};
3942

40-
// This needs to be called in order to disable the watchdog
41-
// void watchdog_reset(void);
42-
4343
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H

ports/atmel-samd/supervisor/port.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,13 +388,16 @@ void reset_port(void) {
388388
#if CIRCUITPY_BUSIO
389389
reset_sercoms();
390390
#endif
391+
391392
#if CIRCUITPY_AUDIOIO
392393
audio_dma_reset();
393394
audioout_reset();
394395
#endif
396+
395397
#if CIRCUITPY_AUDIOBUSIO
396398
pdmin_reset();
397399
#endif
400+
398401
#if CIRCUITPY_AUDIOBUSIO_I2SOUT
399402
i2sout_reset();
400403
#endif
@@ -406,14 +409,18 @@ void reset_port(void) {
406409
#if CIRCUITPY_TOUCHIO && CIRCUITPY_TOUCHIO_USE_NATIVE
407410
touchin_reset();
408411
#endif
412+
409413
eic_reset();
414+
410415
#if CIRCUITPY_PULSEIO
411416
pulsein_reset();
412417
pulseout_reset();
413418
#endif
419+
414420
#if CIRCUITPY_PWMIO
415421
pwmout_reset();
416422
#endif
423+
417424
#if CIRCUITPY_PWMIO || CIRCUITPY_AUDIOIO || CIRCUITPY_FREQUENCYIO
418425
reset_timers();
419426
#endif
@@ -423,6 +430,10 @@ void reset_port(void) {
423430
analogout_reset();
424431
#endif
425432

433+
#if CIRCUITPY_WATCHDOG
434+
watchdog_reset();
435+
#endif
436+
426437
reset_gclks();
427438

428439
#if CIRCUITPY_PEW

0 commit comments

Comments
 (0)