adafruit / Adafruit_nRF52_Bootloader

USB-enabled bootloaders for the nRF52 BLE SoC chips

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Optional feature: Skip DFU with Magic

nitz opened this issue · comments

Hiya!

I had something I added in my fork for my application, where I wanted my application to be able to skip the DFU mode (particularly the double reset wait) using a GPREGRET magic value. I've pasted the patch here if you want to look at it. It's a pretty simple thing, and I'm not sure if it's something you'd want as a feature in the mainline, but I figured I would offer it anyways! Close away if you're not interested, but just let me know if you want me to send a PR!

diff --git "a/src/main.c" "b/src/main.c"
index cf05c1a..6cd2b55 100644
--- "a/src/main.c"
+++ "b/src/main.c"
@@ -109,6 +109,7 @@ void usb_teardown(void);
 #define DFU_MAGIC_OTA_RESET             0xA8
 #define DFU_MAGIC_SERIAL_ONLY_RESET     0x4e
 #define DFU_MAGIC_UF2_RESET             0x57
+#define DFU_MAGIC_SKIP_DFU              0x6d
 
 #define DFU_DBL_RESET_MAGIC             0x5A1AD5      // SALADS
 #define DFU_DBL_RESET_APP               0x4ee5677e
@@ -175,6 +176,8 @@ int main(void)
   bool dfu_start = _ota_dfu || serial_only_dfu || (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET) ||
                     (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk));
 
+  bool skip_dfu = NRF_POWER->GPREGRET == DFU_MAGIC_SKIP_DFU;
+
   // Clear GPREGRET if it is our values
   if (dfu_start) NRF_POWER->GPREGRET = 0;
 
@@ -198,76 +201,79 @@ int main(void)
     led_state(STATE_WRITING_FINISHED);
   }
 
-  /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/
-  // DFU button pressed
-  dfu_start  = dfu_start || button_pressed(BUTTON_DFU);
+  if (skip_dfu == false)
+  {
+    /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/
+    // DFU button pressed
+    dfu_start  = dfu_start || button_pressed(BUTTON_DFU);
 
-  // DFU + FRESET are pressed --> OTA
-  _ota_dfu = _ota_dfu  || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
+    // DFU + FRESET are pressed --> OTA
+    _ota_dfu = _ota_dfu  || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
 
-  bool const valid_app = bootloader_app_is_valid();
-  bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
+    bool const valid_app = bootloader_app_is_valid();
+    bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
 
-  if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET())
-    dfu_start = 1;
+    if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET())
+      dfu_start = 1;
 
-  // App mode: register 1st reset and DFU startup (nrf52832)
-  if ( ! (just_start_app || dfu_start || !valid_app) )
-  {
-    // Register our first reset for double reset detection
-    (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
+    // App mode: register 1st reset and DFU startup (nrf52832)
+    if ( ! (just_start_app || dfu_start || !valid_app) )
+    {
+      // Register our first reset for double reset detection
+      (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
 
 #ifdef NRF52832_XXAA
-    /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
-     * to support auto programming from Arduino IDE
-     *
-     * Note: Supposedly during this time if RST is press, it will count as double reset.
-     * However Double Reset WONT work with nrf52832 since its SRAM got cleared anyway.
-     */
-    bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false);
+      /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
+       * to support auto programming from Arduino IDE
+       *
+       * Note: Supposedly during this time if RST is press, it will count as double reset.
+       * However Double Reset WONT work with nrf52832 since its SRAM got cleared anyway.
+       */
+      bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false);
 #else
-    // if RST is pressed during this delay --> if will enter dfu
-    NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
+      // if RST is pressed during this delay --> if will enter dfu
+      NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
 #endif
-  }
-
-  if (APP_ASKS_FOR_SINGLE_TAP_RESET())
-    (*dbl_reset_mem) = DFU_DBL_RESET_APP;
-  else
-    (*dbl_reset_mem) = 0;
-
-  if ( dfu_start || !valid_app )
-  {
-    if ( _ota_dfu )
-    {
-      led_state(STATE_BLE_DISCONNECTED);
-      softdev_init(!sd_inited);
-      sd_inited = true;
-    }
-    else
-    {
-      led_state(STATE_USB_UNMOUNTED);
-      usb_init(serial_only_dfu);
     }
 
-    // Initiate an update of the firmware.
     if (APP_ASKS_FOR_SINGLE_TAP_RESET())
-    {
-      // If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app.
-      APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 3000, true) );
-    }
+      (*dbl_reset_mem) = DFU_DBL_RESET_APP;
     else
-    {
-      // No timeout if bootloader requires user action (double-reset).
-      APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 0, false) );
-    }
+      (*dbl_reset_mem) = 0;
 
-    if ( _ota_dfu )
+    if ( dfu_start || !valid_app )
     {
-      sd_softdevice_disable();
-    }else
-    {
-      usb_teardown();
+      if ( _ota_dfu )
+      {
+        led_state(STATE_BLE_DISCONNECTED);
+        softdev_init(!sd_inited);
+        sd_inited = true;
+      }
+      else
+      {
+        led_state(STATE_USB_UNMOUNTED);
+        usb_init(serial_only_dfu);
+      }
+
+      // Initiate an update of the firmware.
+      if (APP_ASKS_FOR_SINGLE_TAP_RESET())
+      {
+        // If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app.
+        APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 3000, true) );
+      }
+      else
+      {
+        // No timeout if bootloader requires user action (double-reset).
+        APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 0, false) );
+      }
+
+      if ( _ota_dfu )
+      {
+        sd_softdevice_disable();
+      }else
+      {
+        usb_teardown();
+      }
     }
   }
 

hi @nitz, thanks for asking, but to be honest, I am not really interested in this feature. main.c with current multiple DFU mode is already more complicated than it should be. Also I am not sure if our normal targeted user (Arduino/Circpython) would benefit much from this. Thanks again for asking.