From 20c461dd5396deabf3bc81454a038f575f20bbf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nerijus=20Bend=C5=BEi=C5=ABnas?= Date: Wed, 3 Jun 2026 16:06:00 +0300 Subject: [PATCH] boot: zephyr: enter USB DFU on retention boot mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BOOT_USB_DFU_WAIT only waits a fixed duration, leaving no way for an application to request DFU recovery on demand as BOOT_SERIAL_BOOT_MODE does for serial recovery. Add BOOT_USB_DFU_BOOT_MODE as an independent entrance method: an application sets Zephyr's boot mode retention flag and reboots, and the bootloader stays in USB DFU indefinitely. It can be used on its own or combined with the wait and GPIO methods. Signed-off-by: Nerijus Bendžiūnas --- boot/zephyr/Kconfig | 8 ++++++ .../include/mcuboot_config/mcuboot_config.h | 3 ++- boot/zephyr/io.c | 6 +++-- boot/zephyr/main.c | 25 ++++++++++++++++--- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 228bb5bd7e..e389287772 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1091,6 +1091,14 @@ config BOOT_USB_DFU_DETECT_DELAY Useful for powering on when using the same button as the one used to place the device in bootloader mode. +config BOOT_USB_DFU_BOOT_MODE + bool "Check boot mode via retention subsystem" + depends on RETENTION_BOOT_MODE + help + Allows for entering USB DFU mode by using Zephyr's boot mode + retention system (i.e. an application must set the boot mode to stay + in USB DFU mode and reboot the module). + config BOOT_USB_DFU_NO_APPLICATION bool "Stay in bootloader if no application" help diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 2ae16b7576..efa6fe7edf 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -367,7 +367,8 @@ #endif #if (defined(CONFIG_BOOT_USB_DFU_WAIT) || \ - defined(CONFIG_BOOT_USB_DFU_GPIO)) + defined(CONFIG_BOOT_USB_DFU_GPIO) || \ + defined(CONFIG_BOOT_USB_DFU_BOOT_MODE)) #define MCUBOOT_USB_DFU #endif diff --git a/boot/zephyr/io.c b/boot/zephyr/io.c index 1b156221b7..4a58e26f70 100644 --- a/boot/zephyr/io.c +++ b/boot/zephyr/io.c @@ -36,7 +36,8 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include #endif -#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) +#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) \ + || defined(CONFIG_BOOT_USB_DFU_BOOT_MODE) #include #endif @@ -197,7 +198,8 @@ bool io_detect_pin_reset(void) } #endif -#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) +#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) \ + || defined(CONFIG_BOOT_USB_DFU_BOOT_MODE) bool io_detect_boot_mode(void) { int32_t boot_mode; diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 9dc279960a..69fe68fc5f 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -52,7 +52,8 @@ const struct boot_uart_funcs boot_funcs = { }; #endif -#if defined(CONFIG_BOOT_USB_DFU_WAIT) || defined(CONFIG_BOOT_USB_DFU_GPIO) +#if defined(CONFIG_BOOT_USB_DFU_WAIT) || defined(CONFIG_BOOT_USB_DFU_GPIO) \ + || defined(CONFIG_BOOT_USB_DFU_BOOT_MODE) #include #endif @@ -187,7 +188,8 @@ int main(void) { struct boot_rsp rsp; int rc; -#if defined(CONFIG_BOOT_USB_DFU_GPIO) || defined(CONFIG_BOOT_USB_DFU_WAIT) +#if defined(CONFIG_BOOT_USB_DFU_GPIO) || defined(CONFIG_BOOT_USB_DFU_WAIT) || \ + defined(CONFIG_BOOT_USB_DFU_BOOT_MODE) bool usb_dfu_requested = false; bool usb_dfu_forever = false; #endif @@ -258,7 +260,24 @@ int main(void) usb_dfu_requested = true; #endif -#if defined(CONFIG_BOOT_USB_DFU_GPIO) || defined(CONFIG_BOOT_USB_DFU_WAIT) +#if defined(CONFIG_BOOT_USB_DFU_BOOT_MODE) + BOOT_LOG_DBG("Checking boot mode for USB DFU request"); + if (io_detect_boot_mode()) { + BOOT_LOG_DBG("Staying in USB DFU"); + + usb_dfu_requested = true; + usb_dfu_forever = true; + +#ifdef CONFIG_MCUBOOT_INDICATION_LED + io_led_set(1); +#endif + + mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_ENTERED); + } +#endif + +#if defined(CONFIG_BOOT_USB_DFU_GPIO) || defined(CONFIG_BOOT_USB_DFU_WAIT) || \ + defined(CONFIG_BOOT_USB_DFU_BOOT_MODE) if (usb_dfu_requested) { rc = usb_enable(NULL); if (rc) {