Skip to content

Commit 67bec6b

Browse files
committed
samples: usb: add sample for the new USB DFU implementation
The sample defines an image that uses RAMdisk and also provides an option to enable USB DFU flash backend for the "slot-1" flash partition. Assuming the user runs this sample from the slot-0 partition, uploading to flash should work fine for evaluation purposes. If the sample is built with CONFIG_BOOTLOADER_MCUBOOT=y, the sample will mark the image in slot 1 as pending after an image download. Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
1 parent 321e5ab commit 67bec6b

File tree

8 files changed

+530
-2
lines changed

8 files changed

+530
-2
lines changed

samples/subsys/usb/common/sample_usbd_init.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ LOG_MODULE_REGISTER(usbd_sample_config);
1515

1616
#define ZEPHYR_PROJECT_USB_VID 0x2fe3
1717

18+
/* By default, do not register the USB DFU class DFU mode instance. */
19+
static const char *const blocklist[] = {
20+
"dfu_dfu",
21+
NULL,
22+
};
23+
1824
/* doc device instantiation start */
1925
/*
2026
* Instantiate a context named sample_usbd using the default USB device
@@ -125,7 +131,7 @@ struct usbd_context *sample_usbd_setup_device(usbd_msg_cb_t msg_cb)
125131
}
126132

127133
err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_HS, 1,
128-
NULL);
134+
blocklist);
129135
if (err) {
130136
LOG_ERR("Failed to add register classes");
131137
return NULL;
@@ -144,7 +150,7 @@ struct usbd_context *sample_usbd_setup_device(usbd_msg_cb_t msg_cb)
144150
/* doc configuration register end */
145151

146152
/* doc functions register start */
147-
err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_FS, 1, NULL);
153+
err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_FS, 1, blocklist);
148154
if (err) {
149155
LOG_ERR("Failed to add register classes");
150156
return NULL;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(usb-dfu)
6+
7+
include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
8+
FILE(GLOB app_sources src/*.c)
9+
target_sources(app PRIVATE ${app_sources})

samples/subsys/usb/dfu-next/Kconfig

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright (c) 2023 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
menu "USB DFU sample options"
5+
6+
config APP_USB_DFU_USE_FLASH_BACKEND
7+
select FLASH
8+
select FLASH_MAP
9+
select STREAM_FLASH
10+
select IMG_MANAGER
11+
select IMG_ERASE_PROGRESSIVELY
12+
bool "Option to clear the flash area before mounting"
13+
help
14+
Use this to force an existing file system to be created.
15+
16+
if APP_USB_DFU_USE_FLASH_BACKEND
17+
18+
config USBD_DFU_FLASH
19+
default y
20+
21+
config USBD_DFU_FLASH_SLOT0
22+
default n
23+
24+
config USBD_DFU_FLASH_SLOT1
25+
default y
26+
27+
endif
28+
29+
endmenu
30+
31+
# Source common USB sample options used to initialize new experimental USB
32+
# device stack. The scope of these options is limited to USB samples in project
33+
# tree, you cannot use them in your own application.
34+
source "samples/subsys/usb/common/Kconfig.sample_usbd"
35+
36+
source "Kconfig.zephyr"
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
.. zephyr:code-sample:: dfu-next
2+
:name: USB DFU
3+
:relevant-api: usbd_api usbd_dfu
4+
5+
Implement a basic USB DFU device
6+
7+
Overview
8+
********
9+
10+
This sample application demonstrates the USB DFU implementation using the
11+
new experimental USB device stack.
12+
13+
Requirements
14+
************
15+
16+
This project requires an experimental USB device driver (UDC API) and uses the
17+
:ref:`disk_access_api` and RAM-disk to download/upload the image.
18+
19+
Building and Running
20+
********************
21+
22+
This sample can be built for multiple boards, in this example we will build it
23+
for the reel board:
24+
25+
.. zephyr-app-commands::
26+
:zephyr-app: samples/subsys/usb/dfu-next
27+
:board: reel_board
28+
:goals: build flash
29+
:compact:
30+
31+
`dfu-util`_ tool can be used to download or upload the images. There are two
32+
modes of operation in the USB DFU, runtime and DFU. The example starts in
33+
runtime mode. To switch to DFU mode without uploading or downloading, the
34+
following command can be used:
35+
36+
.. code-block:: console
37+
38+
dfu-util --detach
39+
40+
Use the following command to upload the ``ramdisk0`` image to the host:
41+
42+
.. code-block:: console
43+
44+
dfu-util --alt 0 --upload ramdisk0_backup.bin
45+
46+
Use the following command to download the ``ramdisk0`` image to the device:
47+
48+
.. code-block:: console
49+
50+
dfu-util --alt 0 --download ramdisk0_backup.bin
51+
52+
Building with flash backend enabled
53+
***********************************
54+
55+
The USB DFU device support has a built-in flash backend. This backend uses
56+
:ref:`flash_img_api` and :ref:`flash_map_api` to write or read flash image, the
57+
implementation is similar to the one we had in the previous USB DFU device
58+
example.
59+
60+
To use flash backend set the :kconfig:option:`CONFIG_APP_USB_DFU_USE_FLASH_BACKEND`.
61+
An additional interface will be available in DFU mode to upload/download the
62+
SLOT-1 image.
63+
64+
It is also possible to try the sample together with the MCUboot bootloader
65+
library. The following example shows how to build MCUboot and this sample with
66+
flash backend and MCUboot support enabled using the :ref:`sysbuild`:
67+
68+
.. zephyr-app-commands::
69+
:tool: west
70+
:zephyr-app: samples/subsys/usb/dfu-next
71+
:board: reel_board
72+
:goals: build flash
73+
:west-args: --sysbuild
74+
:gen-args: -DSB_CONFIG_BOOTLOADER_MCUBOOT=y -DCONFIG_APP_USB_DFU_USE_FLASH_BACKEND=y
75+
76+
Another application image is required to be used as a firmware update and
77+
downloaded to SLOT-1. Build and sign a second application image e.g.
78+
:zephyr:code-sample:`hello_world`, which will be used as an image for the
79+
update. Do not forget to enable the required :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT`
80+
option (as described in :ref:`mcuboot`). For example:
81+
82+
.. zephyr-app-commands::
83+
:app: zephyr/samples/hello_world
84+
:board: reel_board
85+
:gen-args: -DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE=\"bootloader/mcuboot/root-rsa-2048.pem\" -DCONFIG_BOOTLOADER_MCUBOOT=y
86+
:goals: flash
87+
88+
Use the following command to download new image to the device:
89+
90+
.. code-block:: console
91+
92+
dfu-util --alt 1 --download build/zephyr/zephyr.signed.bin
93+
94+
Reset the SoC. MCUboot boot will swap the images and boot the new application,
95+
showing this output to the console:
96+
97+
.. code-block:: console
98+
99+
*** Booting MCUboot v2.1.0-rc1-134-gb9d69dd2a2d6 ***
100+
*** Using Zephyr OS build v3.7.0-4345-ga5d0d8533a41 ***
101+
I: Starting bootloader
102+
I: Primary image: magic=good, swap_type=0x4, copy_done=0x1, image_ok=0x1
103+
I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3
104+
I: Boot source: none
105+
I: Image index: 0, Swap type: test
106+
I: Starting swap using move algorithm.
107+
I: Bootloader chainload address offset: 0xc000
108+
I: Image version: v0.0.0
109+
I: Jumping to the first image slot
110+
*** Booting Zephyr OS build v3.7.0-4345-ga5d0d8533a41 ***
111+
Hello World! reel_board@1/nrf52840
112+
113+
114+
Reset the SoC again and MCUboot should revert the images and boot
115+
USB DFU sample, showing this output to the console:
116+
117+
.. code-block:: console
118+
119+
*** Booting MCUboot v2.1.0-rc1-134-gb9d69dd2a2d6 ***
120+
*** Using Zephyr OS build v3.7.0-4345-ga5d0d8533a41 ***
121+
I: Starting bootloader
122+
I: Primary image: magic=good, swap_type=0x2, copy_done=0x1, image_ok=0x3
123+
I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
124+
I: Boot source: none
125+
I: Image index: 0, Swap type: revert
126+
I: Starting swap using move algorithm.
127+
I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
128+
I: Bootloader chainload address offset: 0xc000
129+
I: Image version: v0.0.0
130+
I: Jumping to the first image slot
131+
*** Booting Zephyr OS build v3.7.0-4345-ga5d0d8533a41 ***
132+
[00:00:00.000,335] <inf> main: USBD message: VBUS ready
133+
[00:00:00.000,427] <inf> main: USB DFU sample is initialized
134+
135+
136+
.. _dfu-util: https://dfu-util.sourceforge.net/
137+
.. _Using MCUboot with Zephyr: https://docs.mcuboot.com/readme-zephyr
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
ramdisk0 {
9+
compatible = "zephyr,ram-disk";
10+
disk-name = "image0";
11+
sector-size = <512>;
12+
sector-count = <32>;
13+
};
14+
};

samples/subsys/usb/dfu-next/prj.conf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CONFIG_USB_DEVICE_STACK_NEXT=y
2+
CONFIG_USBD_DFU=y
3+
4+
CONFIG_LOG=y
5+
CONFIG_USBD_LOG_LEVEL_WRN=y
6+
CONFIG_USBD_DFU_LOG_LEVEL_WRN=y
7+
CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y
8+
CONFIG_SAMPLE_USBD_PID=0x0005
9+
10+
CONFIG_DISK_ACCESS=y
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
sample:
2+
name: USB DFU sample
3+
common:
4+
min_ram: 64
5+
depends_on:
6+
- usbd
7+
tests:
8+
sample.usbd.dfu:
9+
integration_platforms:
10+
- nrf52840dk/nrf52840
11+
- nrf54h20dk/nrf54h20/cpuapp
12+
- frdm_k64f
13+
- stm32f723e_disco
14+
- nucleo_f413zh
15+
- mimxrt685_evk/mimxrt685s/cm33
16+
- mimxrt1060_evk/mimxrt1062/qspi
17+
tags: usb
18+
sample.usbd.dfu-flash:
19+
platform_allow:
20+
- nrf52840dk/nrf52840
21+
- frdm_k64f
22+
min_flash: 1024
23+
tags: usb
24+
extra_configs:
25+
- CONFIG_APP_USB_DFU_USE_FLASH_BACKEND=y

0 commit comments

Comments
 (0)