MCUboot should only timeout after hardware reset

Hi there,

I've made MCUboot work, but it always timeouts before loading the application firmware. I only want it to timeout after resetting the SoC via its RESET pin.

I added CONFIG_BOOTLOADER_MCUBOOT=y to my prj.conf, and my mcuboot.conf contains the following:

CONFIG_PINCTRL=y
CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x10000
CONFIG_LOG=y
CONFIG_SIZE_OPTIMIZATIONS=y
CONFIG_SERIAL=y
CONFIG_UART_LINE_CTRL=y
CONFIG_MCUBOOT_SERIAL=y
CONFIG_BOOT_SERIAL_CDC_ACM=y
CONFIG_BOOT_SERIAL_PIN_RESET=y
CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=y
CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT=3000
CONFIG_BOOT_SERIAL_NO_APPLICATION=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_BACKEND_RTT=n

My second issue is that I have to add the `-Dmcuboot_OVERLAY_CONFIG=/home/laci/projects/firmware-uhk/uhk/device/mcuboot.conf` west argument every time I build because the VS Code forgets it:

How can I persist this setting? The "Save Configuration as Preset" option doesn't make a difference.

Thanks in advance!
- Laci

Parents
  • Hi Laci,

    The CONFIG_BOOT_SERIAL_WAIT_FOR_DFU option will make the bootloader always enter serial recovery upon startup. If you don't want this, you should disable this option.

    With regards to issue where the VS code extension "forgets" the build setting, I will to try to reproduce it here. In the meantime, please consider creating a child image folder with your Kconfig file as I suggested in this post:  RE: Issues with Building MCUboot for nRF7002DK Using NCS V2.5.2 

    Best regards,

    Vidar 

  • Hi Vidar,

    I understand that I should remove CONFIG_BOOT_SERIAL_WAIT_FOR_DFU to avoid the initial timeout, but I still want the bootloader to timeout when the SoC is restarted via hardware reset. How can I achieve it?

    Thank you for looking into the VS Code-related issue. I've checked the referenced project, but I can't build the MCUboot-related part of it, and I'd rather wait for your findings.

  • Hi Laci,

    mlac said:
    I understand that I should remove CONFIG_BOOT_SERIAL_WAIT_FOR_DFU to avoid the initial timeout, but I still want the bootloader to timeout when the SoC is restarted via hardware reset. How can I achieve it?

    My apologies. I was under the impression that the CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT applied to all serial entry methods, but I now realize that this is not the case. However, from looking at the main.c implementation for mcuboot, it seems like you can achieve this by simply replacing boot_serial_enter() with boot_serial_check_start() at this line:

    https://github.com/nrfconnect/sdk-mcuboot/blob/6902abba270c0fbcbe8ee3bb56fe39bc9acc2774/boot/zephyr/main.c#L545 

    mlac said:
    Thank you for looking into the VS Code-related issue. I've checked the referenced project, but I can't build the MCUboot-related part of it, and I'd rather wait for your findings.

    I was able to reproduce the same behavior here and have reported it to our VS Code extension team. While waiting for this to be fixed, please create the 'child_image' folder as suggested earlier and place your 'mcuboot.conf' file in this folder. The file will then be picked up by the build system the next time you perform a pristine build.

  • Thanks so much for your help, Vidar! Your suggestion of putting mcuboot.conf into the child_image directory and modifying mcuboot/boot/zephyr/main.c worked perfectly.

    A little correction: The compiler complained that boot_serial_check_start() was given too few arguments. Actually, boot_serial_check_start(&boot_funcs,timeout_in_ms) had to be called, and the definition of timeout_in_ms had to be moved before the call.

    Now, I'm only puzzled about how to integrate the modified mcuboot into my project. My best idea is forking https://github.com/nrfconnect/sdk-mcuboot on GitHub and adding my fork to west.yml to override the stock mcuboot repo. Do you know of a better way?

Reply
  • Thanks so much for your help, Vidar! Your suggestion of putting mcuboot.conf into the child_image directory and modifying mcuboot/boot/zephyr/main.c worked perfectly.

    A little correction: The compiler complained that boot_serial_check_start() was given too few arguments. Actually, boot_serial_check_start(&boot_funcs,timeout_in_ms) had to be called, and the definition of timeout_in_ms had to be moved before the call.

    Now, I'm only puzzled about how to integrate the modified mcuboot into my project. My best idea is forking https://github.com/nrfconnect/sdk-mcuboot on GitHub and adding my fork to west.yml to override the stock mcuboot repo. Do you know of a better way?

Children
  • I'm glad to hear that it worked.

    mlac said:
    Now, I'm only puzzled about how to integrate the modified mcuboot into my project. My best idea is forking https://github.com/nrfconnect/sdk-mcuboot on GitHub and adding my fork to west.yml to override the stock mcuboot repo. Do you know of a better way?

    Creating a fork might be the more appropriate way to handle this. However, I would likely have opted for creating a local patch that I apply manually with each new release. A third option is to submit a PR to propose this change upstream.

  • For some reason, I believed that the suggested MCUboot modification worked, but when testing it again, I realized that the bootloader still always timeouts, not only when the board has been hardware-reset.

    I'm surprised that there's no relevant MCUboot option because my use case shouldn't be unusual; I want the board to boot up as quickly as possible, but I also want to be able to manually trigger the bootloader even if the application firmware is broken. There are plenty of unanswered issues and pull requests in the MCUboot repo, so my hopes are not high, but I'll open an issue nevertheless.

    Do you have further ideas for achieving what I'm after? If my goal requires custom development that is outside the scope of this support, I understand. I can probably figure this out, but it may be time-consuming. Alternatively, I'd be glad to pay to get this done.

  • Please try to apply the diff below, then test your project with the following kconfig settings:

    CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=y
    CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_ALWAYS=n
    CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT=3000

    diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery
    index 52ec3b01..3487e37d 100644
    --- a/boot/zephyr/Kconfig.serial_recovery
    +++ b/boot/zephyr/Kconfig.serial_recovery
    @@ -155,13 +155,17 @@ config BOOT_SERIAL_DETECT_DELAY
     	  the one used to place the device in bootloader mode.
     
     menuconfig BOOT_SERIAL_WAIT_FOR_DFU
    -	bool "Wait a prescribed duration to see if DFU is invoked by receiving a MCUmgr comand"
    +	bool "Wait a prescribed duration to see if DFU is invoked by receiving a MCUmgr command"
     	depends on BOOT_SERIAL_UART || BOOT_SERIAL_CDC_ACM
     	help
     	  If y, MCUboot waits for a prescribed duration of time to allow
     	  for DFU to be invoked. The serial recovery can be entered by receiving any
     	  mcumgr command.
     
    +config BOOT_SERIAL_WAIT_FOR_DFU_ALWAYS
    +	bool "Always enter serial recovery mode upon startup"
    +	depends on BOOT_SERIAL_WAIT_FOR_DFU
    +
     config BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT
     	int "Duration to wait for the serial DFU timeout in ms"
     	default 500
    diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c
    index 27039700..4364ea67 100644
    --- a/boot/zephyr/main.c
    +++ b/boot/zephyr/main.c
    @@ -559,8 +559,12 @@ static void boot_serial_enter()
         BOOT_LOG_INF("Enter the serial recovery mode");
         rc = boot_console_init();
         __ASSERT(rc == 0, "Error initializing boot console.\n");
    +#ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU
    +    boot_serial_check_start(&boot_funcs, CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT);
    +#else
         boot_serial_start(&boot_funcs);
         __ASSERT(0, "Bootloader serial process was terminated unexpectedly.\n");
    +#endif 
     }
     #endif
     
    @@ -649,7 +653,7 @@ int main(void)
         }
     #endif
     
    -#ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU
    +#ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_ALWAYS
         /* Initialize the boot console, so we can already fill up our buffers while
          * waiting for the boot image check to finish. This image check, can take
          * some time, so it's better to reuse thistime to already receive the
    @@ -674,7 +678,7 @@ int main(void)
         }
     #endif
     
    -#ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU
    +#ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_ALWAYS
         timeout_in_ms -= (k_uptime_get_32() - start);
         if( timeout_in_ms <= 0 ) {
             /* at least one check if time was expired */
    

  • Thank you so much for your help, Vidar! It works perfectly, and you also added a relevant Kconfig option, making it generally usable.

    May I create a MCUboot pull request based on your patch?

  • It's great if you want to make a PR based on this patch I've created. I recommend adding more descriptive text to the Kconfig symbols CONFIG_BOOT_SERIAL_WAIT_FOR_DFU and CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_ALWAYS.  Especially for the CONFIG_BOOT_SERIAL_WAIT_FOR_DFU symbol, as this change will affect how this configuration setting should be used.

Related