Skip to content

Commit

Permalink
Provide common API for triggering a synchronous or asynchronous reset…
Browse files Browse the repository at this point in the history
… on various Cyphal enabled platforms. (#6)
  • Loading branch information
aentinger authored Apr 14, 2023
1 parent 058b42a commit 160fafc
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 0 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@ if (auto const opt_err = cyphal::support::save(kv_storage, *node_registry); opt_
Serial.println(static_cast<int>(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));
```
41 changes: 41 additions & 0 deletions examples/AsyncReset/AsyncReset.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* This software is distributed under the terms of the MIT License.
* Copyright (c) 2023 LXRobotics.
* Author: Alexander Entinger <[email protected]>
* 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);
}
30 changes: 30 additions & 0 deletions examples/SyncReset/SyncReset.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* This software is distributed under the terms of the MIT License.
* Copyright (c) 2023 LXRobotics.
* Author: Alexander Entinger <[email protected]>
* 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()
{

}
8 changes: 8 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/107-Arduino-Cyphal-Support.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
* INCLUDE
**************************************************************************************/

#include "reset/reset.h"
#include "storage/storage.h"
#include "uniqueid/uniqueid.h"
83 changes: 83 additions & 0 deletions src/reset/reset-rp2040.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* This software is distributed under the terms of the MIT License.
* Copyright (c) 2023 LXRobotics.
* Author: Alexander Entinger <[email protected]>
* 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<Error> reset()
{
watchdog_enable(/* delay_ms */ 0, /* pause_on_debug */ true);
return std::nullopt;
}

std::optional<Error> 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<Error> 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) */
76 changes: 76 additions & 0 deletions src/reset/reset.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* This software is distributed under the terms of the MIT License.
* Copyright (c) 2023 LXRobotics.
* Author: Alexander Entinger <[email protected]>
* Contributors: https://github.com/107-systems/107-Arduino-Cyphal-Support/graphs/contributors.
*/

#pragma once

/**************************************************************************************
* INCLUDE
**************************************************************************************/

#include <chrono>
#include <optional>

/**************************************************************************************
* NAMESPACE
**************************************************************************************/

namespace cyphal::support::platform
{

/**************************************************************************************
* TYPEDEF
**************************************************************************************/

enum class Error
{
InvalidParam,
};

/**************************************************************************************
* FUNCTION DECLARATION
**************************************************************************************/

/* Immediately after calling this method a reset is performed. */
std::optional<Error> 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<Error> 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<Error> 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 */

0 comments on commit 160fafc

Please sign in to comment.