Modify the MCUboot's booting process

Hi,

I want to use the MCUboot for the DFU and I have been able to configure it and flash it on the device so far (tested that it is correctly flashed).

But I need to make some modifications to the MCUboot's booting process to match with the device's specifications, the modifications that I need to do are:

  • Set a PIN on High as soon as it is powered, the device's turn off if I don't.
  • The device runs on battery so I need to check that the charger is connected before or that it has enough battery.
  • Change the upgrade strategy from swapping the images in the memory slots to just changing the address of the image that it will boot.

I would like to know the best way to make this modifications and in the case of the third point if there is a configuration option or example.

Parents
  • Hi,

    I would like to know the best way to make this modifications and in the case of the third point if there is a configuration option or example.

    If you need to run a function at boot, then the SYS_INIT can be used. (e.g. placed at the bottom of main.c of MCUBoot, assuming it's too late for your device to do it in your own application).

    Change the upgrade strategy from swapping the images in the memory slots to just changing the address of the image that it will boot.

    I'm not seeing any such configs. You can read about the upgrade strategies e.g. here 

Reply
  • Hi,

    I would like to know the best way to make this modifications and in the case of the third point if there is a configuration option or example.

    If you need to run a function at boot, then the SYS_INIT can be used. (e.g. placed at the bottom of main.c of MCUBoot, assuming it's too late for your device to do it in your own application).

    Change the upgrade strategy from swapping the images in the memory slots to just changing the address of the image that it will boot.

    I'm not seeing any such configs. You can read about the upgrade strategies e.g. here 

Children
  • Hi,

    the SYS_INIT can be used. (e.g. placed at the bottom of main.c of MCUBoot, assuming it's too late for your device to do it in your own application).

    Does the main.c file that you mention is the one located on the NCS' path bootloader/mcuboot/boot/zephyr?

    If that is the file, is there a way to create a copy (with my modifications) inside my application's project and just change the file that is going to be used?

    I would like to keep the modifications in the git repository and avoid modifying the NCS directly (if possible).

  • Erasmo said:
    I would like to keep the modifications in the git repository and avoid modifying the NCS directly (if possible).

    I found a different way. Create a file named CMakeLists.txt with this content:

    if(CONFIG_GPIO AND DEFINED CONFIG_MCUBOOT)
    	zephyr_library()
    	zephyr_library_sources(board.c)
    endif()

    place it in in your board folder, e.g. for the nRF52840DK board it would be: zephyr\boards\arm\nrf52840dk_nrf52840\

    Then in the board folder create a file board.c , with something like this:

    /*
     * Copyright (c) 2022 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <init.h>
    #include <drivers/gpio.h>
    #include <sys/printk.h>
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led1)
    
    #if DT_NODE_HAS_STATUS(LED0_NODE, okay)
    #define LED0	DT_GPIO_LABEL(LED0_NODE, gpios)
    #define PIN	DT_GPIO_PIN(LED0_NODE, gpios)
    #define FLAGS	DT_GPIO_FLAGS(LED0_NODE, gpios)
    #else
    /* A build error here means your board isn't set up to blink an LED. */
    #error "Unsupported board: led0 devicetree alias is not defined"
    #define LED0	""
    #define PIN	0
    #define FLAGS	0
    #endif
    
    static int board_init(const struct device *dev)
    {
    	int err;
    	printk("board_init\n");
    	printk("PIN %d\n",PIN);
    
    	static const struct device *led;
    
    	led = device_get_binding(DT_GPIO_LABEL(LED0_NODE, gpios));
    
    	bool led_is_on = false;
    
    	err = gpio_pin_configure(led, PIN, GPIO_OUTPUT_ACTIVE);
    	printk("gpio_pin_configure() returned: %d \n",err);
    	if (err < 0) {
    		return 1;
    	}
    
    	err = gpio_pin_set(led, PIN, (int)led_is_on);
    	printk("gpio_pin_set() returned: %d \n",err);
    	return 0;
    }
    
    SYS_INIT(board_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);

    This board_init() function will then be called before the bootloader starts.

    We do something similar here, but this is before the main application starts:

    https://github.com/nrfconnect/sdk-nrf/blob/v2.0.0/boards/arm/thingy91_nrf9160/adp5360_init.c

    https://github.com/nrfconnect/sdk-nrf/blob/v2.0.0/boards/arm/thingy91_nrf9160/CMakeLists.txt

  • Hi,

    I created the board.c file in the board folder and was able to set the PIN on High before the bootloader started, although I needed to define the PIN on the bootloader's overlay file to use it in the board.c file.
    I have a condition that verifies the device and in case that the condition is met I would like the device to stop every thing and don't turn on, right now I set the PIN back to Low and the device turn off over time, the problem is that in that interval the MCUboot starts its executions. Is there a way to stop the device from continuing when there is an error (the button is released) in the board_init() function? I already tried using a return codes 1 and -1.

    Also, I would like to modify the MCUboot to implement points 2 (battery and charger verification) and 3 (change upgrade strategy) from the original ticket I submitted. Will I have to modify the MCUboot's main.c file directly on the NCS? Or is there a way in which I can create a new main.c file that can be used by the MCUboot without modifying the one in the NCS?

  • Erasmo said:
    Is there a way to stop the device from continuing when there is an error (the button is released) in the board_init() function?

    You could e.g. call k_panic() when you detect an error. https://docs.zephyrproject.org/3.0.0/reference/kernel/other/fatal.html#kernel-panic

    Erasmo said:
    Or is there a way in which I can create a new main.c file that can be used by the MCUboot without modifying the one in the NCS?

    I don't think so. If you are sure can't do this in your application when it boots, and don't want to change the MCUBoot main.c in NCS, you could always create a PR to the MCUBoot with your changes. https://github.com/zephyrproject-rtos/mcuboot

  • Hi, it has been some time since the last message but I got busy with something else and had to put this issue on hold.

    But continuing from where it was left, I have been able to stop the execution of the code for enough time for the board to power OFF by using the function "NRFX_DELAY_US" in the file "board.c"

    Now I am trying to modify the MCUboot image to boot the application directly from the secondary partition. At first it was working with the Direct-XIP configuration, the MCUboot image's "prj.conf" looked like this:

    CONFIG_MCUBOOT_LOG_LEVEL_DBG=y
    CONFIG_BOOT_SWAP_USING_MOVE=n
    CONFIG_BOOT_DIRECT_XIP=y

    I even starting implementing my own changes, but it seems that it was working because some configuration was left on the chip since now it will always boot the application of the primary partition even when the Log says that the image in the secondary partition is newer and that it will be booting it.
    I tried going back in all my changes but the error is still present.


    Right now I have been debugging the booting process after the partition has been selected and it seems that both partitions have the same MSP (Main Stack Pointer) so that might be why the primary partition is booted even when the secondary partition is selected.

    I also found that I might need to use a file that has the word "secondary" in its name when writing an image in the secondary partition, I suppose that this one has the correct MSP to boot the image in the secondary partition, but I cannot see it in the "build" folder and if I try to set the configuration "CONFIG_BOOT_BUILD_DIRECT_XIP_VARIANT" on the application's "prj.conf" file I get a message that said that it is "undefined" during the compilation.

    What should I do so that i can get the correct image for the secondary partition or what should I configure in the MCUboot so that it can be booted?

    Thanks,
    Erasmo

Related