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.