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

Problem with bootloader relocation

My goal is to replace the legacy bootloader present in nRF52832 with a new bootloader with the DFU process.

I am using nRF5 SDK v15.3.0, GCC ARM and S132.

I have done the following with the help of this.

To summarize,

  • The new bootloader was copied into bank-1.
  • Next, the UICR region is erased and the new address is written into 0x10001014 and also the other content which was present before erasing.
  • I had verified the new address being written to 0x10001014 (NRF_UICR->NRFFW[0]).

Now the problem is that, after calling the sd_mbr_cmd(..) with SD_MBR_COMMAND_COPY_BL command, the device resets and doesn't start the new bootloader.

A similar question was asked here, but doesn't seem to have a solution.

I am not sure if I am missing something.

Thanks in advance.

Update: I have also verified (with the help of JLink by reading bytes at the new location) that the new bootloader is being copied into the new location.

Parents
  • Hi Naveenj,

    Could you do a nrfjprog --readcode and read the entire hex dump of the chip ? So that we would know if the softdevice and the bootloader is copied properly or not. 

    Could you tell the softdevice version of the old one and the new one ? I would suggest to try to move from SDK v11 to SDK v12 as described in the guide first before trying to jump from SDK v11 to SDK v15. 

  • I am using SDK v15 and softdevice S132 v6.1.1.

    I verified with the help of nrfjprog --readcode that there is no change in the softdevice (at 0x1000), between the hex files obtained from 1. before writing the bootloader to the new location (working) and 2. after DFU, copying the new bootloader and resetting (not working).

    I also verified that the bootloader is being copied to the new location (0x70000) which was 0x71000 previously. Also UICR->NRFFW[0] (0x10001014) reads 0x70000.

    I have modified the code that copies the bootloader ("bl_activate()" in nrf_bootloader_fw_activation.c ) to include the UICR region erase and writes (from the post mentioned).

    Also would you like to know any differences between the above said hex files?

  • The address 0xFF8 shows FFFF.., every time, which means there is no address in the MBR region. In which case, it should use the address present in UICR region (0x10001014) but seems like it isn't doing so.

    Or by saying "MBR Setting Page", did you mean the one present in UICR.NRFFW[1] (just after the bootloader - higher address / MBR Param Storage)?

    Additionally, the following two check scenarios could be of help (supporting your hypothesis):

    - copied the same bootloader to a different address (0x60000) faraway from the current one (also modified the UICR address to this) and it still jumps to the same old address 0x71000.

    - over-wrote the existing bootloader just in place (i.e. at 0x71000) with the same code and I could verify that it works (staying at the older address).

    I am lighting up an LED in the main() of the bootloader to know that the bootloader is functioning.

    Update: when I read the content present at the address in UICR.NRFFW[1] (MBR Param Storage), it is cleared. Before writing the new bootloader, this address has some content.

    Also, could you tell me how to interpret the data present in MBR Parameter Storage?

  • Hello Hung,

    I've been struggling with this for a while, could you tell me how to set the address in the MBR settings page (I am assuming this to be a part of address *UICR.NRFFW[1])?

  • Hi Naveenj, 

    I would suggest to test with the stock bootloader, you can have a fresh copy of the SDK. 

    Which IDE you are using ? If you using KEIL, this line should be enabled in nrf_bootloader_info.c. 

    uint32_t m_uicr_bootloader_start_address __attribute__((at(NRF_UICR_BOOTLOADER_START_ADDRESS)))
    = BOOTLOADER_START_ADDR;

    This line will configure the address NRF_UICR_BOOTLOADER_START_ADDRESS = MBR_BOOTLOADER_ADDR = 0xFF8 with the value of BOOTLOADER_START_ADDR 

    When you flash the bootloader hex file, the value whould be written at 0xFF8. 

    I assume you are using S132 v6.1.1 ? 

    If you still having trouble you can send us the hex files you have (bootloader + softdevice )

  • I am not using any dedicated IDEs and I am using GCC ARM compiler.

    This line is enabled in my case:

    volatile uint32_t m_uicr_bootloader_start_address __attribute__ ((section(".uicr_bootloader_start_address")))
    = BOOTLOADER_START_ADDR;
    Yes, I am using S132 v6.1.1.
    The bootloader is initially present at 0x71000, relocated to 0x70000. I am attaching the hex files that I took at every step.
    This is the final file after relocating the bootloader.
    This hex file, is taken just after the bootloader is received and before the bootloader is written to the new location.
    This is before the whole process is started.
    The linker file:
    Update: Just to clear some confusion, I am trying to relocate from the bootloader code. Flashing it fully with the new address works, but I want to do this from the bootloader code itself.
  • Hi, 

    Please send us your bootloader and softdevice hex file, the original one. Don't test with changing/switching the bootloader yet. Test with just the normal bootloader, we need to find where the MBR find the bootloader location. 

    I attached here bootloader that I built, you can see at the first 3 lines the address 0xFF8 is written 0x78000 

    I don't see that in your dump_after_copying_to_newloc.hex nor dump_before_dfu.hex

    Note that flash dump wouldn't show the UICR. 

    bootloader.hex

Reply Children
  • When I generated the hex file with the help of example ld file present in examples/pca10040_ble_debug, it shows the address there at 0x0FF8.

    However, when I compared it with the ld file I am using, it was preferred to use it this way because it can be changed during run time (as per my understanding).

    Example file:

    uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4
    uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4
    mbr_params_page (r) : ORIGIN = 0x0007E000, LENGTH = 0x1000
    bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000

    My file:

    mbr_params_page (r) : ORIGIN = 0x0007E000, LENGTH = 0x1000
    bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000
    uicr_mbr_params_page (r) : ORIGIN = 0x10001018, LENGTH = 0x4
    uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4

  • I don't see much of benefit of using UICR in your case. I don't think you can be able to change it in runtime. UICR is a page in flash, you can't change it in runtime unless you erase and rewrite UICR.

    If you want to stick to UICR to store the start address of the bootloader it should be fine, but when you update the UICR bootloader start address (0x10001014), make sure 0x10001018 is restored after the erase as well. 

    Could you check now, after you update the bootloader to different location, do you have the UICR configured correctly. 

  • I had verified that up on DFU success the content of 0x10001014 is indeed the new address and content of 0x10001018 is also what is intended (0x7E000). However, I am seeing something weird, the page 0x7E000 is blank.

    Could this be the cause?

    Update:

    The content at 0x7E000 is present until the bootloader command is executed, but it is being erased right after the command SD_Command is executed [nrf_dfu_mbr_copy_bl (or even sd_mbr_command, tried both)]

    ------ ignoring the previous observation -----

    It tries to write to 0x7E000, but fails to update there.

    "<debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0007E000, src=0x20007474, len=896 bytes), queue usage: 1"

    I see the content in the src addr as something, but 0x7E000 is just blank after the write operation.

    ----------------------------------------------------------

  • It's protected in this call :

    ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR,area_size,NRF_BOOTLOADER_READ_PROTECT);

    Inside nrf_bootloader_app_start_final() of nrf_bootloader_app_start_final.c . Not sure in your case it's executed or not. 

    But I'm not sure why you need to check the mbr_params_page. It's for the MBR to use internally and application, or bootloader should not write to it. 

    If the bootloader start address is correct, the MBR supposed to forward the PC and vector table to the new bootloader address. Could you check where the PC is forwarded to after your download ? 

  • mbr_params_page caught my attention because it is completely blank when I compare it with a working version. So nothing related to the start is present in that region?

    I already commented the part which protects the flash.

    Immediately, after the new bootloader is downloaded and reset, the PC reads 0x20010000.

Related