This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Changes to the application for DFU

I am using SDK17, nRF52840 based custom board and SoftDevice 7.2.0 with SES.

I want to use SDK's secure bootloader (pca10056_s140_ble) with my own keys.

To enter to the bootloader I need to perform these functions and I have added them to my code.

err_code = sd_power_gpregret_clr(0, 0xffffffff);
APP_ERROR_CHECK(err_code);

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

nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);

On bootup, the device shows up as DfuTarg, I can connect to it, upload the ZIP and the device runs perfectly. But to perform another OTA, when I connect to my own service and perform the above-given code portion, the device hangs. It does not enter DFU(I verified it by toggling an LED at the start of the bootloader ).

What else do I need to change in my application? As far as I know, I can not debug my application as there is a bootloader.

Parents
  • Hello,

    Are you sure the gpregret register is actually set after the reset?  Try adding a check before you shut down, because these writes may take some time. Even after returning, it may not be complete.

    err_code = sd_power_gpregret_clr(0, 0xffffffff);
    APP_ERROR_CHECK(err_code);
    
    err_code = sd_power_gpregret_set(0, 0xB1);
    APP_ERROR_CHECK(err_code);
    
    uint32_t gpregret_read_value = 0x00000000;
    while (gpregret_read_value != 0xB1)
    {
        err_code = sd_power_gpregret_get(0, &gpregret_read_value);
    }
    
    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);

    After trying this, then test out the _debug bootloader project (pca10056_s140_ble_debug), and monitor the RTT log. What does the log say in dfu_enter_check():

    static bool dfu_enter_check(void)
    {
        if (!app_is_valid(crc_on_valid_app_required()))
        {
            NRF_LOG_DEBUG("DFU mode because app is not valid.");
            return true;
        }
    
        if (NRF_BL_DFU_ENTER_METHOD_BUTTON &&
           (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0))
        {
            NRF_LOG_DEBUG("DFU mode requested via button.");
            return true;
        }
    
        if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
           (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk))
        {
            NRF_LOG_DEBUG("DFU mode requested via pin-reset.");
            return true;
        }
    
        if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
           (nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
        {
            NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
            return true;
        }
    
        if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
           (s_dfu_settings.enter_buttonless_dfu == 1))
        {
            NRF_LOG_DEBUG("DFU mode requested via bootloader settings.");
            return true;
        }
    
        return false;
    }

    You can also set a breakpoint in:

        if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
           (nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
        {
            NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
            return true;
        }

    And check what the gpregret is set to.

    BR,

    Edvin

Reply
  • Hello,

    Are you sure the gpregret register is actually set after the reset?  Try adding a check before you shut down, because these writes may take some time. Even after returning, it may not be complete.

    err_code = sd_power_gpregret_clr(0, 0xffffffff);
    APP_ERROR_CHECK(err_code);
    
    err_code = sd_power_gpregret_set(0, 0xB1);
    APP_ERROR_CHECK(err_code);
    
    uint32_t gpregret_read_value = 0x00000000;
    while (gpregret_read_value != 0xB1)
    {
        err_code = sd_power_gpregret_get(0, &gpregret_read_value);
    }
    
    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);

    After trying this, then test out the _debug bootloader project (pca10056_s140_ble_debug), and monitor the RTT log. What does the log say in dfu_enter_check():

    static bool dfu_enter_check(void)
    {
        if (!app_is_valid(crc_on_valid_app_required()))
        {
            NRF_LOG_DEBUG("DFU mode because app is not valid.");
            return true;
        }
    
        if (NRF_BL_DFU_ENTER_METHOD_BUTTON &&
           (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0))
        {
            NRF_LOG_DEBUG("DFU mode requested via button.");
            return true;
        }
    
        if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
           (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk))
        {
            NRF_LOG_DEBUG("DFU mode requested via pin-reset.");
            return true;
        }
    
        if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
           (nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
        {
            NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
            return true;
        }
    
        if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
           (s_dfu_settings.enter_buttonless_dfu == 1))
        {
            NRF_LOG_DEBUG("DFU mode requested via bootloader settings.");
            return true;
        }
    
        return false;
    }

    You can also set a breakpoint in:

        if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
           (nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
        {
            NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
            return true;
        }

    And check what the gpregret is set to.

    BR,

    Edvin

Children
Related