Hi,
I'm using SDK v17.0.2 on my nRF52840-based board. I have implemented buttonless secure OTA reflash and it generally works. When I get the NRF_PWR_MGMT_EVT_PREPARE_DFU event in app_shutdown_handler() and then return true, the DFU process works great. However, I would like to ensure that my device either has enough battery power or is powered by USB before starting a DFU. When I added code to check for this, I found that I could not continue the DFU process by connecting USB power to my device after initiating the DFU process. I then simplified the code to add a counter to app_shutdown_handler() to just delay before starting the DFU process rather than checking power constraints. This also did not work. It appears the DFU process works fine if I return true the first time through app_shutdown_handler(), but does not work if I return false the first time, and then return true when app_shutdown_handler() executes 1 second later. Here is the code I am using to test this -
static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
{
// uint8_t battery_level = 0;
// bool usb_connected = false;
bool ok_to_reflash = false;
static int count = 0;
switch (event)
{
case NRF_PWR_MGMT_EVT_PREPARE_DFU:
// Ensure we are connected to USB or have enough
// battery before starting DFU.
// // Get USB connection status
// usb_connected = system_usb_connected();
// // Get the current battery level
// battery_level = system_battery_level_get();
// if ((battery_level > 80) || (usb_connected) || (++count > 10))
if (++count > 10)
{
ok_to_reflash = true;
}
// NRF_LOG_INFO("DFU request, battery level: %i%%, USB %sconnected", battery_level, usb_connected ? "" : "not ");
NRF_LOG_INFO("DFU request, count: %i", count);
break;
default:
return true;
}
if (ok_to_reflash)
{
NRF_LOG_INFO("Power management allowed to reset to DFU mode.");
enter_dfu();
}
return ok_to_reflash;
}
/**@brief Set register to start DFU on power-up and reset.
*
*/
static void enter_dfu(void)
{
uint32_t old;
(void)sd_power_gpregret_get(0, &old);
(void)sd_power_gpregret_set(0, old | BOOTLOADER_DFU_START);
NVIC_SystemReset();
}
The stack trace when the DFU fails is this -

The stack trace when the DFU works (when app_shutdown_handler() returns true the first time through it) is this -

Am I missing something on how I've implemented this?
Thanks...
Brian