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

How do I change the application/bootloader start address?

My ultimate issue is trying to get a bootloader working on custom hardware with an nRF52832. The bootloader is mostly the base UART DFU bootloader from the Nordic SDK, with a few customizations to work with our hardware. I've been able to get the bootloader up and running by using the following flash set up that I have for the application: FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x5a000. However, when I try to change the start address (e.g. to FLASH (rx) : ORIGIN = 0x25000, LENGTH = 0x5b000), the bootloader no longer appears to run. Similarly, I can use Eclipse to step into the debug code of the bootloader when it starts at 0x26000, but not at 0x25000.

To try to eliminate as many variables as possible, I also tried changing the start address of one of the SDK examples and running it on an nRF52 dev kit. In the same way as the bootloader on custom hardware, building the ble_central/ble_app_blinky_c produces an hex file that will run successfully on the dev kit, while building it with the start address changed to 0x25000 produces a hex file that will not run successfully. Below is a diff of my complete changes to the blinky example.

diff --git a/examples/ble_central/ble_app_blinky_c/pca10040/s132/armgcc/ble_app_blinky_c_gcc_nrf52.ld b/examples/ble_central/ble_app_blinky_c/pca10040/s132/armgcc/ble_app_blinky_c_gcc_nrf52.ld
index 1cdf99f61..f4c14ecb0 100644
--- a/examples/ble_central/ble_app_blinky_c/pca10040/s132/armgcc/ble_app_blinky_c_gcc_nrf52.ld
+++ b/examples/ble_central/ble_app_blinky_c/pca10040/s132/armgcc/ble_app_blinky_c_gcc_nrf52.ld
@@ -5,7 +5,7 @@ GROUP(-lgcc -lc -lnosys)

 MEMORY
 {
-  FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x5a000
+  FLASH (rx) : ORIGIN = 0x25000, LENGTH = 0x5b000
   RAM (rwx) :  ORIGIN = 0x20001d70, LENGTH = 0xe290
 }

In both the custom code/hardware and stock SDK/dev kit situations I'm using GCC as my compiler and SDK 15.2.0, with softdevice s132_nrf52_6.1.0_softdevice.hex. My programming procedure in each case is:

nrfjprog -f nrf52 --eraseall
nrfjprog -f nrf52 --chiperase --program <path_to_softdevice>
nrfjprog -f nrf52 --sectorerase --program <application or bootloader>.hex
nrfjprog -f nrf52 --reset

What am I missing about changing the starting address of either the application or the bootloader? What configuration needs to be done to get an application and bootloader running together?

Thanks.

Parents
  • Hi Kathleen,

     the S132 v6.1.0 SoftDevice requires 152 kB (0x26000 bytes) of program memory, starting from 0x0000 ( This is included the MBR, see Memory resource map and usage for the memory layout). So when you are setting the application or bootloader start address to 0x25000, you are effectively overwritting the SoftDevice. Hence setting any start address higher than 0x26000 should work fine for both the bootloader and the application. 

    Best regards
    Bjørn 

  • So that explains why 0x25000 won't work as a start address, but I also can't run the blinky example with the following configuration: FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x59000. Any idea what might be going on here?

  • The SoftDevice will forward interrupts/events  to the application and for the SoftDevice to locate the application interrupt vectors, the application must define its interrupt vector table at the bottom of the Application Flash Region illustrated in Memory resource map. When the base address of the application code is directly after the top address of the SoftDevice, the code can be developed as a standard ARMRegistered CortexRegistered -M4 application project with the compiler creating the interrupt vector table, see Interrupt forwarding to the application for more information.

    In other words, the application must start right after the SoftDevice. The bootloader can be placed anywhere above the application as the MBR will find the bootloader start address in the UICR registers and then forward interrupts to that address, see Master boot record and bootloader for more information.

  • So if I'm understanding you right, the blinky application isn't working at another address because it has to be located immediately after the softdevice (i.e. 0x26000.) But the bootloader should be able to be placed pretty much anywhere in flash where's it's not overwriting the softdevice as the its start location is saved in the UICR registers.

    When I switch over to using our custom bootloader, I'm seeing that when I set the flash configuration to FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x5a000, the bootloader boots up and prints to the debug port successfully, but when I set the flash configuration to FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x59000I don't see any output on the debug port, leading me to believe the bootloader is never being run. As part of my programming procedure I'm running an eraseall, which should make sure the UICR registers get reprogrammed and I'm also making sure to reset the board after programming everything. What am I missing here?

  • Yes, you understanding is correct. 

    Are you able to debug the bootloader when you use the FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x59000 configuration?

    Best regards

    Bjørn

Reply Children
  • No, I am not able to debug with that configuration. I have been able to debug the bootloader with the FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x5a000 configuration.

  • I think the issue is that the length value is to large as ORIGIN+LENGTH is 0x81000. The bootloader should stop at the start of the MBR Params page at 0x7E000, i.e. LENGTH = 0x78000 - ORIGIN = 0x57000.

    I tested the following setting with the bootlaoder in SDK v15.2.0 and I had no issues. 

     FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x57000

  • I've noticed that my custom bootloader isn't setting the bootloader start address in the UICR registers. Is there anything specific in the project setup that signals nrfjprog that a given application is a bootloader and thus that the UICR registers should be set? I'm using the same ld file for my bootloader as for the example in the SDK, so maybe I'm missing something in the makefile?

  • Hi Kathleen,
    as long as you have the following memory regions and sections set in your linker script

    MEMORY
    {
      FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x57000
      RAM (rwx) :  ORIGIN = 0x200057b8, LENGTH = 0xa848
      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
    }
    
    SECTIONS
    {
      .mbr_params_page(NOLOAD) :
      {
        PROVIDE(__start_mbr_params_page = .);
        KEEP(*(SORT(.mbr_params_page*)))
        PROVIDE(__stop_mbr_params_page = .);
      } > mbr_params_page
      .bootloader_settings_page(NOLOAD) :
      {
        PROVIDE(__start_bootloader_settings_page = .);
        KEEP(*(SORT(.bootloader_settings_page*)))
        PROVIDE(__stop_bootloader_settings_page = .);
      } > bootloader_settings_page
      .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
      .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
    }

    specifically the uicr_bootloader_start_address section, then you should be fine. Could you search through your .map file and see if uicr_bootloader_start_address section is included in the generated binary?

  • I've got this line  under Memory Configuration:

    uicr_bootloader_start_address 0x10001014         0x00000004         r

    And this later on in the map file:

    .uicr_bootloader_start_address
                    0x10001014        0x0
                    [!provide]                PROVIDE (__start_uicr_bootloader_start_address = .)
     *(SORT_BY_NAME(.uicr_bootloader_start_address*))
                    [!provide]                PROVIDE (__stop_uicr_bootloader_start_address = .)

Related