Skip to content

Commit 4454d82

Browse files
committed
[nrf] Add watchdog timer implementation for NRF5x
1 parent 65ac765 commit 4454d82

9 files changed

Lines changed: 182 additions & 3 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -787,9 +787,9 @@ Please [discover modm's peripheral drivers for your specific device][discover].
787787
<td align="center">○</td>
788788
<td align="center">○</td>
789789
<td align="center">○</td>
790-
<td align="center"></td>
791-
<td align="center"></td>
792-
<td align="center"></td>
790+
<td align="center"></td>
791+
<td align="center"></td>
792+
<td align="center"></td>
793793
<td align="center">○</td>
794794
<td align="center">○</td>
795795
<td align="center">○</td>

examples/nrf5340-dk/wdt/main.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2026, Niklas Hauser
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
/*
13+
# nRF5340-DK watchdog (app core)
14+
15+
Watchdog example for the nRF5340 application core.
16+
17+
- Target: `nrf5340-xxaa@app`
18+
- Uses app-core-owned `Led1` and `Button1` from the BSP.
19+
- If `Button1` is held for more than 4 seconds after the watchdog starts,
20+
the MCU resets.
21+
- A watchdog reset is indicated by a faster LED blink sequence after startup.
22+
*/
23+
24+
#include <modm/board.hpp>
25+
26+
using namespace Board;
27+
using namespace std::chrono_literals;
28+
29+
int
30+
main()
31+
{
32+
Board::initialize();
33+
Wdt::initialize<SystemClock, 4s>();
34+
auto startupDelay = 100ms;
35+
36+
MODM_LOG_INFO << "nRF5340-DK watchdog example" << modm::endl;
37+
MODM_LOG_INFO << "Press and hold Button1 for more than 4s to trigger a watchdog reset." << modm::endl;
38+
if (NRF_RESET->RESETREAS & RESET_RESETREAS_DOG0_Msk) {
39+
NRF_RESET->RESETREAS = RESET_RESETREAS_DOG0_Msk;
40+
MODM_LOG_INFO << "Previous reset reason: watchdog." << modm::endl;
41+
startupDelay = 50ms;
42+
}
43+
44+
uint32_t counter(0);
45+
while (counter < 10)
46+
{
47+
Led1::toggle();
48+
modm::delay(startupDelay);
49+
MODM_LOG_INFO << "startup: " << counter++ << modm::endl;
50+
}
51+
52+
Wdt::enable();
53+
MODM_LOG_INFO << "Watchdog started." << modm::endl;
54+
55+
while (true)
56+
{
57+
Led1::toggle();
58+
modm::delay(500ms);
59+
if (!Button1::read()) { Wdt::trigger(); }
60+
MODM_LOG_INFO << "loop: " << counter++ << modm::endl;
61+
}
62+
63+
return 0;
64+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<library>
2+
<extends>modm:nrf5340-dk</extends>
3+
<options>
4+
<option name="modm:build:build.path">../../../build/nrf5340-dk/wdt</option>
5+
</options>
6+
<modules>
7+
<module>modm:platform:wdt</module>
8+
<module>modm:build:scons</module>
9+
</modules>
10+
</library>

src/modm/board/nrf51422_dk/board.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct SystemClock
3131
{
3232
static constexpr uint32_t Frequency = 16_MHz;
3333
static constexpr uint32_t Uart0 = 16_MHz;
34+
static constexpr uint32_t Wdt = 32.768_kHz;
3435

3536
static bool inline
3637
enable()

src/modm/board/nrf52840_dk/board.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct SystemClock
3030
{
3131
static constexpr uint32_t Frequency = 64_MHz;
3232
static constexpr uint32_t Uarte0 = 16_MHz;
33+
static constexpr uint32_t Wdt = 32.768_kHz;
3334

3435
static bool inline
3536
enable()

src/modm/board/nrf5340_dk/board.hpp.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct SystemClock
3434
%% endif
3535
static constexpr uint32_t Uarte0 = 16_MHz;
3636
static constexpr uint32_t Uarte1 = 16_MHz;
37+
static constexpr uint32_t Wdt = 32.768_kHz;
3738

3839
static bool inline
3940
enable()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright (c) 2026, Niklas Hauser
5+
#
6+
# This file is part of the modm project.
7+
#
8+
# This Source Code Form is subject to the terms of the Mozilla Public
9+
# License, v. 2.0. If a copy of the MPL was not distributed with this
10+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
11+
# -----------------------------------------------------------------------------
12+
13+
def init(module):
14+
module.name = ":platform:wdt"
15+
module.description = "Watchdog Timer"
16+
17+
18+
def prepare(module, options):
19+
device = options[":target"]
20+
21+
module.depends(":cmsis:device", ":math:algorithm")
22+
return device.has_driver("wdt:nrf*")
23+
24+
25+
def build(env):
26+
target = env[":target"].identifier
27+
28+
if target.family == "53":
29+
peripheral = "NRF_WDT0" if target.core == "app" else "NRF_WDT_NS"
30+
else:
31+
peripheral = "NRF_WDT"
32+
33+
env.outbasepath = "modm/src/modm/platform/wdt"
34+
env.substitutions = {
35+
"peripheral": peripheral,
36+
}
37+
env.template("wdt.hpp.in")
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2026, Niklas Hauser
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#pragma once
13+
14+
#include <algorithm>
15+
#include <modm/architecture/interface/peripheral.hpp>
16+
#include <modm/math/algorithm/prescaler.hpp>
17+
#include "../device.hpp"
18+
19+
20+
namespace modm::platform
21+
{
22+
23+
/// @ingroup modm_platform_wdt
24+
class Wdt : public ::modm::PeripheralDriver
25+
{
26+
public:
27+
static inline void
28+
initialize(uint32_t reload)
29+
{
30+
{{ peripheral }}->CRV = reload;
31+
{{ peripheral }}->RREN = WDT_RREN_RR0_Enabled;
32+
}
33+
34+
template< class SystemClock, milliseconds_t timeout, percent_t tolerance=pct(1) >
35+
static void
36+
initialize()
37+
{
38+
constexpr auto result = modm::GenericPrescaler<double>::from_linear(
39+
SystemClock::Wdt, 1000.0 / timeout.count(), 0xFul, 0xFFFFFFFFul);
40+
assertDurationInTolerance< double(result.prescaler) / SystemClock::Wdt,
41+
timeout.count() / 1000.0, tolerance >();
42+
initialize(result.prescaler - 1);
43+
}
44+
45+
static inline void
46+
enable()
47+
{
48+
{{ peripheral }}->TASKS_START = 1ul;
49+
}
50+
51+
static inline void
52+
trigger()
53+
{
54+
{{ peripheral }}->RR[0] = WDT_RR_RR_Reload;
55+
}
56+
57+
static inline bool
58+
isRunning()
59+
{
60+
return {{ peripheral }}->RUNSTATUS;
61+
}
62+
};
63+
64+
}

tools/scripts/generate_hal_matrix.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def hal_get_modules():
108108
"fsmc": "External Memory",
109109
"flash": "Internal Flash",
110110
"iwdg": "Watchdog",
111+
"wdt": "Watchdog",
111112
"timer": "Timer",
112113
"i2c": "I<sup>2</sup>C",
113114
"usart": "UART",

0 commit comments

Comments
 (0)