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

How to do IRQ forwarding from bootloader?

Hello,

I've had to redesign my bootloader and I am now stuck with a problem that I can not solve. I need to know the correct workflow for switching from bootloader to application and I was unable to figure it out.

  • I am writing the UICR_BOOTADDR register with the address of my bootloader
  • I have two projects, one for my bootloader and one for my application at fitting addresses
  • My bootloader does not need the softdevice

When the bootaddress is set, all interrupts will be forwarded by the MBR to my bootloader. Before I start my application, I am doing the following:

interrupts_disable();

sd_mbr_command_t com;
com.command = SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET;
com.params.base_set.address = SD_SIZE_GET(MBR_SIZE);
err = sd_mbr_command(&com);

bootloader_util_app_start(CODE_REGION_1_START); //copied this function from the SDK code.

My app starts, but I have so far been unable to enable the softdevice or use sd_softdevice_vector_table_base_set. If I do not flash the bootloader and just the application, everything works as expected. It must have something to do with the interrupt table, but I am a bit lost there.

What is the correct order in which I call these functions? Also, GCC will not compile the bootloader_util_app_start function depending on the settings of the optimizer,...?

What does the SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET do? I get the feeling that it changes something persistently that is then remembered after a reboot....

  • Since the application relies on the softdevice being present you can try to use the code below:

    void bootloader_app_start(uint32_t app_addr)
    {
        // If the applications CRC has been checked and passed, the magic number will be written       and we
    // can start the application safely.
    sd_mbr_command_t com = {SD_MBR_COMMAND_INIT_SD, };
    
    uint32_t err_code = sd_mbr_command(&com);
    APP_ERROR_CHECK(err_code);
    
    interrupts_disable();
    
    // Set base address for the applications vector table
    err_code = sd_softdevice_vector_table_base_set(app_addr);
    APP_ERROR_CHECK(err_code);
    
    // Branch to the reset handler for the application
    bootloader_util_app_start(app_addr);
    
    }
    

    If you compile without optimization you need to add '-fomit-frame-pointer' to the compiler flags for it to compile correctly.

    SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET does set the address persistently within the MBR, but you don't want this in this case as the bootloader should always start first

  • Thanks, that worked :-) I had parts of that code in my application and only executed it when the BOOTADDR was set, but this way looks better.

    So the sd_mbr_command_init_sd will set the magic number in the softdevice info structure? and maybe, the SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET will also change something in the softdevice's image? Any chance that could be added to the doumentation?

    What does sd_softdevice_vector_table_base_set do? Will it write a value to the ram?

  • That's good:) sd_mbr_command_init_sd will invoke the softdevice which basically means that the MBR will start forwarding interrupts to the softdevice. The softdevice will then relay the interrupts to either the bootloader or application depending on the address used in previous call to sd_softdevice_vector_table_base_set(). The address argument in is stored in RAM and will be cleared on reset ensuring that the bootloader will boot first on startup.

    SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET sets the forwarding address within the MBR persistently. Unfortunately, that's not very clear from the documentation [here] (infocenter.nordicsemi.com/.../mbr_sd_reset_behavior.html, but I verified that the address was in fact stored at 0x800 after issuing this command.

Related