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

Application is not loading post DFU over serial

Hello,

I am able to get a successful confirmation that my application has been updated using the nordic secure bootloader over serial code example. However, my application doesn't load. Here are the steps I followed:

1) Created an app package using cmd: nrfutil pkg generate --hw-version 52 --sd-req 0x00 --application-version 1 --application app.hex --key-file private.pem app52_1.zip

2) Erased the device and downloaded the bootloader (code based on \examples\dfu\secure_bootloader\pca10040_uart projoct.

3) Generated and programmed the setting.hex file

4) Recycled power and uploaded my app using cmd: nrfutil dfu serial -pkg app52_1.zip -p COM14 -fc 0. I got a confirmation message that the DFU is 100% done.

5) Recycled power but my app didn't load properly and neither did the bootloader. I know that because I cannot upload an app using step 3 anymore nor the correct DFU GPIO pattern is outputted.
Any ideas how to troubleshoot this issue? I did see other tickets referring to the boatload button being the issue so I disable that feature in the sdk_config.h file and still not working. I also tried to manually reset using nrfjprg --reset and that didn't help either. Any ideas? Thanks!
  • Hello Eina,

    If using DFU but no SoftDevice, the application starts at 0x1000,

    I just wanted to point out that according to the nRF connect read image, my application does NOT start at location 0x1000. It show it starting at location 0x0FF8 instead. Is that okay?

    ould it be an issue in the application, that somehow is only triggered when you use a bootloader? How have you verified that the application does not load?

    When I program my application directly on an erased device (no bootloader), it works fine. I just did that again and read the image and attached it here for reference. The section in the top is my emulated eeprom user parameters. I also added my application code flash placement file for your reference.

    Can you try to toggle a GPIO a few times as the very first thing you do in the application, and see if you can detect that from a logic analyzer?

    I will do that next but I thought I send these info your way first in case it is useful.

    <!DOCTYPE Linker_Placement_File>
    <Root name="Flash Section Placement">
      <MemorySegment name="FLASH" start="$(FLASH_PH_START)" size="$(FLASH_PH_SIZE)">
        <ProgramSection load="no" name=".reserved_flash" start="$(FLASH_PH_START)" size="$(FLASH_START)-$(FLASH_PH_START)" />
        <ProgramSection alignment="0x100" load="Yes" name=".vectors" start="$(FLASH_START)" />
        <ProgramSection alignment="4" load="Yes" name=".init" />
        <ProgramSection alignment="4" load="Yes" name=".init_rodata" />
        <ProgramSection alignment="4" load="Yes" name=".text" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".log_const_data" inputsections="*(SORT(.log_const_data*))" address_symbol="__start_log_const_data" end_symbol="__stop_log_const_data" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".log_backends" inputsections="*(SORT(.log_backends*))" address_symbol="__start_log_backends" end_symbol="__stop_log_backends" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".nrf_balloc" inputsections="*(.nrf_balloc*)" address_symbol="__start_nrf_balloc" end_symbol="__stop_nrf_balloc" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".nrf_sections" address_symbol="__start_nrf_sections" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".fs_data"  inputsections="*(.fs_data*)" runin=".fs_data_run"/>
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".log_dynamic_data"  inputsections="*(SORT(.log_dynamic_data*))" runin=".log_dynamic_data_run"/>
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".log_filter_data"  inputsections="*(SORT(.log_filter_data*))" runin=".log_filter_data_run"/>
        <ProgramSection alignment="4" load="Yes" name=".dtors" />
        <ProgramSection alignment="4" load="Yes" name=".ctors" />
        <ProgramSection alignment="4" load="Yes" name=".rodata" />
        <ProgramSection alignment="4" load="Yes" name=".ARM.exidx" address_symbol="__exidx_start" end_symbol="__exidx_end" />
        <ProgramSection alignment="4" load="Yes" runin=".fast_run" name=".fast" />
        <ProgramSection alignment="4" load="Yes" runin=".data_run" name=".data" />
        <ProgramSection alignment="4" load="Yes" runin=".tdata_run" name=".tdata" />
      </MemorySegment>
      <MemorySegment name="RAM" start="$(RAM_PH_START)" size="$(RAM_PH_SIZE)">
        <ProgramSection load="no" name=".reserved_ram" start="$(RAM_PH_START)" size="$(RAM_START)-$(RAM_PH_START)" />
        <ProgramSection alignment="0x100" load="No" name=".vectors_ram" start="$(RAM_START)" address_symbol="__app_ram_start__"/>
        <ProgramSection alignment="4" keep="Yes" load="No" name=".nrf_sections_run" address_symbol="__start_nrf_sections_run" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".fs_data_run" address_symbol="__start_fs_data" end_symbol="__stop_fs_data" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".log_dynamic_data_run" address_symbol="__start_log_dynamic_data" end_symbol="__stop_log_dynamic_data" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".log_filter_data_run" address_symbol="__start_log_filter_data" end_symbol="__stop_log_filter_data" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".nrf_sections_run_end" address_symbol="__end_nrf_sections_run" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".emulated_eeprom" address_symbol="__emulated_eeprom_start" end_symbol="__emulated_eeprom_end" size_symbol="__emulated_eeprom_size"/>
        <ProgramSection alignment="4" keep="Yes" load="No" name=".emulated_eeprom_crc" address_symbol="__emulated_eeprom_crc_start" end_symbol="__emulated_eeprom_crc_end" size_symbol="__emulated_eeprom_crc_size"/>
        <ProgramSection alignment="4" load="No" name=".fast_run" />
        <ProgramSection alignment="4" load="No" name=".data_run" />
        <ProgramSection alignment="4" load="No" name=".tdata_run" />
        <ProgramSection alignment="4" load="No" name=".bss" />
        <ProgramSection alignment="4" load="No" name=".tbss" />
        <ProgramSection alignment="4" load="No" name=".non_init" />
        <ProgramSection alignment="4" size="__HEAPSIZE__" load="No" name=".heap" />
        <ProgramSection alignment="8" size="__STACKSIZE__" load="No" place_from_segment_end="Yes" name=".stack"  address_symbol="__StackLimit" end_symbol="__StackTop"/>
        <ProgramSection alignment="8" size="__STACKSIZE_PROCESS__" load="No" name=".stack_process" />
      </MemorySegment>
    </Root>
    

  • Hi, 

    moose said:
    I just wanted to point out that according to the nRF connect read image, my application does NOT start at location 0x1000. It show it starting at location 0x0FF8 instead. Is that okay?

    That is just an issue with nRF Connect Programmer. Since the last two words in the MBR page contain data (which was written either when you programmed the bootloader hex or the first reset after programming the bootloader depending on SDK version), the programmer app thinks the application starts there. But that is not the case. This is not an issue.

    I suspect there is something that causes an error in the application when the bootloader runs first, but it will be interesting to see what you find when trying to verify if the application runs or not.

  • Hello Einar,

    So I did the test you asked me to do. I added the following code right after my main in my application

    int main(void)
    {
        if(!nrfx_gpiote_is_init())
          APP_ERROR_CHECK(nrfx_gpiote_init());
       
        nrfx_gpiote_out_config_t out_config = NRFX_GPIOTE_CONFIG_OUT_SIMPLE(false);
        APP_ERROR_CHECK(nrfx_gpiote_out_init(LED1_PIN , &out_config));
    
        for(uint16_t i=0; i<1000; i++)
          nrfx_gpiote_out_set(LED1_PIN);
        for(uint16_t i=0; i<1000; i++)
          nrfx_gpiote_out_clear(LED1_PIN);
        for(uint16_t i=0; i<1000; i++)
          nrfx_gpiote_out_set(LED1_PIN);
        for(uint16_t i=0; i<1000; i++)
          nrfx_gpiote_out_clear(LED1_PIN);
        for(uint16_t i=0; i<1000; i++)
          nrfx_gpiote_out_set(LED1_PIN);
        for(uint16_t i=0; i<1000; i++)
          nrfx_gpiote_out_clear(LED1_PIN);
        for(uint16_t i=0; i<1000; i++)
          nrfx_gpiote_out_set(LED1_PIN);
        for(uint16_t i=0; i<1000; i++)
          nrfx_gpiote_out_clear(LED1_PIN);

    After programming my board and resetting it, I can capture the expected LED pulses on my scope and I can repeat it every time I reset the board.

    I used nrfutil and this new app hex file to generate a new zip package, segger studio to erase and downloaded the debug boatloader and nrfutil to upload the app zip package. Here are the nrfutil commands I used. I skipped the setting.hex since I am just downloading a fresh bootloader. 

    nrfutil pkg generate --hw-version 52 --sd-req 0x00 --application-version 1 --application apppulse.hex --key-file private.pem app52_1pulse.zip
    nrfutil dfu serial -pkg app52_1pulse.zip -p COM14 -fc 0

    I was able to get a successful upload but my app is still not loading and I did not detect any LED pulses on my scope. Resetting the board does not help. How would you recommend to proceed? Please keep in mind that my app use freeRTOS. Not sure if that is a factor. Below is the log file for your reference. I did a reset at the end.

    <info> nrf_dfu_serial_uart: Allocated buffer 20000AF4
    <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0000D480, src=0x20000B7C, len=64 bytes), queue usage: 1
    <info> nrf_dfu_serial_uart: Allocated buffer 20000AF4
    <debug> nrf_dfu_flash: Flash write success: addr=0x0000D480, pending 0
    <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_CRC_GET (data)
    <debug> nrf_dfu_req_handler: Offset:50368, CRC:0x932409F1
    <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    <debug> nrf_dfu_serial: Sending Response: [0x3, 0x1]
    <info> nrf_dfu_serial_uart: Allocated buffer 20000AF4
    <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_EXECUTE (data)
    <debug> nrf_dfu_req_handler: Whole firmware image received. Postvalidating.
    <debug> nrf_dfu_validation: Hash verification. start address: 0x1000, size: 0xC4C0
    <debug> nrf_dfu_validation: Invalidating old application in bank 0.
    <debug> nrf_dfu_serial: Sending Response: [0x4, 0x1]
    <debug> nrf_dfu_settings: Writing settings...
    <debug> nrf_dfu_settings: Erasing old settings at: 0x0007F000
    <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x0007F000, len=1 pages), queue usage: 1
    <debug> nrf_dfu_flash: Flash erase success: addr=0x0007F000, pending 0
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0007F000, src=0x20000CE0, len=896 bytes), queue usage: 1
    <debug> nrf_dfu_flash: Flash write success: addr=0x0007F000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    <debug> nrf_dfu_settings: Writing settings...
    <debug> nrf_dfu_settings: Erasing old settings at: 0x0007E000
    <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x0007E000, len=1 pages), queue usage: 1
    <debug> nrf_dfu_flash: Flash erase success: addr=0x0007E000, pending 0
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0007E000, src=0x20001060, len=896 bytes), queue usage: 1
    <debug> nrf_dfu_flash: Flash write success: addr=0x0007E000, pending 0
    <debug> nrf_dfu_req_handler: All flash operations have completed. DFU completed.
    <debug> app: Shutting down transports (found: 1)
    <debug> app: Resetting bootloader.
    <info> app: Inside main
    <debug> app: In nrf_bootloader_init
    <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    <debug> nrf_dfu_settings: Using settings page.
    <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <debug> app: Enter nrf_bootloader_fw_activate
    <debug> app: Valid App
    <debug> app: Enter nrf_dfu_app_continue
    <debug> app: No copy needed
    <debug> app: Setting app as valid
    <debug> nrf_dfu_settings: Writing settings...
    <debug> nrf_dfu_settings: Erasing old settings at: 0x0007F000
    <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x0007F000, len=1 pages), queue usage: 0
    <debug> nrf_dfu_flash: Flash erase success: addr=0x0007F000, pending 0
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0007F000, src=0x20000CE0, len=896 bytes), queue usage: 1
    <debug> nrf_dfu_flash: Flash write success: addr=0x0007F000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    <debug> nrf_dfu_settings: Writing settings...
    <debug> nrf_dfu_settings: Erasing old settings at: 0x0007E000
    <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x0007E000, len=1 pages), queue usage: 1
    <debug> nrf_dfu_flash: Flash erase success: addr=0x0007E000, pending 0
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0007E000, src=0x20001060, len=896 bytes), queue usage: 1
    <debug> nrf_dfu_flash: Flash write success: addr=0x0007E000, pending 0
    <debug> app: Resetting bootloader.
    <info> nrf_dfu_settings: Backing up settings page to address 0x7<info> app: Inside main
    <debug> app: In nrf_bootloader_init
    <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    <debug> nrf_dfu_settings: Using settings page.
    <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <debug> app: Enter nrf_bootloader_fw_activate
    <info> app: No firmware to activate.
    <debug> app: App is valid
    <warning> nrf_dfu_settings: No additional data erased
    <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <debug> app: Running nrf_bootloader_app_start with address: 0x00001000
    <debug> app: Disabling interrupts. NVIC->ICER[0]: 0x0
    <info> app: Inside main
    <debug> app: In nrf_bootloader_init
    <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    <debug> nrf_dfu_settings: Using settings page.
    <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    E000.
    001000
    <info> app: Inside main
    <debug> app: In nrf_bootloader_init
    <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    <debug> nrf_dfu_settings: Using settings page.
    <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    <debug> nrf_dfu_settings: Destination settings are identical to E000.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <debug> app: Running nrf_bootloader_app_start with address: 0x00001000
    <debug> app: Disabling interrupts. NVIC->ICER[0]: 0x0
    

  • Hi,

    This is my current understanding of the situation:

    • According to the bootloader log, the application is started and everything looks OK.
    • The applications normally toggle a GPIO at the beginning of the main, which works without a bootloader. When using a bootloader, the GPIO is not toggled indicating that the application is not started or at least not running at this point.
    • Anything happening later in your application is irrelevant (at this point) since the GPIO toggling happens first. (So the FreeRTOS scheduler is not started yet, and thus this can be disregarded for).

    I find this a bit strange and would like to try to debug this on my side. Is it possible to run your code on a DK? If so, can you upload your complete project (both application and bootloader) together with instructions on how to perform the test so that I can do it on my side? You can upload it in a private case if you don't want it to be public. In so, please refer to this case so that the new case is assigned to me.

  • So I finally was able to solve the problem. In short the documentation for the serial DFU bootlader with no softdevice is really missing few key steps. I would highly suggest they get updated.

    Basically beside the application hex and the booloader hex you also need the mbr hex. This code that actually reside at memory address 0x0. It is already included in the softdevice but if you are not using a softdevice then you need to do few additional steps:

    1) Add mbr_nrf52_2.4.1_mbr.hex. In segger you could do so under project options, debug, loader, additional load files. The relative path is ../../../../../../components/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.hex

    2) Add MBR_PRESENT to the preprocessor defines. In segger you could do so under project options, code, preprocessor, preprocessor definitions.

    3) Include mbr and cmsis headers if they are not already included. In segger you could do so under project options, code, preprocessor, user include directories. The relatives file are 

    ../../../../../../components/softdevice/mbr/headers

    ../../../../../../components/toolchain/cmsis/include

    4) Change the flash start address to 0x1000 and update the size (substract 0x1000). In segger you could do so under project options, code, linker, section placement macros. 

    5) Change the RAM start address to 0x20000010 and update the size (substract 0x10). In segger you could do so under project options, code, linker, section placement macros. 

    This worked for me. You could do the same changes plenty other ways but this is how I did it. Good luck!

Related