Jump from SoftDevice to Application A or B

We have an existing application for the NRF52840 using SDKv15. This application will handle writing a new application to a free bank.  I need to add the ability to jump from SoftDevice to the new Application (A or B).  Can I specify what address to jump to from SoftDevice?  If not, then would the SoftDevice jump to a small main application, then jump to either application A or B?

Example flash layout

- Application B

- Application A

- Soft Device

- MBR

~~~~~

Or would it go like this: Bootloader -> Softdevice->Application A or B:

- Bootloader

- Application B

- Application A

- Soft Device

- MBR

Parents
  • Hi,

    You will need a bootloader for this. The bootloader in the SDK does not support jumping to any address out of the box, but it is possible.

    The way this will work is that the MBR runs first, and then jumps to the bootloader. Then the bootloader can jump to either App 1 or App 2. (The default behavior in the bootloader in SDK version >= 15.0.0, is to jump to the SoftDevice, but then the SoftDevice will always jump to the application that is right above it.)

    See this post for details on how can be done with SDK 15.

  • Thank you for providing that example.  However, as I understand it, that suggests a custom bootloader that jumps to Application A or B.  I need to also run SoftDevice:

    ------MBR-->SoftDevice-->Application A or B.

    If SoftDevice always runs whatever is immediately after, and that is fixed, is there a way to jump to Application A or B after running SoftDevice? 

    -----MBR-->SoftDevice--"Bootloader" -->Application A or B

    Perhaps I need two SoftDevice sectors?

    -----MBR-->Bootloader--> (SoftDeviceA-->Application A) || (SoftDeviceB-->ApplicationB)

    Thank you for your guidance.

  • Softdevice only works in its specific flash location.

    Note that this also applies to any apps on Cortex-M3, at least last time I checked there was little support for position-independent code.

    One solution could be

    MBR->Bootloader->Softdevice->Stub App C deciding wether to ececute-> either A or B

  • Is there a way for the bootloader to tell the SoftDevice what address to jump to for the application?

    See Bootloader Documentation

    The bootloader is responsible for determining the start address of the application. It uses sd_softdevice_vector_table_base_set(uint32_t address) to tell the SoftDevice where the application starts.

    Did I read that wrong?  Is this to set where the bootloader jumps to (either application or SoftDevice)?

  • The post I linked to describe how you can use this both with and without a SoftDevice (the difference is one line that initializes parts of the SoftDevice and one line that configures the SoftDevice so that it knows the application vector table address).

Reply Children
  •  Thank you for that confirmation.  I will dive into that code further.  Much appreciated!

  • I am just now diving back into this.  In SDKv15, there is no definition for `sd_softdevice_vector_table_base_set`.  What do you suggest?

  • Perhaps I need to use `sd_mbr_command` instead, which takes a struct that includes the vector offset.

  • Hi,

    The sd_softdevice_vector_table_base_set() function is there in SDK 15 as well (see nrf_sdm.h)

  • Success!! Thanks for your help, Einar

    So far I have two applications loaded, neither of which start at the default address after the SoftDevices (not 0x0002'6000).  I can change myStartAddress to determine which app to run.

    Note! This applies to SDK15.0.0 and SoftDevices S140 v6.0.0.  I believe this is right before changes to where the start address of the bootloader is stored (from UCIR to MBR address).

    I repurposed the example: open_bootloader (pca10056_usb), though the bootloader does not transfer data so I could have started from a blank slate.

    As your linked post stated,,,

    1) Create Bootloader

    - Call nrf_bootloader_app_start(myStartAddress);

    void nrf_bootloader_app_start(uint32_t startAddress)
    {
        nrf_dfu_mbr_init_sd();
    
        // Disable and clear interrupts
        NVIC->ICER[0] = 0xFFFFFFFF;
        NVIC->ICPR[0] = 0xFFFFFFFF;
        NVIC->ICER[1] = 0xFFFFFFFF;
        NVIC->ICPR[1] = 0xFFFFFFFF;
    
        sd_softdevice_vector_table_base_set(startAddress);
        nrf_dfu_mbr_irq_forward_address_set(MBR_SIZE);
        nrf_bootloader_app_start_final(startAddress);
    }

    - Modify the function (as below) to accept a custom address to forward the IRQ

    uint32_t nrf_dfu_mbr_irq_forward_address_set(uint32_t address)
    {
        uint32_t ret_val = NRF_ERROR_INVALID_PARAM;
    //  uint32_t address = MBR_SIZE;
    ...

    In IAR's flash table (.icf), set:

    define symbol __ICFEDIT_intvec_start__ = 0x000E0000; 
    
    /*-Memory Regions-*/
    define symbol __ICFEDIT_region_ROM_start__   = 0x000E0000; //0x000F8000
    define symbol __ICFEDIT_region_ROM_end__     = 0x000FDFFF; //0x000FE000
    
    //I think this could be set to 0x000F8000-0x000FE000, but this is what the example used

    Guide the debugger to the correct __vector_table symbol: Project > Options > Debugger > Extra Options and specify:

    --drv_vector_table_base=0x000E0000

    2) Create Apps

    Tell IAR where to store the two apps:

    /*App A*/
    define symbol __ICFEDIT_intvec_start__ = 0x00027000;
    
    /*-Memory Regions-*/
    define symbol __ICFEDIT_region_ROM_start__   	= 0x00027000;
    define symbol __ICFEDIT_region_ROM_end__     	= 0x0004FFFF;
    
    or use... 
    /*App B*/
    define symbol __ICFEDIT_intvec_start__ = 0x00057000;
    
    define symbol __ICFEDIT_region_ROM_start__   	= 0x00057000;
    define symbol __ICFEDIT_region_ROM_end__    	= 0x00087000;
    
    

    3) Crop the Bootloader

    For some reason, the bootloader code has a byte at 0x00000000 that prevents merging with the MBR/SoftDevices code.  Exclude this using the free hex tool:

    srec_cat.exe bootloader.hex -Intel -exclude 0x00000000 0x00001000 -o bootLoaderCropped.hex -Intel

    4) Create the Bootloader Settings code

    This is not needed for SDK15.0.0, but you may need it on later SDK's or if you enable CRC checking (?)

    Generate the bootloader settings code using the NRF tool:

    nrfutil settings generate --family NRF52840 --application main_app.hex --application-version 1 --bootloader-version 1 --bl-settings-version 1 settings.hex

    5) Merge and Download Hex files

    Use the nice NRF Util Programmer to merge and upload hex files.

    - Select device

    - Add the hex files

    • Bootloader (0x000E'0000 - 0x000E'1315)
    • App 2 (0x0005'7000 - 0x0007'A0AF)
    • App 1 (0x0002'7000 - 0x0004'A0AF)
    • MBR (0x0000'0000 - 0x0000'0A17) & SoftDevices (0x0000'1000-0x0002'53C7)

    - Erase & Write: Note that I received an error: Part of the HEX regions are out of the device memory size.  But I just proceeded.

Related