From 6d1e226ce646056f7a24e26985397a8ee3cde110 Mon Sep 17 00:00:00 2001 From: XuGuohui Date: Wed, 29 Mar 2023 00:15:38 +0800 Subject: [PATCH] Merge pull request #2635 from particle-iot/fix/nrf52_watchdog/sc116493 nRF52: watchdog timeout is not accurate --- hal/src/nRF52840/watchdog_hal.cpp | 17 +++++++++----- third_party/nrf5_sdk/nrf5_sdk | 2 +- user/tests/wiring/watchdog/watchdog.cpp | 30 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/hal/src/nRF52840/watchdog_hal.cpp b/hal/src/nRF52840/watchdog_hal.cpp index 6bfcd8cc1a..da1e121fa9 100644 --- a/hal/src/nRF52840/watchdog_hal.cpp +++ b/hal/src/nRF52840/watchdog_hal.cpp @@ -63,7 +63,7 @@ class WatchdogLock { class Nrf52Watchdog : public Watchdog { public: int init(const hal_watchdog_config_t* config) { - CHECK_FALSE(initialized_, SYSTEM_ERROR_INVALID_STATE); + CHECK_FALSE(started(), SYSTEM_ERROR_INVALID_STATE); CHECK_TRUE(config && (config->size > 0), SYSTEM_ERROR_INVALID_ARGUMENT); CHECK_TRUE(config->timeout_ms >= WATCHDOG_MIN_TIMEOUT, SYSTEM_ERROR_INVALID_ARGUMENT); CHECK_TRUE(config->timeout_ms <= WATCHDOG_MAX_TIMEOUT, SYSTEM_ERROR_INVALID_ARGUMENT); @@ -80,10 +80,17 @@ class Nrf52Watchdog : public Watchdog { } else { nrfConfig.behaviour = NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT; } - nrfx_err_t ret = nrfx_wdt_init(&nrfConfig, nrf52WatchdogEventHandler); - SPARK_ASSERT(ret == NRF_SUCCESS); - ret = nrfx_wdt_channel_alloc(&channelId_); - SPARK_ASSERT(ret == NRF_SUCCESS); + if (!initialized_) { + nrfx_err_t ret = nrfx_wdt_init(&nrfConfig, nrf52WatchdogEventHandler); + SPARK_ASSERT(ret == NRF_SUCCESS); + ret = nrfx_wdt_channel_alloc(&channelId_); + SPARK_ASSERT(ret == NRF_SUCCESS); + } else { + nrf_wdt_behaviour_set(nrfConfig.behaviour); + uint64_t ticks = (nrfConfig.reload_value * 32768ULL) / 1000; + SPARK_ASSERT(ticks <= UINT32_MAX); + nrf_wdt_reload_value_set((uint32_t)ticks); + } memcpy(&info_.config, config, std::min(info_.config.size, config->size)); info_.state = HAL_WATCHDOG_STATE_CONFIGURED; diff --git a/third_party/nrf5_sdk/nrf5_sdk b/third_party/nrf5_sdk/nrf5_sdk index 20ec87b968..ef292929f8 160000 --- a/third_party/nrf5_sdk/nrf5_sdk +++ b/third_party/nrf5_sdk/nrf5_sdk @@ -1 +1 @@ -Subproject commit 20ec87b96875a1bfc2a2a99f2fe2c6d8d46f87dc +Subproject commit ef292929f836948ceef6f575f454de9bec040fd2 diff --git a/user/tests/wiring/watchdog/watchdog.cpp b/user/tests/wiring/watchdog/watchdog.cpp index 8310bfc7e4..4576276145 100644 --- a/user/tests/wiring/watchdog/watchdog.cpp +++ b/user/tests/wiring/watchdog/watchdog.cpp @@ -174,5 +174,35 @@ test(WATCHDOG_07_notify_2) { assertEqual(magick, 0xdeadbeef); } +#include "nrf_wdt.h" +static void checkError(system_tick_t expectedTo) { + uint32_t reg = nrf_wdt_reload_value_get(); + uint64_t actualTo = (reg * 1000ULL) / 32768; + uint32_t delta = (expectedTo > actualTo) ? (expectedTo - actualTo) : (actualTo - expectedTo); + // Serial.printlnf("expected: %ld, actual: %lu, delta: %d", expectedTo, (uint32_t)actualTo, delta); + assertLessOrEqual(delta, 1); + assertMoreOrEqual(delta, 0); +} + #endif // HAL_PLATFORM_NRF52840 +test(WATCHDDOG_100_reload_value_is_calculated_correctly) { + constexpr system_tick_t TEST_LOOP_CNT = 100; + + WatchdogInfo info; + assertEqual(0, Watchdog.getInfo(info)); + + for (uint16_t i = 1; i <= TEST_LOOP_CNT; i++) { + system_tick_t expectedTo; + if (i == 1) { + expectedTo = info.minTimeout(); + } else if (i == TEST_LOOP_CNT) { + expectedTo = info.maxTimeout(); + } else { + expectedTo = random(info.minTimeout(), info.maxTimeout()); + } + assertEqual(0, Watchdog.init(WatchdogConfiguration().timeout(expectedTo))); + + checkError(expectedTo); + } +}