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 Reply Children
  • 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.

  •  , a few questions I would like to ask:

    1) How should I set IAR to debug this while it jumps from bootloader to app A or AppB?

    • Combine both projects under the same Workspace
    • Tell IAR that vector table is at the bootloader starting address: drv_vector_table_base=0x000E0000
    • Download the .out file as an extra image under Debugger?  (Perhaps this is just needed when using two separate workspaces)

    2) Why does the bootloader code have data at 0x0000'0000, which conflicts with the MBR/SoftDevices S140 code?

    3) Where is the best place to put generic application data? 

    4) If I wanted to use CRC checking, I assume I would need to generate bootloader settings and update the CRC there.  What other settings do I need to change in the code?

    5) I'm a bit confused about the bootloader start address.  With my SDK, it seems that it is defined here: 

    #define NRF_UICR_BOOTLOADER_START_ADDRESS       (NRF_UICR_BASE + 0x14)
    

    and it provides a symbol for IAR to write it to ICIR:

    #if defined (__CC_ARM )
        #pragma push
        #pragma diag_suppress 1296
        uint32_t  m_uicr_bootloader_start_address __attribute__((at(NRF_UICR_BOOTLOADER_START_ADDRESS)))
                                                        = BOOTLOADER_START_ADDR;
        #pragma pop
    #elif defined ( __GNUC__ ) || defined ( __SES_ARM )
        volatile uint32_t m_uicr_bootloader_start_address  __attribute__ ((section(".uicr_bootloader_start_address")))
                                                = BOOTLOADER_START_ADDR;
    #elif defined ( __ICCARM__ )
        __root    const uint32_t m_uicr_bootloader_start_address @ NRF_UICR_BOOTLOADER_START_ADDRESS
                                                = BOOTLOADER_START_ADDR;
    #endif

    However, others have advised to write this start address using NRF tools:

    nrfjprog --memwr 0xff8 --val 0x78000 // An example that does not use the correct address and value

  • Hi,

    I am glad to hear you got it working!

    erk1313 said:
    1) How should I set IAR to debug this while it jumps from bootloader to app A or AppB?

    I must admit we don't use IAR much, but generally most debuggers will start executing from the start address of the binary that is running, and that will not work when you have a bootloader (and not even a SoftDevice). As long as execution starts at 0 (starting with the MBR), I would assume it should be OK in that regard? (You have also the issue that the bootloader will check the hash of the application, so if you changed the application you must also update the bootloader settings or modify the bootloader to not check the CRC, but this is regardless of the debugging environment you are using).

    erk1313 said:
    2) Why does the bootloader code have data at 0x0000'0000, which conflicts with the MBR/SoftDevices S140 code?

    This data is the bootloader start address, that the MBR check to know if there is a bootloader, and if so, where it is. In recent SDK versions, the bootloader hex file will contain the bootloader start address in the UICR 0x10001014, and on first boot, the, the MBR will copy it to address 0xFF8, which is in the end of the MBR page. However, a few SDK 15 minor versions had this in the MBR page itself in the hex file instead of the UICR. This caused problems, as if you for instance program the MBR (typically with the SoftDevice) first, and then program the bootloader, the MBR would typical be erase with the most common programing method, which is to do an erase of all sectors that are to be written to. 

    erk1313 said:
    3) Where is the best place to put generic application data? 

    That is right before (lower address) the bootlaoder. This is also where the FDS pages are located if you use FDS. The bootlaoder can be configured to never touch a specified amount of pages in this area, to prevent corrupting this data during DFU updates (when the area above the application can be used as a second slot to temporarily hold a new image. The relevant define here is NRF_DFU_APP_DATA_AREA_SIZE in the bootloader's sdk_config.h.

    erk1313 said:
    4) If I wanted to use CRC checking, I assume I would need to generate bootloader settings and update the CRC there.  What other settings do I need to change in the code?

    Yes, that is correct. CRC checking is the default so that is in use without you having to change anything.

    erk1313 said:
    5) I'm a bit confused about the bootloader start address.  With my SDK, it seems that it is defined here: 

    This goes back to my answer in 2). This is the bootloader start address.

Related