top of page
  • Linkedin

General Discussions

Public·2 members

Zephyr: Entering Serial Recovery bootmode programatically

Hello everyone!


Today we'll cover the topic on how to enter Serial Recovery boot mode in MCUBoot, using Zephyr. This can be handful if no user input is available, as traditionally, it is how you let the user initiate Serial Recovery.

In this article, we'll see:

  • How configure MCUBoot to enable Serial Recovery

  • How to add a retention memory to communicate between our application and MCUBoot

  • How to request Serial Recovery mode from the application

  • What is needed once entering the Serial Recovery mode


Configuring MCUBoot for Serial Recovery

The first step is enabling serial recovery support in MCUBoot. This is done through the MCUBoot Kconfig options.


You’ll need to make sure your build of MCUBoot is compiled with:

CONFIG_MCUBOOT_SERIAL=y

Depending on your board, you may also need to configure the UART device used by MCUBoot for recovery. For example:

CONFIG_MCUBOOT_SERIAL_UART=1

This ensures that MCUBoot includes the serial recovery subsystem and listens on the correct UART port for incoming SMP commands.


Adding Retention Memory

To request Serial Recovery from your application, Zephyr offers the retention memory API. It allows one to define an area in the DTS, which will be shared across you application and MCUBoot. Here is how to add it in the DTS overlay:


/ {
    /* Define a non-init RAM region as retained memory */
    sram@2003FC00 {
        compatible = "zephyr,memory-region", "mmio-sram";
        reg = <0x2003FC00 DT_SIZE_K(1)>;
        zephyr,memory-region = "RetainedMem";
        status = "okay";
        /* Define a small partition dedicated to boot mode (1 byte) */
        retainedmem {
            compatible = "zephyr,retained-ram";
            status = "okay";
            #address-cells = <1>;
            #size-cells = <1>;

            retention0: retention@0 {
                compatible = "zephyr,retention";
                status = "okay";
                reg = <0x0 0x1>;
            };
        };
    };

    /* Tell Zephyr this retention region is used for boot-mode */
    chosen {
        zephyr,boot-mode = &retention0;
    };
};

/* Reduce SRAM0 usage by 1 byte to account for non-init area */
&sram0 {
        reg = <0x20000000 0x3FFFF>;
};

And in the config (prj.conf or an overlay):

CONFIG_RETAINED_MEM=y
CONFIG_RETENTION=y
CONFIG_RETENTION_BOOT_MODE=y

# Enable MCUboot serial recovery feature
CONFIG_MCUBOOT_SERIAL=y
CONFIG_BOOT_SERIAL_BOOT_MODE=y

Requesting Serial Recovery from the Application

Once the retention mechanism is in place, the application can request Serial Recovery mode by:

  1. Writing the predefined flag value into the retention memory.

  2. Triggering a system reset (sys_reboot(SYS_REBOOT_COLD) in Zephyr).

#include <zephyr/retention/bootmode.h>
#include <zephyr/sys/reboot.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);

void request_serial_recovery(void){
    int ret;
    ret = bootmode_set(BOOT_MODE_TYPE_BOOTLOADER);
    if (ret) {
        LOG_ERR("Failed to set boot mode (err %d)", ret);
        return;
    }

    sys_reboot(SYS_REBOOT_COLD);

    /* Should not reach here */
}

On the next startup, MCUBoot detects the flag and drops directly into Serial Recovery, waiting for a flashing system to send new firmware.


What Happens in Serial Recovery Mode

When MCUBoot is running in Serial Recovery, it uses the Simple Management Protocol (SMP) over UART. This means it expects SMP packets containing image management commands (upload, erase, test, confirm, etc.). The commands implementation can be found at bootloader/mcuboot/boot/boot_serial/src/boot_serial.c


To make use of this, you need an SMP-capable machine another Zephyr device configured as an SMP client.

Some common options:

  • From a host machine: use mcumgr, the reference SMP tool. For example:

mcumgr -t 30 -c serial1 image upload app_update.bin

  • From another Zephyr board: you can build Zephyr with the mcumgr subsystem enabled, turning the board into an SMP client. In this case, you’ll need to configure the board with:

CONFIG_MCUMGR=y 
CONFIG_MCUMGR_CMD_IMG_MGMT=y 
CONFIG_MCUMGR_CMD_OS_MGMT=y 
CONFIG_MCUMGR_SMP_UART=y

Then, your second board can act as the update host and push firmware into the target board running MCUBoot in Serial Recovery, from an SDCard, WiFi, ...


Conclusion

With this setup, your application can programmatically request Serial Recovery, and MCUBoot will listen for new firmware uploads via SMP, whether from a PC host tool like mcumgr or from another SMP capable device.

23 Views
bottom of page