diff --git a/docs/cli_commands.md b/docs/cli_commands.md index 0e785f4e83..57ab6c6459 100644 --- a/docs/cli_commands.md +++ b/docs/cli_commands.md @@ -30,6 +30,16 @@ This document provides an overview of CLI commands that can be sent to MeshCore --- +### Enter the UF2 bootloader (nRF52 only) +**Usage:** +- `uf2reset` + +**Serial Only:** Yes + +**Note:** Reboots directly into the UF2 bootloader on supported nRF52 boards. + +--- + ### Reset the clock and reboot **Usage:** - `clkreboot` diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 2f7a0fffcb..ab035f6623 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -4,6 +4,29 @@ #include "AdvertDataHelpers.h" #include +#if defined(NRF52_PLATFORM) +#include +#include + +#ifndef DFU_MAGIC_UF2_RESET +#define DFU_MAGIC_UF2_RESET 0x57 +#endif + +static void resetToUf2Bootloader() { + uint8_t sd_enabled = 0; + sd_softdevice_is_enabled(&sd_enabled); + + if (sd_enabled) { + sd_power_gpregret_clr(0, 0xFF); + sd_power_gpregret_set(0, DFU_MAGIC_UF2_RESET); + } else { + NRF_POWER->GPREGRET = DFU_MAGIC_UF2_RESET; + } + + NVIC_SystemReset(); +} +#endif + #ifndef BRIDGE_MAX_BAUD #define BRIDGE_MAX_BAUD 115200 #endif @@ -210,6 +233,12 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch _board->powerOff(); // doesn't return } else if (memcmp(command, "reboot", 6) == 0) { _board->reboot(); // doesn't return + } else if (sender_timestamp == 0 && memcmp(command, "uf2reset", 8) == 0 && (command[8] == 0 || command[8] == ' ')) { // from serial command line only +#if defined(NRF52_PLATFORM) + resetToUf2Bootloader(); // doesn't return +#else + strcpy(reply, "ERR: unsupported"); +#endif } else if (memcmp(command, "clkreboot", 9) == 0) { // Reset clock getRTCClock()->setCurrentTime(1715770351); // 15 May 2024, 8:50pm