Skip to content

Commit 8e56a4e

Browse files
authored
Merge pull request #9 from pennam/wdt
Add watchdog timer support
2 parents 18426c4 + e18075b commit 8e56a4e

File tree

4 files changed

+351
-0
lines changed

4 files changed

+351
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Watchdog Refresh
3+
4+
This sketch shows how to enable the watchdog and
5+
refresh the timer to avoid resets
6+
7+
Watchdog intervals are limited to 7 timeout periods
8+
the library will select the best clock divisor and timeout
9+
according to the selected wdtInterval.
10+
11+
UNO R4 min wdtInterval 1ms / max wdtInterval 5592ms
12+
Comment out Serial.print() in the setup to make it work with
13+
small intervals
14+
15+
Portenta C33 min wdtInterval 1ms / max wdtInterval 2684ms
16+
17+
Circuit:
18+
- Portenta C33
19+
- UNO R4
20+
*/
21+
22+
#include <WDT.h>
23+
24+
const long ledInterval = 1000;
25+
unsigned long ledMillis = 0;
26+
bool ledState = true;
27+
const long wdtInterval = 2684;
28+
unsigned long wdtMillis = 0;
29+
30+
void setup() {
31+
Serial.begin(9600);
32+
while (!Serial);
33+
34+
pinMode(LED_BUILTIN, OUTPUT);
35+
36+
if(wdtInterval < 1) {
37+
Serial.println("Invalid watchdog interval");
38+
while(1){}
39+
}
40+
41+
if(WDT.begin(wdtInterval)) {
42+
Serial.print("WDT interval: ");
43+
WDT.refresh();
44+
Serial.print(WDT.getTimeout());
45+
WDT.refresh();
46+
Serial.println(" ms");
47+
WDT.refresh();
48+
} else {
49+
Serial.println("Error initializing watchdog");
50+
while(1){}
51+
}
52+
}
53+
54+
void loop() {
55+
if(millis() - ledMillis >= ledInterval) {
56+
digitalWrite(LED_BUILTIN, ledState);
57+
ledState = !ledState;
58+
ledMillis = millis();
59+
}
60+
61+
if(millis() - wdtMillis >= wdtInterval - 1) {
62+
WDT.refresh(); // Comment this line to stop refreshing the watchdog
63+
wdtMillis = millis();
64+
}
65+
66+
}

libraries/WDT/library.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=WDT
2+
version=0.0.1
3+
author=Arduino
4+
maintainer=Arduino <info@arduino.cc>
5+
sentence=Watchdog timer library for Renesas RA boards
6+
paragraph=
7+
category=Timing
8+
url=
9+
architectures=renesas

libraries/WDT/src/WDT.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
WDT.cpp
3+
Copyright (c) 2023 Arduino SA. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include "WDT.h"
21+
22+
WDTimer::WDTimer()
23+
: _is_initialized {false}
24+
, _p_ctrl {0}
25+
, _timeout {0}
26+
{
27+
28+
}
29+
30+
WDTimer::~WDTimer() { }
31+
32+
int WDTimer::begin(wdt_cfg_t config)
33+
{
34+
if (_is_initialized) {
35+
return 1;
36+
}
37+
38+
fsp_err_t err = R_WDT_Open(&_p_ctrl, &config);
39+
if (err != FSP_SUCCESS) {
40+
return 0;
41+
}
42+
R_WDT_Refresh(&_p_ctrl);
43+
_is_initialized = true;
44+
45+
return 1;
46+
}
47+
48+
int WDTimer::begin(uint32_t timeout_ms)
49+
{
50+
if (_is_initialized) {
51+
return 1;
52+
}
53+
54+
const uint8_t pr = getPrescaler(timeout_ms);
55+
if (pr == WDT_INVALID_TIMEOUT) {
56+
return 0;
57+
}
58+
59+
const uint8_t rl = getReload(pr, timeout_ms);
60+
61+
wdt_cfg_t p_cfg;
62+
p_cfg.timeout = (wdt_timeout_t)rl;
63+
p_cfg.clock_division = (wdt_clock_division_t)pr;
64+
p_cfg.window_start = WDT_WINDOW_START_100;
65+
p_cfg.window_end = WDT_WINDOW_END_0;
66+
p_cfg.reset_control = WDT_RESET_CONTROL_RESET;
67+
p_cfg.stop_control = WDT_STOP_CONTROL_ENABLE;
68+
69+
fsp_err_t err = R_WDT_Open(&_p_ctrl, &p_cfg);
70+
if (err != FSP_SUCCESS) {
71+
return 0;
72+
}
73+
74+
R_WDT_Refresh(&_p_ctrl);
75+
_is_initialized = true;
76+
77+
return 1;
78+
}
79+
80+
void WDTimer::refresh()
81+
{
82+
if (_is_initialized) {
83+
R_WDT_Refresh(&_p_ctrl);
84+
}
85+
}
86+
87+
uint32_t WDTimer::getTimeout()
88+
{
89+
if (_is_initialized) {
90+
return _timeout;
91+
}
92+
return 0;
93+
}
94+
95+
uint32_t WDTimer::getCounter()
96+
{
97+
uint32_t count = 0;
98+
99+
if (_is_initialized) {
100+
R_WDT_CounterGet (&_p_ctrl, &count);
101+
}
102+
return count;
103+
}
104+
105+
uint32_t WDTimer::getTicksMs()
106+
{
107+
return (R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKB) / 1000);
108+
}
109+
110+
uint32_t WDTimer::getMaxTimeout()
111+
{
112+
return ((WDT_RL_VALUES::RL_16384 * WDT_PR_VALUES::PR_8192) / getTicksMs());
113+
}
114+
115+
uint32_t WDTimer::getPrescalerMaxTimeout(WDT_PR_VALUES pr)
116+
{
117+
return ((WDT_RL_VALUES::RL_16384 * pr) / getTicksMs());
118+
}
119+
120+
uint8_t WDTimer::getPrescaler(uint32_t timeout_ms)
121+
{
122+
const uint32_t max_timeout_ms = getMaxTimeout();
123+
124+
if (timeout_ms > max_timeout_ms) {
125+
return WDT_INVALID_TIMEOUT;
126+
}
127+
128+
uint32_t pr;
129+
for (pr = 0; pr < WDT_PR_ARRAY_SIZE; pr++) {
130+
if (!prescaler_values[pr]) {
131+
break;
132+
}
133+
134+
const uint32_t pr_max_timeout_ms = getPrescalerMaxTimeout(prescaler_values[pr]);
135+
if (timeout_ms <= pr_max_timeout_ms) {
136+
break;
137+
}
138+
}
139+
140+
const uint32_t pr_max_timeout_ms = getPrescalerMaxTimeout(WDT_PR_VALUES::PR_128);
141+
if (pr > WDT_CLOCK_DIVISION_64 && timeout_ms <= pr_max_timeout_ms) {
142+
return WDT_CLOCK_DIVISION_128;
143+
}
144+
return pr;
145+
}
146+
147+
uint8_t WDTimer::getReload(uint8_t pr, uint32_t timeout_ms)
148+
{
149+
uint32_t rl;
150+
for (rl = 0; rl < WDT_RL_ARRAY_SIZE; rl++) {
151+
const uint32_t pr_max_timeout_ms = (reload_values[rl] * prescaler_values[pr]) / (getTicksMs());
152+
if (timeout_ms <= pr_max_timeout_ms) {
153+
_timeout = pr_max_timeout_ms;
154+
return rl;
155+
}
156+
}
157+
return rl;
158+
}
159+
160+
WDTimer WDT;

libraries/WDT/src/WDT.h

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
WDT.h
3+
Copyright (c) 2023 Arduino SA. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#ifndef _WDTIMER_H_
21+
#define _WDTIMER_H_
22+
23+
#include "r_wdt.h"
24+
25+
#define WDT_INVALID_TIMEOUT 255
26+
#define WDT_PR_ARRAY_SIZE 16
27+
#define WDT_RL_ARRAY_SIZE 7
28+
29+
class WDTimer {
30+
public:
31+
WDTimer();
32+
~WDTimer();
33+
34+
int begin(wdt_cfg_t config);
35+
int begin(uint32_t timeout_ms);
36+
void refresh();
37+
uint32_t getTimeout();
38+
uint32_t getCounter();
39+
40+
private:
41+
bool _is_initialized;
42+
wdt_instance_ctrl_t _p_ctrl;
43+
uint32_t _timeout;
44+
45+
/* WDT prescaler values */
46+
enum WDT_PR_VALUES
47+
{
48+
PR_INVALID = 0,
49+
PR_1 = 1,
50+
PR_4 = 4,
51+
PR_16 = 16,
52+
PR_32 = 32,
53+
PR_64 = 64,
54+
PR_128 = 128,
55+
PR_256 = 256,
56+
PR_512 = 512,
57+
PR_2048 = 2048,
58+
PR_8192 = 8192,
59+
};
60+
61+
/* WDT reload values */
62+
enum WDT_RL_VALUES
63+
{
64+
RL_128 = 128,
65+
RL_512 = 512,
66+
RL_1024 = 1024,
67+
RL_2048 = 2048,
68+
RL_4096 = 4096,
69+
RL_8192 = 8192,
70+
RL_16384 = 16384,
71+
};
72+
73+
/* Maps to WDT clock division ratio. e_wdt_clock_division */
74+
const WDT_PR_VALUES prescaler_values[WDT_PR_ARRAY_SIZE] =
75+
{
76+
WDT_PR_VALUES::PR_1,
77+
WDT_PR_VALUES::PR_4,
78+
WDT_PR_VALUES::PR_16,
79+
WDT_PR_VALUES::PR_32,
80+
WDT_PR_VALUES::PR_64,
81+
WDT_PR_VALUES::PR_256,
82+
WDT_PR_VALUES::PR_512,
83+
WDT_PR_VALUES::PR_2048,
84+
WDT_PR_VALUES::PR_8192,
85+
WDT_PR_VALUES::PR_INVALID,
86+
WDT_PR_VALUES::PR_INVALID,
87+
WDT_PR_VALUES::PR_INVALID,
88+
WDT_PR_VALUES::PR_INVALID,
89+
WDT_PR_VALUES::PR_INVALID,
90+
WDT_PR_VALUES::PR_INVALID,
91+
WDT_PR_VALUES::PR_128
92+
};
93+
94+
/* Maps to WDT time-out periods. e_wdt_timeout */
95+
const WDT_RL_VALUES reload_values[WDT_RL_ARRAY_SIZE] =
96+
{
97+
WDT_RL_VALUES::RL_128,
98+
WDT_RL_VALUES::RL_512,
99+
WDT_RL_VALUES::RL_1024,
100+
WDT_RL_VALUES::RL_2048,
101+
WDT_RL_VALUES::RL_4096,
102+
WDT_RL_VALUES::RL_8192,
103+
WDT_RL_VALUES::RL_16384
104+
};
105+
106+
uint32_t getTicksMs();
107+
uint32_t getMaxTimeout();
108+
uint32_t getPrescalerMaxTimeout(WDT_PR_VALUES pr);
109+
uint8_t getPrescaler(uint32_t timeout_ms);
110+
uint8_t getReload(uint8_t pr, uint32_t timeout_ms);
111+
112+
};
113+
114+
extern WDTimer WDT;
115+
116+
#endif

0 commit comments

Comments
 (0)