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

Update SD+BL+APP from SDK v13 to v14 via DFU Fails

Hi. I am trying to create a dfu zip file that contains the softdevice, bootloader, and application. I am DFU upgrading an NRF52 device from SDK v13 to SDK v14 via Nordic's Android nRF Toolbox DFU app. I can create a zip file that contains the softdevice and bootloader and another zip file that contains the app. When I program the device with the softdevice+bootloader zip file, it updates successfully. However, the device exits DFU mode and I can no longer update the application. I can no longer wirelessly put the device into DFU mode. Also, updating the app first does not work. Again, the device is nonresponsive. The DFU app does not allow me to choose both zip files. Please advise on how to perform a two step DFU.

  • You should be able to create a single SD+BL+ APP firmware image using nrfutil, i.e.

    nrfutil --application app.hex --application-version 1 --bootloader bootloader.hex --bootloader-version 1 --softdevice softdevice.hex --hw-version 52 --sd-req 0x9D,0x98 --sd-id 0x9D --key-file private_key.pem sd_bl_app_firmware_image.zip
    
  • Hi Bjorn. thank you for your reply. Success. Looks like is was missing "--sd-id 0x9d". Now, when the DFU app is used, it shows uploading part 1/2. After uploading part 1, the device disconnects and the app reports a failure. Using nRFgo Studio, the bootloader and softdevice are upgraded successfully. However, the application code does not upgrade. As an experiment, I programmed the board with SDKv14's softdevice and bootloader and used the same zip file to perform a DFU. DFU was successful. I suspect the issue is that SDKv13 used softdevice version 4.0.2 and SDKv14 uses softdevice version 5.0.0. Please advise.

  • We've found an issue with the Secure Bootloader's bootloader copy routine ( nrf_dfu_bl_continue() in nrf_dfu_utils.c ) - the logic in this routine breaks when doing a combined softdevice and bootloader update and the new softdevice is of a different size compared to previous version.

    After the old bootloader has been swapped with the new bootloader, the new bootloader will compare itself against the banked version to verify that the MBR performed the swap correctly. The start address of BANK1, where the bootloader image is stored, is equal to the end of the SoftDevice. However, due to the change in SoftDevice size, from 0x1F000 with S132 v4.0.2 to 0x23000 with the S132 v5.0.0, the new bootloader will use 0x23000 as the start address instead of the old at 0x1F000. This leads to the memory compare operation being performed with a 0x4000 offset, which will fail.

    The workaround is to modify the nrf_dfu_bl_continue() in the SDK v14.0.0 bootloader to check both the new and the old Bank1 start addresses, i.e.

    static uint32_t nrf_dfu_bl_continue(uint32_t src_addr, nrf_dfu_bank_t * p_bank)
    {
        uint32_t       err_code      = NRF_SUCCESS;
        uint32_t       ret_val      = NRF_SUCCESS;
        uint32_t const len          = (p_bank->image_size - s_dfu_settings.sd_size);
        uint32_t       old_src_addr;
        
        // if the update is a combination of BL + SD, offset with SD size to get BL start address
        src_addr += s_dfu_settings.sd_size;
        // Offset by 16K due to change in softdevice size. 0x1F000 -> 0x23000
        old_src_addr = src_addr - 0x4000;
        
        NRF_LOG_DEBUG("Verifying BL: Addr: 0x%08x, Src: 0x%08x, Len: 0x%08x", MAIN_APPLICATION_START_ADDR, src_addr, len);
        
        //Check new and old bank1 address to prevent new bootloader from repeating the swap with wrong src_addr
        err_code = nrf_dfu_mbr_compare((uint32_t*)BOOTLOADER_START_ADDR, (uint32_t*)old_src_addr, len);
            
        // If the bootloader is the same as the banked version, the copy is finished
        ret_val = nrf_dfu_mbr_compare((uint32_t*)BOOTLOADER_START_ADDR, (uint32_t*)src_addr, len);
        if (ret_val == NRF_SUCCESS || err_code == NRF_SUCCESS)
        {
            NRF_LOG_DEBUG("Bootloader was verified");
    
            // Invalidate bank, marking completion
            nrf_dfu_invalidate_bank(p_bank);
    
            // Upon successful completion, the callback function will be called and reset the device. If a valid app is present, it will launch.
            NRF_LOG_DEBUG("Writing settings and reseting device.");
            ret_val = nrf_dfu_settings_write(reset_device_callback);
        }
        else
        {
            NRF_LOG_DEBUG("Bootloader not verified, copying: Src: 0x%08x, Len: 0x%08x", src_addr, len);
            // Bootloader is different than the banked version. Continue copy
            // Note that if the SD and BL was combined, then the split point between them is in s_dfu_settings.sd_size
            ret_val = nrf_dfu_mbr_copy_bl((uint32_t*)src_addr, len);
            if (ret_val != NRF_SUCCESS)
            {
                NRF_LOG_ERROR("Request to copy BL failed");
            }
        }
    
        return ret_val;
    }
    
  • Hi Bjorn

    As far as I see this is not a generic solution, isn't it? The offset of 0x4000 is correct at the moment for the updated from S132 4.0.4 to S132 5.0.0, but it could be wrong in some other cases. Is there a bugfix to fix this issue in a general way?

  • @adrian: Yes, this solution is not generic and will only be valid for a DFU update from S132 v3.x.x. or S132 v4.x.x to S132 v5.0.0. A generic fix that will work for all SoftDevices will be included in the next SDK release.

Related