Can't DFU if app_shutdown_handler() initially returns false

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

Parents Reply Children
No Data
Related