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

DFU: nRF51822 OTA bootloader jams after reset_prepare()

I managed to upload my application OTA DFU when there was only the bootloader running. After my application is there, I can start DFU and my application runs thru reset_prepare() function as expected. However, it seems that it never enters the bootloader although DfuTarg seems to appear as an available BLE device. So I cannot upload my application another time :(

Any ideas what could be wrong? Why my application does not start bootloader (correctly) after reset_prepare()?

EDIT: The bootloader enters event loop and jams there, see the code below (from bootloader.c/nRF51_SDK_8.0.0_5fc2c3a). The DFU loader at phone side says "disconnected" (mostly, sometimes it jams). I cannot reconnect although DfuTarg is visible.

for (;;)
{
    // Wait in low power state for any events.
    uint32_t err_code = sd_app_evt_wait();
    APP_ERROR_CHECK(err_code);

	myLedIndication(); // This shows me bootloader is running here very busy

    // Event received. Process it from the scheduler.
    app_sched_execute();

    if ((m_update_status == BOOTLOADER_COMPLETE) ||
        (m_update_status == BOOTLOADER_TIMEOUT)  ||
        (m_update_status == BOOTLOADER_RESET))
    {
        // When update has completed or a timeout/reset occured we will return.
        return;
    }
}

And the reset_prepare() looks like:

static void reset_prepare(void)
{
	uint32_t err_code;
	if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
	{
		// Disconnect from peer.
		err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
		APP_ERROR_CHECK(err_code);
		//err_code = bsp_indication_set(BSP_INDICATE_IDLE);
		//APP_ERROR_CHECK(err_code);
	}
	else
	{
		// If not connected, the device will be advertising. Hence stop the advertising.
		advertising_stop();
	}
	err_code = ble_conn_params_stop();
	APP_ERROR_CHECK(err_code);
}
Parents
  • I am now using a dirty hack to get rid of bootloader jamming. The modification is at the bootloader's main.c, and it makes the bootloader to reset after it first enters from application, and only after that, it enters the actual bootloader code. However, two upload tries is now needed from nRFTools, so the solution is not optimal.

    bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START);
    bool app_reset2 = (NRF_POWER->GPREGRET == ~BOOTLOADER_DFU_START);
    
    if (app_reset)
    {
        NRF_POWER->GPREGRET = ~BOOTLOADER_DFU_START;
        NVIC_SystemReset();
    }
    else if (app_reset2)
    {
        NRF_POWER->GPREGRET = 0;
    }
    

    In addition, few other changes are needed to support "app_reset2" (several places at main). At least it works now somehow. But it is really a dirty hack as I said...

Reply
  • I am now using a dirty hack to get rid of bootloader jamming. The modification is at the bootloader's main.c, and it makes the bootloader to reset after it first enters from application, and only after that, it enters the actual bootloader code. However, two upload tries is now needed from nRFTools, so the solution is not optimal.

    bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START);
    bool app_reset2 = (NRF_POWER->GPREGRET == ~BOOTLOADER_DFU_START);
    
    if (app_reset)
    {
        NRF_POWER->GPREGRET = ~BOOTLOADER_DFU_START;
        NVIC_SystemReset();
    }
    else if (app_reset2)
    {
        NRF_POWER->GPREGRET = 0;
    }
    

    In addition, few other changes are needed to support "app_reset2" (several places at main). At least it works now somehow. But it is really a dirty hack as I said...

Children
  • The assembly routine in bootloader_util_app_start() does jump from application to bootloader, but it doesn't do a system reset like NVIC_SystemReset, power on reset or a pin reset resulting in the softdevice already being invoked going from application to bootloader. This is the reason for the "app reset" check in ble_stack_init() as SD_MBR_COMMAND_INIT_SD can't be issued when SD is already invoked. In other words, only issue the SD_MBR_COMMAND_INIT_SD command if a system reset has been performed.

    Reason for not doing a system reset in the example is to support sharing of bond information between the application and bootlaoder to keep the same encrypted link while doing DFU (bond sharing). If this feature is not needed you can call NVIC_SystemReset(); in your application and always invoke the Softdevice in ble_stack_init().

  • Thanks, that clarified a bit!

    What I really need is to be able to upload application.zip from nRFTools. If I do the reset, then it doesn't work very well, because user needs to start the upload twice... And if I don't, the bootloader jams into its event loop. :(

Related