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.

  • 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 

  • 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

Related