From 160fafcd3791c17b30fdc1f7008799cee0ce7669 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 14 Apr 2023 15:28:16 +0200 Subject: [PATCH] Provide common API for triggering a synchronous or asynchronous reset on various Cyphal enabled platforms. (#6) --- README.md | 7 +++ examples/AsyncReset/AsyncReset.ino | 41 +++++++++++++++ examples/SyncReset/SyncReset.ino | 30 +++++++++++ keywords.txt | 8 +++ src/107-Arduino-Cyphal-Support.h | 1 + src/reset/reset-rp2040.cpp | 83 ++++++++++++++++++++++++++++++ src/reset/reset.h | 76 +++++++++++++++++++++++++++ 7 files changed, 246 insertions(+) create mode 100644 examples/AsyncReset/AsyncReset.ino create mode 100644 examples/SyncReset/SyncReset.ino create mode 100644 src/reset/reset-rp2040.cpp create mode 100644 src/reset/reset.h diff --git a/README.md b/README.md index 5fb0b28..f9d728a 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,10 @@ if (auto const opt_err = cyphal::support::save(kv_storage, *node_registry); opt_ Serial.println(static_cast(opt_err.value())); } ``` +* API for performing **synchronous and asynchronous resets**. +```C++ +/* Synchronous reset: */ +cyphal::support::platform::reset_sync(std::chrono::milliseconds(5000)); +/* Asynchronous reset: */ +cyphal::support::platform::reset_async(std::chrono::milliseconds(5000)); +``` diff --git a/examples/AsyncReset/AsyncReset.ino b/examples/AsyncReset/AsyncReset.ino new file mode 100644 index 0000000..a1a2316 --- /dev/null +++ b/examples/AsyncReset/AsyncReset.ino @@ -0,0 +1,41 @@ +/** + * This software is distributed under the terms of the MIT License. + * Copyright (c) 2023 LXRobotics. + * Author: Alexander Entinger + * Contributors: https://github.com/107-systems/107-Arduino-Cyphal-Support/graphs/contributors. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include <107-Arduino-Cyphal-Support.h> + +/************************************************************************************** + * GLOBAL VARIABLES + **************************************************************************************/ + +static unsigned long start = 0; + +/************************************************************************************** + * SETUP/LOOP + **************************************************************************************/ + +void setup() +{ + Serial.begin(115200); + while (!Serial) { } + + Serial.println("Trigger async reset in 5 seconds ..."); + cyphal::support::platform::reset_async(std::chrono::milliseconds(5000)); + start = millis(); +} + +void loop() +{ + char msg[32] = {0}; + snprintf(msg, sizeof(msg), "[ %ld ]", (millis() - start)); + Serial.println(msg); + + delay(100); +} diff --git a/examples/SyncReset/SyncReset.ino b/examples/SyncReset/SyncReset.ino new file mode 100644 index 0000000..5c326f7 --- /dev/null +++ b/examples/SyncReset/SyncReset.ino @@ -0,0 +1,30 @@ +/** + * This software is distributed under the terms of the MIT License. + * Copyright (c) 2023 LXRobotics. + * Author: Alexander Entinger + * Contributors: https://github.com/107-systems/107-Arduino-Cyphal-Support/graphs/contributors. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include <107-Arduino-Cyphal-Support.h> + +/************************************************************************************** + * SETUP/LOOP + **************************************************************************************/ + +void setup() +{ + Serial.begin(115200); + while (!Serial) { } + + Serial.println("Trigger sync reset in 5 seconds ..."); + cyphal::support::platform::reset_sync(std::chrono::milliseconds(5000)); +} + +void loop() +{ + +} diff --git a/keywords.txt b/keywords.txt index 362ad74..8c23d89 100644 --- a/keywords.txt +++ b/keywords.txt @@ -19,10 +19,18 @@ KeyValueStorage_littlefs KEYWORD1 instance KEYWORD2 value KEYWORD2 + get KEYWORD2 put KEYWORD2 drop KEYWORD2 +reset KEYWORD2 +reset_sync KEYWORD2 +reset_async KEYWORD2 +is_async_reset_pending KEYWORD2 + ####################################### # Constants (LITERAL1) ####################################### + +InvalidParam LITERAL1 diff --git a/src/107-Arduino-Cyphal-Support.h b/src/107-Arduino-Cyphal-Support.h index 257d8c2..f0d2602 100644 --- a/src/107-Arduino-Cyphal-Support.h +++ b/src/107-Arduino-Cyphal-Support.h @@ -11,5 +11,6 @@ * INCLUDE **************************************************************************************/ +#include "reset/reset.h" #include "storage/storage.h" #include "uniqueid/uniqueid.h" diff --git a/src/reset/reset-rp2040.cpp b/src/reset/reset-rp2040.cpp new file mode 100644 index 0000000..d6b2e98 --- /dev/null +++ b/src/reset/reset-rp2040.cpp @@ -0,0 +1,83 @@ +/** + * This software is distributed under the terms of the MIT License. + * Copyright (c) 2023 LXRobotics. + * Author: Alexander Entinger + * Contributors: https://github.com/107-systems/107-Arduino-Cyphal-Support/graphs/contributors. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "reset.h" + +#if defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED) + +#include "hardware/watchdog.h" + +/* Provide prototype for Arduino's delay function. */ +extern "C" void delay(unsigned long); + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace cyphal::support::platform +{ + +/************************************************************************************** + * GLOBAL CONSTANTS + **************************************************************************************/ + +static uint32_t const RP2040_MAX_DELAY_ms = 0x7FFFFF; + +/************************************************************************************** + * GLOBAL VARIABLES + **************************************************************************************/ + +static bool is_async_reset_pending_flag = false; + +/************************************************************************************** + * FUNCTION DEFINITION + **************************************************************************************/ + +std::optional reset() +{ + watchdog_enable(/* delay_ms */ 0, /* pause_on_debug */ true); + return std::nullopt; +} + +std::optional reset_sync(std::chrono::milliseconds const ms) +{ + if (ms.count() > RP2040_MAX_DELAY_ms) + return Error::InvalidParam; + + watchdog_enable(/* delay_ms */ ms.count(), /* pause_on_debug */ true); + for(;;) { delay(100); } /* Wait for the watchdog to bite. */ + return std::nullopt; +} + +std::optional reset_async(std::chrono::milliseconds const ms) +{ + if (ms.count() > RP2040_MAX_DELAY_ms) + return Error::InvalidParam; + + watchdog_enable(/* delay_ms */ ms.count(), /* pause_on_debug */ true); + + is_async_reset_pending_flag = true; + + return std::nullopt; +} + +bool is_async_reset_pending() +{ + return is_async_reset_pending_flag; +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* cyphal::support::platform */ + +#endif /* defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED) */ diff --git a/src/reset/reset.h b/src/reset/reset.h new file mode 100644 index 0000000..c88d1ac --- /dev/null +++ b/src/reset/reset.h @@ -0,0 +1,76 @@ +/** + * This software is distributed under the terms of the MIT License. + * Copyright (c) 2023 LXRobotics. + * Author: Alexander Entinger + * Contributors: https://github.com/107-systems/107-Arduino-Cyphal-Support/graphs/contributors. + */ + +#pragma once + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include +#include + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace cyphal::support::platform +{ + +/************************************************************************************** + * TYPEDEF + **************************************************************************************/ + +enum class Error +{ + InvalidParam, +}; + +/************************************************************************************** + * FUNCTION DECLARATION + **************************************************************************************/ + +/* Immediately after calling this method a reset is performed. */ +std::optional reset() +#if !defined(ARDUINO_ARCH_RP2040) +__attribute__ ((error("Currently the reset API only supports ARDUINO_ARCH_RP2040."))) +#endif +; + +/* This method performs a reset in 'ms' milliseconds after its invocation, + * blocking while waiting for the time to expire. + */ +std::optional reset_sync(std::chrono::milliseconds const ms) +#if !defined(ARDUINO_ARCH_RP2040) +__attribute__ ((error("Currently the reset API only supports ARDUINO_ARCH_RP2040."))) +#endif +; + +/* This method performs a reset in 'ms' milliseconds after its invocation, + * but returns immediately after its invocation. + */ +std::optional reset_async(std::chrono::milliseconds const ms) +#if !defined(ARDUINO_ARCH_RP2040) +__attribute__ ((error("Currently the reset API only supports ARDUINO_ARCH_RP2040."))) +#endif +; + +/* Returns true if currently an async reset is pending. Since this + * functionality is implemented via watchdog it is necessary to stop + * regular watchdog feeding i.e. in the main loop. + */ +bool is_async_reset_pending() +#if !defined(ARDUINO_ARCH_RP2040) +__attribute__ ((error("Currently the reset API only supports ARDUINO_ARCH_RP2040."))) +#endif +; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* cyphal::support::platform */