From 288489d8d1252f570fd179727e4853da35dc61bb Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 9 Mar 2021 08:17:48 +0100 Subject: [PATCH 1/3] Adding watchdog for SAMD architecture which is continually fed within ArduinoIoTCloud::update() to reset the board in case some function becomes stuck. --- src/ArduinoIoTCloudTCP.cpp | 27 +++++++++++++++++++++++++++ src/utility/watchdog/Watchdog.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/utility/watchdog/Watchdog.h diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4d6d294e4..7b0ead11b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -43,6 +43,8 @@ #include "cbor/CBOREncoder.h" +#include "utility/watchdog/Watchdog.h" + /****************************************************************************** * EXTERN ******************************************************************************/ @@ -262,11 +264,36 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) } #endif /* OTA_STORAGE_SNU */ +#ifdef ARDUINO_ARCH_SAMD + /* Since we do not control what code the user inserts + * between ArduinoIoTCloudTCP::begin() and the first + * call to ArduinoIoTCloudTCP::update() it is wise to + * set a rather large timeout at first. + */ + Watchdog.enable(120 * 1000); +#endif /* ARDUINO_ARCH_SAMD */ + return 1; } void ArduinoIoTCloudTCP::update() { +#ifdef ARDUINO_ARCH_SAMD + /* Now that we are within the regularly called function + * ArduinoIoTCloudTCP::update() it's a wise idea to reduce + * the watchdog timeout to a smaller amount of time. + */ + static bool is_watchdog_set = false; + if (!is_watchdog_set) { + Watchdog.enable(30 * 1000); + is_watchdog_set = true; + } + /* Feed the watchdog. If any of the functions called below + * get stuck than we can at least reset and recover. + */ + Watchdog.reset(); +#endif /* ARDUINO_ARCH_SAMD */ + /* Run through the state machine. */ State next_state = _state; switch (_state) diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h new file mode 100644 index 000000000..b7a1c39aa --- /dev/null +++ b/src/utility/watchdog/Watchdog.h @@ -0,0 +1,29 @@ +/* + This file is part of ArduinoIoTCloud. + + Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of arduino-cli. + The terms of this license can be found at: + https://www.gnu.org/licenses/gpl-3.0.en.html + + You can be released from the requirements of the above licenses by purchasing + a commercial license. Buying such a license is mandatory if you want to modify or + otherwise use the software for commercial activities involving the Arduino + software without disclosing the source code of your own applications. To purchase + a commercial license, send an email to license@arduino.cc. +*/ + +#ifndef ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ +#define ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#ifdef ARDUINO_ARCH_SAMD +# include +#endif /* ARDUINO_ARCH_SAMD */ + +#endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */ From 50183c2ed40c26c5971d9c5ca7d221687bf03f0a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 9 Mar 2021 08:20:53 +0100 Subject: [PATCH 2/3] Adding dependency 'Adafruit_SleepyDog' to CI build. --- .github/workflows/compile-examples.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 559a184ac..7e1595839 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -63,6 +63,7 @@ jobs: - name: ArduinoECCX08 - name: RTCZero - name: WiFi101 + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning # MKR WiFi 1010, Nano 33 IoT @@ -77,6 +78,7 @@ jobs: - name: WiFiNINA - name: Arduino_JSON - name: ArduinoBearSSL + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning - examples/utility/SelfProvisioning @@ -113,6 +115,7 @@ jobs: - name: ArduinoECCX08 - name: RTCZero - name: MKRGSM + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning # NB boards @@ -124,6 +127,7 @@ jobs: - name: ArduinoECCX08 - name: RTCZero - name: MKRNB + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning # Portenta From c6f03363d1af418790239eecf8fa2467f6698297 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 10 Mar 2021 11:01:21 +0100 Subject: [PATCH 3/3] Since the watchdog timeout can't be larger than 16 seconds adjust the code accordingly. Also add watchdog resets within the OTA callback to prevent the watchdog from biting during OTA. --- src/ArduinoIoTCloudTCP.cpp | 19 +++++++++---------- src/utility/watchdog/Watchdog.h | 1 + 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7b0ead11b..d3a5db3fd 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -270,7 +270,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) * call to ArduinoIoTCloudTCP::update() it is wise to * set a rather large timeout at first. */ - Watchdog.enable(120 * 1000); + Watchdog.enable(SAMD_WATCHDOG_MAX_TIME_ms); #endif /* ARDUINO_ARCH_SAMD */ return 1; @@ -279,15 +279,6 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) void ArduinoIoTCloudTCP::update() { #ifdef ARDUINO_ARCH_SAMD - /* Now that we are within the regularly called function - * ArduinoIoTCloudTCP::update() it's a wise idea to reduce - * the watchdog timeout to a smaller amount of time. - */ - static bool is_watchdog_set = false; - if (!is_watchdog_set) { - Watchdog.enable(30 * 1000); - is_watchdog_set = true; - } /* Feed the watchdog. If any of the functions called below * get stuck than we can at least reset and recover. */ @@ -549,6 +540,10 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { +#ifdef ARDUINO_ARCH_SAMD + Watchdog.reset(); +#endif /* ARDUINO_ARCH_SAMD */ + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); #if OTA_STORAGE_SNU @@ -556,6 +551,10 @@ void ArduinoIoTCloudTCP::onOTARequest() WiFiStorage.remove("/fs/UPDATE.BIN.LZSS"); WiFiStorage.remove("/fs/UPDATE.BIN.LZSS.TMP"); +#ifdef ARDUINO_ARCH_SAMD + Watchdog.reset(); +#endif /* ARDUINO_ARCH_SAMD */ + /* Trigger direct download to nina module. */ uint8_t nina_ota_err_code = 0; if (!WiFiStorage.downloadOTA(_ota_url.c_str(), &nina_ota_err_code)) diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index b7a1c39aa..9f81e372a 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -24,6 +24,7 @@ #ifdef ARDUINO_ARCH_SAMD # include +# define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) #endif /* ARDUINO_ARCH_SAMD */ #endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */