NRF52840 doesn't enter the secure DFU mode by setting sd_power_gpregret_set(0, 0xB1);

Greetings,

I'm using NRF52840 with softdevice and nRF5_SDK_17.1.0 on NRF52 DK.

The shutdown_handler in my code is as follows:

bool shutdown_handler(nrf_pwr_mgmt_evt_t event)
{
    uint32_t err_code;
    
    NRF_LOG_INFO("Entered power manager handler.");

    switch (event)
    {
        case NRF_PWR_MGMT_EVT_PREPARE_SYSOFF:
            NRF_LOG_INFO("NRF_PWR_MGMT_EVT_PREPARE_SYSOFF");
            err_code = bsp_buttons_disable();
            APP_ERROR_CHECK(err_code);
            break;

        case NRF_PWR_MGMT_EVT_PREPARE_WAKEUP:
            NRF_LOG_INFO("NRF_PWR_MGMT_EVT_PREPARE_WAKEUP");
            err_code = bsp_buttons_disable();
            // Suppress NRF_ERROR_NOT_SUPPORTED return code.
            UNUSED_VARIABLE(err_code);

            err_code = bsp_wakeup_button_enable(BTN0);
            // Suppress NRF_ERROR_NOT_SUPPORTED return code.
            UNUSED_VARIABLE(err_code);

            break;

        case NRF_PWR_MGMT_EVT_PREPARE_DFU:
            err_code = sd_power_gpregret_clr(0, 0xffffffff);
            VERIFY_SUCCESS(err_code);

            err_code = sd_power_gpregret_set(0, 0xB1);
            VERIFY_SUCCESS(err_code);

            break;

        case NRF_PWR_MGMT_EVT_PREPARE_RESET:
            NRF_LOG_INFO("NRF_PWR_MGMT_EVT_PREPARE_RESET");
            break;
    }

    NRF_LOG_FLUSH();
    bsp_board_leds_off();

    err_code = app_timer_stop_all();
    APP_ERROR_CHECK(err_code);

    return true;
}


/**@brief Register application shutdown handler with priority 0. */
NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, 0);

There is a secure bootloader from Nordic examples on my NRF52840 with the following configs set:

#define NRF_BL_DFU_ENTER_METHOD_PINRESET 1

#define NRF_BL_DFU_ENTER_METHOD_GPREGRET 1

But when I run the following command in my code, it just resets the device and does not enter the DFU mode. The only way to enter DFU is using the reset pin.

nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);

What is the problem and how can I resolve that?

Thanks in advance.

Parents
  • Hi Hamed, 
    It looks OK to me on what you did. 
    Could you double check before the reset the application actually managed to write to GPREGRET register ? 
    Please also check the bootloader in dfu_enter_check() function in nrf_bootload.c if nrf_power_gpregret_get() return the correct value ? You may want to test using the _debug version of the bootloader. By using the debug version you can set breakpoint and step into the code of the bootload the same way as debugging application.

  • Hi Hung.

    Thanks for your reply.

    I've tested my code in various situations.

    If I use

    nrf_power_gpregret_set(0xB1);

    instead of

    err_code = sd_power_gpregret_clr(0, 0xffffffff);
    VERIFY_SUCCESS(err_code);
    
    err_code = sd_power_gpregret_set(0, 0xB1);
    VERIFY_SUCCESS(err_code);

    then in release build, my code shows a fatal error but restarts into the DFU mode successfully.

    However, in debug build my code returns "SOFTDEVICE: INVALID MEMORY ACCESS" error and freezes.

    But by using

    err_code = sd_power_gpregret_clr(0, 0xffffffff);
    VERIFY_SUCCESS(err_code);
    
    err_code = sd_power_gpregret_set(0, 0xB1);
    VERIFY_SUCCESS(err_code);

    my code freezes in both release and debug builds.

    In debug build, sometimes it shows the following error:

    ERROR 2 [NRF_ERROR_SOFTDEVICE_NOT_ENABLED] at Z:\...\main.c:446
    PC at: 0x0002E69B

    where line 446 of main.c refers to err_code = sd_power_gpregret_clr(0, 0xffffffff).

    While nrf_power_gpregret_set(0xB1) can do the job for me, I tried using that. But another problem arose:

    As soon as I enabled the watchdog timer in my app, after entering the DFU mode, the LED blinks once, and the device restarts automatically into the app.

    I've checked nrf_bootloader_wdt_feed() in the bootloader using logs, it seems to feed the WDT but DFU mode still restarts and I don't know why!

    So I have 2 questions:

    1. How can I use sd_power_gpregret_clr without getting errors?

    2. How can I resolve the DFU reset problem after enabling WDT?

    Thank you.

  • Hi, 

    If the softdevice is not enable (I assume it's the case ? ) then you should use nrf_power_gpregret_set(). sd_power_gpregret_set() should only be used when the softdevice is active. 

    Regarding the watchdog, could you try to increase the watchdog timeout to let says 10 seconds and check if it's restarted after the same time ?  Just to be sure if it's the watchdog causing the issue. 

    Please also double check if nrf_bootloader_wdt_feed() is called periodically in this period of time. 

Reply
  • Hi, 

    If the softdevice is not enable (I assume it's the case ? ) then you should use nrf_power_gpregret_set(). sd_power_gpregret_set() should only be used when the softdevice is active. 

    Regarding the watchdog, could you try to increase the watchdog timeout to let says 10 seconds and check if it's restarted after the same time ?  Just to be sure if it's the watchdog causing the issue. 

    Please also double check if nrf_bootloader_wdt_feed() is called periodically in this period of time. 

Children
  • Dear Hung,

    Thanks a lot for your assistance.

    I could finally find the problems.

    It seems that debug mode raises a lot of problems for our code.

    I don't know what was the problem with Softdevice and how it was resolved, but sd_softdevice_is_enabled returned 1 and after checking sd_power_gpregret commands, we found out that they are working without any problems.

    About the bootloader, we found this topic which describes the same situation we were experiencing.

    The suggested solution, changing

            if (!nrf_clock_lf_is_running())
            {
                nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
            }

    into

            nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);

    in \components\libraries\bootloader\nrf_bootloader_dfu_timers.c file resolved the problem.

Related