Merged bootloader+settings+SD+app not working

Hello,

Issue: after successfully compiling, generating bootloader settings, merging and flashing bootloader+settings+sd+app, the device enters DFU mode while i was expecting to run the app.

I'm developing a solution based on a nRF52832 with a custom board, softdevice S112 version 7.0.2, with SDK 17.0.2.

I have successfully built the micro_eec library, and bootloader from $(SDK)/examples/dfu/secure_bootloader/pca10040e_s112_ble.

My app is tested working when flashing with no bootloader (erase device, flash the softdevice and app). My app also uses two flash pages to store data, as per this definition:

NRF_FSTORAGE_DEF(nrf_fstorage_t my_flash) =
{
.evt_handler = flash_callback,
.start_addr = 0x7E000,
.end_addr = 0x7FFFF,
};

Bootloader setting is generated successfully with the following line:

nrfutil settings generate --family NRF52 --application $(OUTPUT_DIRECTORY)/nrf52810_xxaa.hex --application-version 0 --bootloader-version 0 --bl-settings-version 2 $(OUTPUT_DIRECTORY)/bootloader_setting.hex

Here is the output:

Bootloader DFU Settings:
* File:                     _build/bootloader_setting.hex
* Family:                   nRF52
* Start Address:            0x0007F000
* CRC:                      0x3879A3DC
* Settings Version:         0x00000002 (2)
* App Version:              0x00000000 (0)
* Bootloader Version:       0x00000000 (0)
* Bank Layout:              0x00000000
* Current Bank:             0x00000000
* Application Size:         0x0000D8A4 (55460 bytes)
* Application CRC:          0x74ED94AE
* Bank0 Bank Code:          0x00000001
* Softdevice Size:          0x00000000 (0 bytes)
* Boot Validation CRC:      0xFEBF7781
* SD Boot Validation Type:  0x00000000 (0)
* App Boot Validation Type: 0x00000001 (1)

Bootloader project linker config file:

/* Linker script to configure memory regions. */

SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)

MEMORY
{
  FLASH (rx) : ORIGIN = 0x28000, LENGTH = 0x6000
  RAM (rwx) :  ORIGIN = 0x200022c8, LENGTH = 0x3d38
  uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4
  uicr_mbr_params_page (r) : ORIGIN = 0x10001018, LENGTH = 0x4
  mbr_params_page (r) : ORIGIN = 0x0002E000, LENGTH = 0x1000
  bootloader_settings_page (r) : ORIGIN = 0x0002F000, LENGTH = 0x1000
}

SECTIONS
{
  . = ALIGN(4);
  .uicr_bootloader_start_address :
  {
    PROVIDE(__start_uicr_bootloader_start_address = .);
    KEEP(*(SORT(.uicr_bootloader_start_address*)))
    PROVIDE(__stop_uicr_bootloader_start_address = .);
  } > uicr_bootloader_start_address
  . = ALIGN(4);
  .uicr_mbr_params_page :
  {
    PROVIDE(__start_uicr_mbr_params_page = .);
    KEEP(*(SORT(.uicr_mbr_params_page*)))
    PROVIDE(__stop_uicr_mbr_params_page = .);
  } > uicr_mbr_params_page
  . = ALIGN(4);
  .mbr_params_page(NOLOAD) :
  {
    PROVIDE(__start_mbr_params_page = .);
    KEEP(*(SORT(.mbr_params_page*)))
    PROVIDE(__stop_mbr_params_page = .);
  } > mbr_params_page
  . = ALIGN(4);
  .bootloader_settings_page(NOLOAD) :
  {
    PROVIDE(__start_bootloader_settings_page = .);
    KEEP(*(SORT(.bootloader_settings_page*)))
    PROVIDE(__stop_bootloader_settings_page = .);
  } > bootloader_settings_page
}

SECTIONS
{
  . = ALIGN(4);
  .mem_section_dummy_ram :
  {
  }
  .log_dynamic_data :
  {
    PROVIDE(__start_log_dynamic_data = .);
    KEEP(*(SORT(.log_dynamic_data*)))
    PROVIDE(__stop_log_dynamic_data = .);
  } > RAM
  .log_filter_data :
  {
    PROVIDE(__start_log_filter_data = .);
    KEEP(*(SORT(.log_filter_data*)))
    PROVIDE(__stop_log_filter_data = .);
  } > RAM
  .fs_data :
  {
    PROVIDE(__start_fs_data = .);
    KEEP(*(.fs_data))
    PROVIDE(__stop_fs_data = .);
  } > RAM

} INSERT AFTER .data;

SECTIONS
{
  .mem_section_dummy_rom :
  {
  }
  .crypto_data :
  {
    PROVIDE(__start_crypto_data = .);
    KEEP(*(SORT(.crypto_data*)))
    PROVIDE(__stop_crypto_data = .);
  } > FLASH
  .log_const_data :
  {
    PROVIDE(__start_log_const_data = .);
    KEEP(*(SORT(.log_const_data*)))
    PROVIDE(__stop_log_const_data = .);
  } > FLASH
    .nrf_queue :
  {
    PROVIDE(__start_nrf_queue = .);
    KEEP(*(.nrf_queue))
    PROVIDE(__stop_nrf_queue = .);
  } > FLASH
  .dfu_trans :
  {
    PROVIDE(__start_dfu_trans = .);
    KEEP(*(SORT(.dfu_trans*)))
    PROVIDE(__stop_dfu_trans = .);
  } > FLASH
    .nrf_balloc :
  {
    PROVIDE(__start_nrf_balloc = .);
    KEEP(*(.nrf_balloc))
    PROVIDE(__stop_nrf_balloc = .);
  } > FLASH
    .svc_data :
  {
    PROVIDE(__start_svc_data = .);
    KEEP(*(.svc_data))
    PROVIDE(__stop_svc_data = .);
  } > FLASH
  .sdh_ble_observers :
  {
    PROVIDE(__start_sdh_ble_observers = .);
    KEEP(*(SORT(.sdh_ble_observers*)))
    PROVIDE(__stop_sdh_ble_observers = .);
  } > FLASH
  .sdh_req_observers :
  {
    PROVIDE(__start_sdh_req_observers = .);
    KEEP(*(SORT(.sdh_req_observers*)))
    PROVIDE(__stop_sdh_req_observers = .);
  } > FLASH
  .sdh_state_observers :
  {
    PROVIDE(__start_sdh_state_observers = .);
    KEEP(*(SORT(.sdh_state_observers*)))
    PROVIDE(__stop_sdh_state_observers = .);
  } > FLASH
  .sdh_stack_observers :
  {
    PROVIDE(__start_sdh_stack_observers = .);
    KEEP(*(SORT(.sdh_stack_observers*)))
    PROVIDE(__stop_sdh_stack_observers = .);
  } > FLASH
  .sdh_soc_observers :
  {
    PROVIDE(__start_sdh_soc_observers = .);
    KEEP(*(SORT(.sdh_soc_observers*)))
    PROVIDE(__stop_sdh_soc_observers = .);
  } > FLASH

} INSERT AFTER .text


INCLUDE "nrf_common.ld"

App project linker config file:

/* Linker script to configure memory regions. */

SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)

MEMORY
{
  FLASH (rx) : ORIGIN = 0x19000, LENGTH = 0x17000
  RAM (rwx) :  ORIGIN = 0x200022c8, LENGTH = 0x3d38
}

SECTIONS
{
}

SECTIONS
{
  . = ALIGN(4);
  .mem_section_dummy_ram :
  {
  }
  .cli_sorted_cmd_ptrs :
  {
    PROVIDE(__start_cli_sorted_cmd_ptrs = .);
    KEEP(*(.cli_sorted_cmd_ptrs))
    PROVIDE(__stop_cli_sorted_cmd_ptrs = .);
  } > RAM
  .fs_data :
  {
    PROVIDE(__start_fs_data = .);
    KEEP(*(.fs_data))
    PROVIDE(__stop_fs_data = .);
  } > RAM
  .log_dynamic_data :
  {
    PROVIDE(__start_log_dynamic_data = .);
    KEEP(*(SORT(.log_dynamic_data*)))
    PROVIDE(__stop_log_dynamic_data = .);
  } > RAM
  .log_filter_data :
  {
    PROVIDE(__start_log_filter_data = .);
    KEEP(*(SORT(.log_filter_data*)))
    PROVIDE(__stop_log_filter_data = .);
  } > RAM

} INSERT AFTER .data;

SECTIONS
{
  .mem_section_dummy_rom :
  {
  }
  .sdh_soc_observers :
  {
    PROVIDE(__start_sdh_soc_observers = .);
    KEEP(*(SORT(.sdh_soc_observers*)))
    PROVIDE(__stop_sdh_soc_observers = .);
  } > FLASH
  .sdh_ble_observers :
  {
    PROVIDE(__start_sdh_ble_observers = .);
    KEEP(*(SORT(.sdh_ble_observers*)))
    PROVIDE(__stop_sdh_ble_observers = .);
  } > FLASH
  .pwr_mgmt_data :
  {
    PROVIDE(__start_pwr_mgmt_data = .);
    KEEP(*(SORT(.pwr_mgmt_data*)))
    PROVIDE(__stop_pwr_mgmt_data = .);
  } > FLASH
  .sdh_req_observers :
  {
    PROVIDE(__start_sdh_req_observers = .);
    KEEP(*(SORT(.sdh_req_observers*)))
    PROVIDE(__stop_sdh_req_observers = .);
  } > FLASH
  .sdh_state_observers :
  {
    PROVIDE(__start_sdh_state_observers = .);
    KEEP(*(SORT(.sdh_state_observers*)))
    PROVIDE(__stop_sdh_state_observers = .);
  } > FLASH
  .sdh_stack_observers :
  {
    PROVIDE(__start_sdh_stack_observers = .);
    KEEP(*(SORT(.sdh_stack_observers*)))
    PROVIDE(__stop_sdh_stack_observers = .);
  } > FLASH
    .nrf_queue :
  {
    PROVIDE(__start_nrf_queue = .);
    KEEP(*(.nrf_queue))
    PROVIDE(__stop_nrf_queue = .);
  } > FLASH
    .nrf_balloc :
  {
    PROVIDE(__start_nrf_balloc = .);
    KEEP(*(.nrf_balloc))
    PROVIDE(__stop_nrf_balloc = .);
  } > FLASH
    .cli_command :
  {
    PROVIDE(__start_cli_command = .);
    KEEP(*(.cli_command))
    PROVIDE(__stop_cli_command = .);
  } > FLASH
  .crypto_data :
  {
    PROVIDE(__start_crypto_data = .);
    KEEP(*(SORT(.crypto_data*)))
    PROVIDE(__stop_crypto_data = .);
  } > FLASH
  .log_const_data :
  {
    PROVIDE(__start_log_const_data = .);
    KEEP(*(SORT(.log_const_data*)))
    PROVIDE(__stop_log_const_data = .);
  } > FLASH
  .log_backends :
  {
    PROVIDE(__start_log_backends = .);
    KEEP(*(SORT(.log_backends*)))
    PROVIDE(__stop_log_backends = .);
  } > FLASH

} INSERT AFTER .text


INCLUDE "nrf_common.ld"

i have no warnings when merging (ie, no overlap)

Thanks,

Martin

Parents
  • Hi Martin,

    Your choice of fstorage pages sticks out. Referring to the memory layout from the bootloader documentation you see that the bootloader settings page and MBR params page (latter is optional but needed for SoftDevice and bootloader updates) are fixed to the two last pages. So using the example bootloader, when you write other data to these pages from your application they will be corrupted. With a corrupt bootloader settings page, the bootloader will enter DFU mode instead of starting the application.

    I see that you have relocated the bootloader settings page and MBR params page in your bootloader linker file though, so at first glance the above is not the issue in your bootloader. However, there are also other parts of the code where the bootloader settings page address is defined. Specifically, the definition of BOOTLOADER_SETTINGS_ADDRESS and NRF_MBR_PARAMS_PAGE_ADDRESS in <nRF5 SDK 17.0.2>\components\libraries\bootloader\dfu\nrf_dfu_types.h. Have you adjusted that?

    (Generally, I would recommend placing your user data below the bootloader (and even below the FDS pages if you use that, as that is also hard coded to always be immediately below the bootloader) just because that is what is supported out of the box. Generally where you locate data should not matter, but changing as little as possible in the SDK code probably makes sense unless there are good reasons to do so.)

  • Hello Einar,

    Thank you very much for your answer.

    First, i want to clarify that i did not make any changes in the bootloader linker script. All values shown in that file are the same as the ones stated in the bootloader documentation, under memory layout, but for the nRF52810 with S112.

    I'm on nRF52832 with S112, so it arises a couple of questions:

    1) is it possible to have the bootloader performing DFU over ble using nRF52832 with s112? all examples i see use S132 with nRF52832

    2) how do change a project (app and bootloader) to use nRF52832 with S112? i mean which defines and where do i need to update? do i have to change linker script by hand? When i change the CFLAGS/ASMFLAGS in the makefile of bootloader project from -DNRF52810_XXAA to -DNRF52832_XXAA, the compiler complains about nRF5_SDK_17.0.2_d674dde/modules/nrfx/mdk/system_nrf52810.c:133:16: error: 'NRF_CCM_Type' has no member named 'MAXPACKETSIZE'
    133 | NRF_CCM->MAXPACKETSIZE = 0xFBul;

    I made no changes about this in my current project (app and bootloader)

    But i did try this: from you answer i got that my settings page and MRB settings were placed incorrectly (according to bootloader linker script). So, as a quick fix i generate new bootloader settings with --family NRF82810. This outputs a setting hex with the information placed in 0x2E000 and 0x2F000. i merged all together (bl+settings+app+sd) and flashed, but i still enter DFU mode and no app shows up even waiting the DFU inactivity timeout.

    Thanks again,

    Martin

  • The bootloader is not shown on that image because that capture correspond to flashing just the SD and my app. That is working, despite the difference we are seeing about the loaded hex files and the memory read from the device.

    Below you can find a capture showing the loaded the merged hex file (bl+set+app+sd), and memory read from the device after programming the merged hex. This is the scenario we have been talking about. The device enter DFU mode, no app shows running even after inactivity timeout, can perform an OTA DFU, but the OTA uploaded package (app only) does not runs, and enters DFU mode.

    The red warning banner shows up after loading merged hex file into the programming tool.

    I think we can share a folder, perhaps not fully public.

    Thanks!

  • Martin Buc said:
    The bootloader is not shown on that image because that capture correspond to flashing just the SD and my app. That is working, despite the difference we are seeing about the loaded hex files and the memory read from the device.

    I see, then perhaps there is an issue with the graphical representation in the programmer app. I suggest we ignore that for now. By the way, that also applies to the red warning banner, it shows up because there is data outside of the flash region, in this case in the UICR region. That is a known issue that has been reported before but is not yet fixed.

    It would be better to upload the firmware to DevZone rather han in a shared folder. As you don't want to share it publicly, I suggest you open a private support ticket and attach your projects there and refer to this case. That way it is shared in a private manner and we can discuss any private matters in the other thread.

  • Hello Einar,

    Sorry for the delay.

    Please find attached the bootloader and app projects that show the issue.

    Just to remember: when i erase the device, then flash SD and my app only, the app is working ok. When i erase the device and flash the merged hex with BL+settings+SD+app, the device enters DFU mode while expecting to run the app.

    You should put both projects in the same folder (in order to use makefile commands to flash). Also, these variables are needed in environment (replacing the path for your system).

    export NRF_GCC=~/gcc-arm-none-eabi
    export NRF_SDK=~/nRF5_SDK_17.0.2_d674dde

    Hope you can check this soon. Thanks.

    bootloader-test.zip

    firmware-test.zip

  • Hi,

    I will test on my end and get back to you. I will not be able to do it today, but will try tomorrow (Friday). If not, I will get back to you next week.

    Einar

  • I do not see any problems here, and when I test the bootloader starts the application right away, also after repeated resets.

    However, I see that you have NRF_BL_DFU_ENTER_METHOD_BUTTON set to 1 and NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN set to 16 in the bootloader's sdk_config.h. That is also the pin of your LED2_PIN in your application. The bootloader will configure this pin as an input and decide based on that if it should enter bootloader mode or start the application (if the pin is 0, enter DFU mode).  Note that if this is the problem will immediately be obvious if you use the debug bootloader with RTT logging, as that prints the reason for entering DFU mode.

    If you do not want to use the pin method to enter bootloader mode, set NRF_BL_DFU_ENTER_METHOD_BUTTON to 0.

Reply
  • I do not see any problems here, and when I test the bootloader starts the application right away, also after repeated resets.

    However, I see that you have NRF_BL_DFU_ENTER_METHOD_BUTTON set to 1 and NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN set to 16 in the bootloader's sdk_config.h. That is also the pin of your LED2_PIN in your application. The bootloader will configure this pin as an input and decide based on that if it should enter bootloader mode or start the application (if the pin is 0, enter DFU mode).  Note that if this is the problem will immediately be obvious if you use the debug bootloader with RTT logging, as that prints the reason for entering DFU mode.

    If you do not want to use the pin method to enter bootloader mode, set NRF_BL_DFU_ENTER_METHOD_BUTTON to 0.

Children
Related