summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2026-02-05 20:39:38 +0800
committersakumisu <[email protected]>2026-02-05 20:39:38 +0800
commit6b0ec0e16f82c4b869ccc373a2a284b3a4085115 (patch)
tree5236f72cc570754d83468eef68cf4ebd51641727
parent1a5bc9d1503f19eefa6b53787f1e7fec43946c30 (diff)
refactor(class/dfu): refactor dfu device driver
Signed-off-by: sakumisu <[email protected]>
-rw-r--r--Kconfig4
-rw-r--r--Kconfig.rtt4
-rw-r--r--Kconfig.rttpkg4
-rw-r--r--README.md1
-rw-r--r--README_zh.md1
-rw-r--r--SConscript2
-rw-r--r--class/dfu/usb_dfu.h57
-rw-r--r--class/dfu/usbd_dfu.c688
-rw-r--r--class/dfu/usbd_dfu.h14
-rw-r--r--demo/dfu_st_cubemx_main.c372
-rw-r--r--demo/dfu_template.c (renamed from demo/dfu_with_st_tool_template.c)62
-rw-r--r--tools/dfu-util/url3
-rw-r--r--tools/stm32_dfuse/url1
13 files changed, 370 insertions, 843 deletions
diff --git a/Kconfig b/Kconfig
index 6d4b0f76..39fb6ff4 100644
--- a/Kconfig
+++ b/Kconfig
@@ -211,6 +211,10 @@ if CHERRYUSB
bool
prompt "cdc_ncm"
depends on CHERRYUSB_DEVICE_CDC_NCM
+ config CHERRYUSB_DEVICE_TEMPLATE_DFU
+ bool
+ prompt "dfu"
+ depends on CHERRYUSB_DEVICE_DFU
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool
prompt "cdc_acm_msc"
diff --git a/Kconfig.rtt b/Kconfig.rtt
index 769bfb95..162af731 100644
--- a/Kconfig.rtt
+++ b/Kconfig.rtt
@@ -221,6 +221,10 @@ if RT_USING_CHERRYUSB
bool
prompt "cdc_ncm"
depends on RT_CHERRYUSB_DEVICE_CDC_NCM
+ config RT_CHERRYUSB_DEVICE_TEMPLATE_DFU
+ bool
+ prompt "dfu"
+ depends on RT_CHERRYUSB_DEVICE_DFU
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool
prompt "cdc_acm_msc"
diff --git a/Kconfig.rttpkg b/Kconfig.rttpkg
index 9f0e6834..4583fd09 100644
--- a/Kconfig.rttpkg
+++ b/Kconfig.rttpkg
@@ -220,6 +220,10 @@ if PKG_USING_CHERRYUSB
bool
prompt "cdc_ncm"
depends on PKG_CHERRYUSB_DEVICE_CDC_NCM
+ config PKG_CHERRYUSB_DEVICE_TEMPLATE_DFU
+ bool
+ prompt "dfu"
+ depends on PKG_CHERRYUSB_DEVICE_DFU
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool
prompt "cdc_acm_msc"
diff --git a/README.md b/README.md
index 24b55277..51a59960 100644
--- a/README.md
+++ b/README.md
@@ -93,6 +93,7 @@ CherryUSB Device Stack resource usage (GCC 10.2 with -O2, disable log):
|usbd_rndis.c | ~2500 | 2 * 1580(default)+156+8 | 80 | 0 |
|usbd_cdc_ecm.c | ~900 | 2 * 1514(default)+16 | 42 | 0 |
|usbd_mtp.c | ~9000 | 2048(default)+128 | sizeof(struct mtp_object) * n| 0 |
+|usbd_dfu.c | ~2200 | 0 | 45 | 0 |
## Host Stack Overview
diff --git a/README_zh.md b/README_zh.md
index b4b60472..53f225f5 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -93,6 +93,7 @@ CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|usbd_rndis.c | ~2500 | 2 * 1580(default)+156+8 | 80 | 0 |
|usbd_cdc_ecm.c | ~900 | 2 * 1514(default)+16 | 42 | 0 |
|usbd_mtp.c | ~9000 | 2048(default)+128 | sizeof(struct mtp_object) * n| 0 |
+|usbd_dfu.c | ~2200 | 0 | 45 | 0 |
## Host 协议栈简介
diff --git a/SConscript b/SConscript
index 6f24f2b1..eafc5722 100644
--- a/SConscript
+++ b/SConscript
@@ -165,6 +165,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('demo/cdc_ecm_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM']):
src += Glob('demo/cdc_ncm_template.c')
+ if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_DFU']):
+ src += Glob('demo/dfu_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC']):
src += Glob('demo/cdc_acm_msc_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID']):
diff --git a/class/dfu/usb_dfu.h b/class/dfu/usb_dfu.h
index f1ccba88..fd106960 100644
--- a/class/dfu/usb_dfu.h
+++ b/class/dfu/usb_dfu.h
@@ -23,7 +23,7 @@
#define DFU_PROTOCOL_RUNTIME 0x01
/** DFU Class DFU mode Protocol */
-#define DFU_PROTOCOL_MODE 0x02
+#define DFU_PROTOCOL_DFU 0x02
/**
* @brief DFU Class Specific Requests
@@ -76,21 +76,23 @@
#define DFU_STATE_DFU_UPLOAD_IDLE 9U
#define DFU_STATE_DFU_ERROR 10U
-/** DFU Manifestation State */
-#define DFU_MANIFEST_COMPLETE 0U
-#define DFU_MANIFEST_IN_PROGRESS 1U
+/* Define DFU application notification signals. */
+#define DFU_NOTIFICATION_BEGIN_DOWNLOAD 0x1u
+#define DFU_NOTIFICATION_END_DOWNLOAD 0x2u
+#define DFU_NOTIFICATION_ABORT_DOWNLOAD 0x3u
+#define DFU_NOTIFICATION_BEGIN_UPLOAD 0x5u
+#define DFU_NOTIFICATION_END_UPLOAD 0x6u
+#define DFU_NOTIFICATION_ABORT_UPLOAD 0x7u
-/** Special Commands with Download Request */
-#define DFU_CMD_GETCOMMANDS 0U
-#define DFU_CMD_SETADDRESSPOINTER 0x21U
-#define DFU_CMD_ERASE 0x41U
-#define DFU_MEDIA_ERASE 0x00U
-#define DFU_MEDIA_PROGRAM 0x01U
+/* Define DFU application notification signals. */
+#define DFU_MEDIA_STATUS_OK 0
+#define DFU_MEDIA_STATUS_BUSY 1
+#define DFU_MEDIA_STATUS_ERROR 2
-/** Other defines */
-/* Bit Detach capable = bit 3 in bmAttributes field */
-#define DFU_DETACH_MASK (1U << 3)
-#define DFU_MANIFEST_MASK (1U << 2)
+/** Special Commands with Download Request for STM32, wValue = 0 */
+#define DFU_SPECIAL_CMD_SET_ADDRESS_POINTER 0x21U
+#define DFU_SPECIAL_CMD_ERASE 0x41U
+#define DFU_SPECIAL_READ_UNPROTECT 0x92U
/** Run-Time Functional Descriptor */
struct dfu_runtime_descriptor {
@@ -103,35 +105,36 @@ struct dfu_runtime_descriptor {
} __PACKED;
/**\brief Payload packet to response in DFU_GETSTATUS request */
-struct dfu_info {
- uint8_t bStatus; /**<\brief An indication of the status resulting from the
+struct dfu_status {
+ uint8_t bStatus; /**<\brief An indication of the status resulting from the
* execution of the most recent request.*/
- uint8_t bPollTimeout; /**<\brief Minimum time (LSB) in ms, that the host should wait
+ uint32_t bwPollTimeout; /**<\brief Minimum time in ms, that the host should wait
* before sending a subsequent DFU_GETSTATUS request.*/
- uint16_t wPollTimeout; /**<\brief Minimum time (MSB) in ms, that the host should wait
- * before sending a subsequent DFU_GETSTATUS request.*/
- uint8_t bState; /**<\brief An indication of the state that the device is going
+ uint8_t bState; /**<\brief An indication of the state that the device is going
* to enter immediately following transmission of this response.*/
- uint8_t iString; /**<\brief Index of the status string descriptor.*/
+ uint8_t iString; /**<\brief Index of the status string descriptor.*/
};
+#define DFU_DESCRIPTOR_LEN 18
+
// clang-format off
-#define DFU_DESCRIPTOR_INIT() \
+#define DFU_DESCRIPTOR_INIT(str_idx) \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x00, /* bNumEndpoints Default Control Pipe only */ \
USB_DEVICE_CLASS_APP_SPECIFIC, /* bInterfaceClass */ \
- 0x01, /* bInterfaceSubClass Device Firmware Upgrade */ \
- 0x02, /* bInterfaceProtocol DFU mode */ \
- 0x04, /* iInterface */ /*!< Device Firmware Update Functional Descriptor */ \
+ DFU_SUBCLASS_DFU, /* bInterfaceSubClass Device Firmware Upgrade */ \
+ DFU_PROTOCOL_DFU, /* bInterfaceProtocol DFU mode */ \
+ str_idx, /* iInterface */ \
+ /*!< Device Firmware Update Functional Descriptor */ \
0x09, /* bLength */ \
0x21, /* DFU Functional Descriptor */ \
0x0B, /* bmAttributes */ \
WBVAL(0x00ff), /* wDetachTimeOut */ \
- WBVAL(USBD_DFU_XFER_SIZE), /* wTransferSize */ \
- WBVAL(0x011a) /* bcdDFUVersion */
+ WBVAL(CONFIG_USBDEV_REQUEST_BUFFER_LEN), /* wTransferSize */ \
+ WBVAL(DFU_VERSION) /* bcdDFUVersion */
// clang-format on
#endif /* USB_DFU_H */
diff --git a/class/dfu/usbd_dfu.c b/class/dfu/usbd_dfu.c
index 2da38288..a49827d1 100644
--- a/class/dfu/usbd_dfu.c
+++ b/class/dfu/usbd_dfu.c
@@ -1,465 +1,289 @@
/*
- * Copyright (c) 2022, sakumisu
+ * Copyright (c) 2022 ~ 2026, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_dfu.h"
-/** Modify the following three parameters according to different platforms */
-#ifndef USBD_DFU_XFER_SIZE
-#define USBD_DFU_XFER_SIZE 1024
-#endif
-
-#ifndef USBD_DFU_APP_DEFAULT_ADD
-#define USBD_DFU_APP_DEFAULT_ADD 0x8004000
-#endif
-
-#ifndef FLASH_PROGRAM_TIME
-#define FLASH_PROGRAM_TIME 50
-#endif
-
-#ifndef FLASH_ERASE_TIME
-#define FLASH_ERASE_TIME 50
-#endif
-
struct usbd_dfu_priv {
- struct dfu_info info;
- union {
- uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
- uint8_t d8[USBD_DFU_XFER_SIZE];
- } buffer;
-
- uint32_t wblock_num;
- uint32_t wlength;
- uint32_t data_ptr;
- uint32_t alt_setting;
-
- uint8_t dev_status[6];
- uint8_t ReservedForAlign[2];
- uint8_t dev_state;
- uint8_t manif_state;
- uint8_t firmwar_flag;
+ uint8_t dfu_state;
} g_usbd_dfu;
-static void dfu_reset(void)
-{
- memset(&g_usbd_dfu, 0, sizeof(g_usbd_dfu));
+const char *usbd_dfu_state_string[] = {
+ "APP_IDLE",
+ "APP_DETACH",
+ "DFU_IDLE",
+ "DFU_DNLOAD_SYNC",
+ "DFU_DNLOAD_BUSY",
+ "DFU_DNLOAD_IDLE",
+ "DFU_MANIFEST_SYNC",
+ "DFU_MANIFEST",
+ "DFU_MANIFEST_WAIT_RESET",
+ "DFU_UPLOAD_IDLE",
+ "DFU_ERROR"
+};
- g_usbd_dfu.alt_setting = 0U;
- g_usbd_dfu.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
- g_usbd_dfu.wblock_num = 0U;
- g_usbd_dfu.wlength = 0U;
+static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("DFU Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
- g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
- g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
+ USB_LOG_DBG("dfu state:%s\r\n", usbd_dfu_state_string[g_usbd_dfu.dfu_state]);
- g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = DFU_STATE_DFU_IDLE;
- g_usbd_dfu.dev_status[5] = 0U;
-}
+ switch (g_usbd_dfu.dfu_state) {
+ case DFU_STATE_APP_IDLE:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_DETACH:
+ break;
+ case DFU_REQUEST_GETSTATUS:
+ (*data)[0] = DFU_STATUS_OK; /* bStatus */
+ (*data)[1] = 0;
+ (*data)[2] = 0;
+ (*data)[3] = 0;
+ (*data)[4] = g_usbd_dfu.dfu_state;
+ (*data)[5] = 0; /* iString */
+ *len = 6;
+ break;
+ case DFU_REQUEST_GETSTATE:
+ (*data)[0] = g_usbd_dfu.dfu_state;
+ *len = 1;
+ break;
-static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
-{
- switch (cmd) {
- case DFU_MEDIA_PROGRAM:
- buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;
- buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);
- buffer[3] = 0;
+ default:
+ return -1;
+ }
break;
+ case DFU_STATE_APP_DETACH:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_GETSTATUS:
+ (*data)[0] = DFU_STATUS_OK; /* bStatus */
+ (*data)[1] = 0;
+ (*data)[2] = 0;
+ (*data)[3] = 0;
+ (*data)[4] = g_usbd_dfu.dfu_state;
+ (*data)[5] = 0; /* iString */
+ *len = 6;
+ break;
+ case DFU_REQUEST_GETSTATE:
+ (*data)[0] = g_usbd_dfu.dfu_state;
+ *len = 1;
+ break;
- case DFU_MEDIA_ERASE:
- buffer[1] = (uint8_t)FLASH_ERASE_TIME;
- buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
- buffer[3] = 0;
- default:
-
+ default:
+ return -1;
+ }
break;
- }
- return (0);
-}
-
-static void dfu_request_detach(void)
-{
- if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
- (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
- (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
- (g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
- (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
- /* Update the state machine */
- g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
- g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- g_usbd_dfu.dev_status[5] = 0U; /*iString*/
- g_usbd_dfu.wblock_num = 0U;
- g_usbd_dfu.wlength = 0U;
- }
-}
-
-static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
- struct usb_setup_packet *req = setup;
- uint32_t addr;
- /* Data setup request */
- if (req->wLength > 0U) {
- if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
- /* Update the global length and block number */
- g_usbd_dfu.wblock_num = req->wValue;
- g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
-
- /* DFU Get Command */
- if (g_usbd_dfu.wblock_num == 0U) {
- /* Update the state machine */
- g_usbd_dfu.dev_state = (g_usbd_dfu.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
+ case DFU_STATE_DFU_IDLE:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_DNLOAD:
+ /* We received a DOWNLOAD command. Check the length field of the request. If it is 0,
+ we are done with the transfer. */
+ if (setup->wLength == 0) {
+ usbd_dfu_end_load();
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_SYNC;
+ } else {
+ usbd_dfu_begin_load();
+ if (usbd_dfu_write(setup->wValue, *data, setup->wLength) < 0) {
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
+ return -1;
+ } else {
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_SYNC;
+ }
+ }
+ break;
+ case DFU_REQUEST_UPLOAD:
+ usbd_dfu_begin_load();
- /* Store the values of all supported commands */
- g_usbd_dfu.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
- g_usbd_dfu.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
- g_usbd_dfu.buffer.d8[2] = DFU_CMD_ERASE;
+ uint16_t actual_length;
+ if (usbd_dfu_read(setup->wValue, *data, setup->wLength, &actual_length) < 0) {
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
+ return -1;
+ } else {
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_UPLOAD_IDLE;
+ }
+ break;
+ case DFU_REQUEST_ABORT:
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+ break;
+ case DFU_REQUEST_GETSTATUS:
+ (*data)[0] = DFU_STATUS_OK; /* bStatus */
+ (*data)[1] = 0;
+ (*data)[2] = 0;
+ (*data)[3] = 0;
+ (*data)[4] = g_usbd_dfu.dfu_state;
+ (*data)[5] = 0; /* iString */
+ *len = 6;
+ break;
+ case DFU_REQUEST_GETSTATE:
+ (*data)[0] = g_usbd_dfu.dfu_state;
+ *len = 1;
+ break;
- /* Send the status data over EP0 */
- memcpy(*data, g_usbd_dfu.buffer.d8, 3);
- *len = 3;
- } else if (g_usbd_dfu.wblock_num > 1U) {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-
- addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
-
- /* Return the physical address where data are stored */
- dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
-
- /* Send the status data over EP0 */
- memcpy(*data, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
- *len = g_usbd_dfu.wlength;
- } else /* unsupported g_usbd_dfu.wblock_num */
- {
- g_usbd_dfu.dev_state = DFU_STATUS_ERR_STALLEDPKT;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-
- /* Call the error management function (command will be NAKed */
- USB_LOG_ERR("Dfu_request_upload unsupported g_usbd_dfu.wblock_num\r\n");
+ default:
+ return -1;
}
- }
- /* Unsupported state */
- else {
- g_usbd_dfu.wlength = 0U;
- g_usbd_dfu.wblock_num = 0U;
-
- /* Call the error management function (command will be NAKed */
- USB_LOG_ERR("Dfu_request_upload unsupported state\r\n");
- }
- }
- /* No Data setup request */
- else {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- }
-}
-
-static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
- /* Data setup request */
- struct usb_setup_packet *req = setup;
- if (req->wLength > 0U) {
- if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
- /* Update the global length and block number */
- g_usbd_dfu.wblock_num = req->wValue;
- g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
-
- /* Update the state machine */
- g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
-
- /*!< Data has received complete */
- memcpy((uint8_t *)g_usbd_dfu.buffer.d8, (uint8_t *)*data, g_usbd_dfu.wlength);
- /*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
- g_usbd_dfu.firmwar_flag = 1;
- }
- /* Unsupported state */
- else {
- USB_LOG_ERR("Dfu_request_dnload unsupported state\r\n");
- }
- }
- /* 0 Data DNLOAD request */
- else {
- /* End of DNLOAD operation*/
- if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE)) {
- g_usbd_dfu.manif_state = DFU_MANIFEST_IN_PROGRESS;
- g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- } else {
- /* Call the error management function (command will be NAKed */
- USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", g_usbd_dfu.dev_state);
- }
- }
-}
+ break;
+ case DFU_STATE_DFU_DNLOAD_SYNC:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_GETSTATUS:
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_BUSY;
-static int8_t dfu_getstatus_special_handler(void)
-{
- uint32_t addr;
- if (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
- /* Decode the Special Command */
- if (g_usbd_dfu.wblock_num == 0U) {
- if (g_usbd_dfu.wlength == 1U) {
- if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
- /* Nothing to do */
- }
- } else if (g_usbd_dfu.wlength == 5U) {
- if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
- g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
- g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
- g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
- g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
- } else if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE) {
- g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
- g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
- g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
- g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
+ (*data)[0] = DFU_STATUS_OK; /* bStatus */
+ (*data)[1] = 0;
+ (*data)[2] = 0;
+ (*data)[3] = 0;
+ (*data)[4] = g_usbd_dfu.dfu_state;
+ (*data)[5] = 0; /* iString */
+ *len = 6;
+ break;
+ case DFU_REQUEST_GETSTATE:
+ (*data)[0] = g_usbd_dfu.dfu_state;
+ *len = 1;
+ break;
- USB_LOG_DBG("Erase start add %08x \r\n", g_usbd_dfu.data_ptr);
- /*!< Erase */
- dfu_erase_flash(g_usbd_dfu.data_ptr);
- } else {
+ default:
return -1;
- }
- } else {
- /* Reset the global length and block number */
- g_usbd_dfu.wlength = 0U;
- g_usbd_dfu.wblock_num = 0U;
- /* Call the error management function (command will be NAKed) */
- USB_LOG_ERR("Reset the global length and block number\r\n");
}
- }
- /* Regular Download Command */
- else {
- if (g_usbd_dfu.wblock_num > 1U) {
- /* Decode the required address */
- addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
-
- /* Perform the write operation */
- /* Write flash */
- USB_LOG_DBG("Write start add %08x length %d\r\n", addr, g_usbd_dfu.wlength);
- dfu_write_flash(g_usbd_dfu.buffer.d8, (uint8_t *)addr, g_usbd_dfu.wlength);
- }
- }
-
- /* Reset the global length and block number */
- g_usbd_dfu.wlength = 0U;
- g_usbd_dfu.wblock_num = 0U;
-
- /* Update the state machine */
- g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- }
- return 0;
-}
-
-static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
- /*!< Determine whether to leave DFU mode */
- if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS &&
- g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
- g_usbd_dfu.dev_status[1] == 0U &&
- g_usbd_dfu.dev_status[2] == 0U &&
- g_usbd_dfu.dev_status[3] == 0U &&
- g_usbd_dfu.dev_status[4] == g_usbd_dfu.dev_state) {
- g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
-
- if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- return;
- } else {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- /* Generate system reset to allow jumping to the user code */
- dfu_leave();
- }
- }
-
- switch (g_usbd_dfu.dev_state) {
- case DFU_STATE_DFU_DNLOAD_SYNC:
- if (g_usbd_dfu.wlength != 0U) {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
+ break;
+ case DFU_STATE_DFU_DNLOAD_BUSY:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_GETSTATUS:
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_IDLE;
- if ((g_usbd_dfu.wblock_num == 0U) && (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE)) {
- dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_ERASE, g_usbd_dfu.dev_status);
- } else {
- dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_PROGRAM, g_usbd_dfu.dev_status);
- }
- } else /* (g_usbd_dfu.wlength==0)*/
- {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
+ (*data)[0] = DFU_STATUS_OK; /* bStatus */
+ (*data)[1] = 0;
+ (*data)[2] = 0;
+ (*data)[3] = 0;
+ (*data)[4] = g_usbd_dfu.dfu_state;
+ (*data)[5] = 0; /* iString */
+ *len = 6;
+ break;
+ case DFU_REQUEST_GETSTATE:
+ (*data)[0] = g_usbd_dfu.dfu_state;
+ *len = 1;
+ break;
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
+ default:
+ return -1;
}
break;
+ case DFU_STATE_DFU_DNLOAD_IDLE:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_DNLOAD:
+ /* We received a DOWNLOAD command. Check the length field of the request. If it is 0,
+ we are done with the transfer. */
+ if (setup->wLength == 0) {
+ usbd_dfu_end_load();
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_SYNC;
+ } else {
+ if (usbd_dfu_write(setup->wValue, *data, setup->wLength) < 0) {
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
+ return -1;
+ } else {
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_SYNC;
+ }
+ }
- case DFU_STATE_DFU_MANIFEST_SYNC:
- if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS) {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST;
+ break;
+ case DFU_REQUEST_ABORT:
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+ break;
+ case DFU_REQUEST_GETSTATUS:
+ (*data)[0] = DFU_STATUS_OK; /* bStatus */
+ (*data)[1] = 0;
+ (*data)[2] = 0;
+ (*data)[3] = 0;
+ (*data)[4] = g_usbd_dfu.dfu_state;
+ (*data)[5] = 0; /* iString */
+ *len = 6;
+ break;
+ case DFU_REQUEST_GETSTATE:
+ (*data)[0] = g_usbd_dfu.dfu_state;
+ *len = 1;
+ break;
- g_usbd_dfu.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- } else {
- if ((g_usbd_dfu.manif_state == DFU_MANIFEST_COMPLETE) &&
- ((0x0B & DFU_MANIFEST_MASK) != 0U)) {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
-
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U;
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- }
+ default:
+ return -1;
}
break;
+ case DFU_STATE_DFU_UPLOAD_IDLE:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_UPLOAD: {
+ uint16_t actual_length;
+ if (usbd_dfu_read(setup->wValue, *data, setup->wLength, &actual_length) < 0) {
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
+ return -1;
+ } else {
+ if (actual_length < setup->wLength) {
+ usbd_dfu_end_load();
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+ } else {
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_UPLOAD_IDLE;
+ }
+ }
+ } break;
+ case DFU_REQUEST_ABORT:
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+ break;
+ case DFU_REQUEST_GETSTATUS:
+ (*data)[0] = DFU_STATUS_OK; /* bStatus */
+ (*data)[1] = 0;
+ (*data)[2] = 0;
+ (*data)[3] = 0;
+ (*data)[4] = g_usbd_dfu.dfu_state;
+ (*data)[5] = 0; /* iString */
+ *len = 6;
+ break;
+ case DFU_REQUEST_GETSTATE:
+ (*data)[0] = g_usbd_dfu.dfu_state;
+ *len = 1;
+ break;
- default:
+ default:
+ return -1;
+ }
break;
- }
+ case DFU_STATE_DFU_MANIFEST_SYNC:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_GETSTATUS:
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
- /* Send the status data over EP0 */
- memcpy(*data, g_usbd_dfu.dev_status, 6);
- *len = 6;
+ (*data)[0] = DFU_STATUS_OK; /* bStatus */
+ (*data)[1] = 0;
+ (*data)[2] = 0;
+ (*data)[3] = 0;
+ (*data)[4] = g_usbd_dfu.dfu_state;
+ (*data)[5] = 0; /* iString */
+ *len = 6;
- if (g_usbd_dfu.firmwar_flag == 1) {
- if (dfu_getstatus_special_handler() != 0) {
- USB_LOG_ERR("dfu_getstatus_special_handler error \r\n");
- }
- g_usbd_dfu.firmwar_flag = 0;
- }
-}
+ usbd_dfu_reset();
+ break;
+ case DFU_REQUEST_GETSTATE:
+ (*data)[0] = g_usbd_dfu.dfu_state;
+ *len = 1;
+ break;
-static void dfu_request_clrstatus(void)
-{
- if (g_usbd_dfu.dev_state == DFU_STATE_DFU_ERROR) {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
- g_usbd_dfu.dev_status[0] = DFU_STATUS_OK; /* bStatus */
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
- g_usbd_dfu.dev_status[5] = 0U; /* iString */
- } else {
- /* State Error */
- g_usbd_dfu.dev_state = DFU_STATE_DFU_ERROR;
- g_usbd_dfu.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
- g_usbd_dfu.dev_status[5] = 0U; /* iString */
- }
-}
-
-static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
- /* Return the current state of the DFU interface */
- (*data)[0] = g_usbd_dfu.dev_state;
- *len = 1;
-}
-
-void dfu_request_abort(void)
-{
- if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
- (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
- (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
- (g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
- (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
- g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
- g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
- g_usbd_dfu.dev_status[1] = 0U;
- g_usbd_dfu.dev_status[2] = 0U;
- g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
- g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
- g_usbd_dfu.dev_status[5] = 0U; /* iString */
- g_usbd_dfu.wblock_num = 0U;
- g_usbd_dfu.wlength = 0U;
- }
-}
-
-static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
-{
- USB_LOG_DBG("DFU Class request: "
- "bRequest 0x%02x\r\n",
- setup->bRequest);
-
- switch (setup->bRequest) {
- case DFU_REQUEST_DETACH:
- dfu_request_detach();
- break;
- case DFU_REQUEST_DNLOAD:
- dfu_request_dnload(setup, data, len);
- break;
- case DFU_REQUEST_UPLOAD:
- dfu_request_upload(setup, data, len);
- break;
- case DFU_REQUEST_GETSTATUS:
- dfu_request_getstatus(setup, data, len);
- break;
- case DFU_REQUEST_CLRSTATUS:
- dfu_request_clrstatus();
- break;
- case DFU_REQUEST_GETSTATE:
- dfu_request_getstate(setup, data, len);
+ default:
+ return -1;
+ }
break;
- case DFU_REQUEST_ABORT:
- dfu_request_abort();
+ case DFU_STATE_DFU_ERROR:
+ switch (setup->bRequest) {
+ case DFU_REQUEST_CLRSTATUS:
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
+ break;
+
+ default:
+ return -1;
+ }
break;
+
default:
- USB_LOG_WRN("Unhandled DFU Class bRequest 0x%02x\r\n", setup->bRequest);
+ USB_LOG_WRN("Invalid dfu state %s\r\n", usbd_dfu_state_string[g_usbd_dfu.dfu_state]);
return -1;
}
-
return 0;
}
@@ -467,7 +291,7 @@ static void dfu_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
- dfu_reset();
+ g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
break;
default:
break;
@@ -484,21 +308,29 @@ struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf)
return intf;
}
-__WEAK uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
+uint8_t usbd_dfu_get_state(void)
{
- return dest;
+ return g_usbd_dfu.dfu_state;
}
-__WEAK uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
+__WEAK void usbd_dfu_begin_load(void)
{
- return 0;
}
-__WEAK uint16_t dfu_erase_flash(uint32_t add)
+__WEAK void usbd_dfu_end_load(void)
{
- return 0;
}
-__WEAK void dfu_leave(void)
+__WEAK void usbd_dfu_reset(void)
{
}
+
+__WEAK int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length)
+{
+ return 0;
+}
+
+__WEAK int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length)
+{
+ return 0;
+} \ No newline at end of file
diff --git a/class/dfu/usbd_dfu.h b/class/dfu/usbd_dfu.h
index 9081d0dd..cec005c1 100644
--- a/class/dfu/usbd_dfu.h
+++ b/class/dfu/usbd_dfu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, sakumisu
+ * Copyright (c) 2022 ~ 2026, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,12 +14,14 @@ extern "C" {
/* Init dfu interface driver */
struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf);
+uint8_t usbd_dfu_get_state(void);
+
+void usbd_dfu_begin_load(void);
+void usbd_dfu_end_load(void);
+void usbd_dfu_reset(void);
+int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length);
+int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length);
-/* Interface functions that need to be implemented by the user */
-uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len);
-uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len);
-uint16_t dfu_erase_flash(uint32_t add);
-void dfu_leave(void);
#ifdef __cplusplus
}
#endif
diff --git a/demo/dfu_st_cubemx_main.c b/demo/dfu_st_cubemx_main.c
deleted file mode 100644
index b845af3e..00000000
--- a/demo/dfu_st_cubemx_main.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/* USER CODE BEGIN Header */
-/**
- ******************************************************************************
- * @file : main.c
- * @brief : Main program body
- ******************************************************************************
- * @attention
- *
- * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under Ultimate Liberty license
- * SLA0044, the "License"; You may not use this file except in compliance with
- * the License. You may obtain a copy of the License at:
- * www.st.com/SLA0044
- *
- ******************************************************************************
- */
-/* USER CODE END Header */
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-
-/* Private includes ----------------------------------------------------------*/
-/* USER CODE BEGIN Includes */
-#include "usbd_core.h"
-#include "usb_dfu.h"
-/* USER CODE END Includes */
-
-/* Private typedef -----------------------------------------------------------*/
-/* USER CODE BEGIN PTD */
-
-/* USER CODE END PTD */
-
-/* Private define ------------------------------------------------------------*/
-/* USER CODE BEGIN PD */
-/* USER CODE END PD */
-
-/* Private macro -------------------------------------------------------------*/
-/* USER CODE BEGIN PM */
-
-/* USER CODE END PM */
-
-/* Private variables ---------------------------------------------------------*/
-UART_HandleTypeDef huart1;
-
-PCD_HandleTypeDef hpcd_USB_FS;
-
-/* USER CODE BEGIN PV */
-
-/* USER CODE END PV */
-
-/* Private function prototypes -----------------------------------------------*/
-void SystemClock_Config(void);
-static void MX_GPIO_Init(void);
-static void MX_USART1_UART_Init(void);
-static void MX_USB_PCD_Init(void);
-/* USER CODE BEGIN PFP */
-typedef void (*pFunction)(void);
-static void jump_app(void)
-{
- pFunction JumpToApplication;
- uint32_t JumpAddress;
-
- if (((*(__IO uint32_t *)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFFB000) == 0x20000000)
- {
- /* Jump to user application */
- /*!< Jump to app reset_handler */
- JumpAddress = *(__IO uint32_t *)(USBD_DFU_APP_DEFAULT_ADD + 4);
- JumpToApplication = (pFunction)JumpAddress;
-
- /* Initialize user application's Stack Pointer */
- __set_MSP(*(__IO uint32_t *)USBD_DFU_APP_DEFAULT_ADD);
- JumpToApplication();
- }
-}
-/* USER CODE END PFP */
-
-/* Private user code ---------------------------------------------------------*/
-/* USER CODE BEGIN 0 */
-int fputc(int ch, FILE *f)
-{
- while ((USART1->SR & USART_SR_TXE) == 0)
- ;
- USART1->DR = ch;
- return ch;
-}
-
-void usb_dc_low_level_init(void)
-{
- /* Peripheral clock enable */
- __HAL_RCC_USB_CLK_ENABLE();
- /* USB interrupt Init */
- HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
-
-}
-
-uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
-{
- uint32_t i = 0;
- uint8_t *psrc = src;
-
- for (i = 0; i < len; i++)
- {
- dest[i] = *psrc++;
- }
- /* Return a valid address to avoid HardFault */
- return (uint8_t *)(dest);
-}
-
-uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
-{
- HAL_FLASH_Unlock();
- uint32_t i = 0;
-
- for (i = 0; i < len; i += 4)
- {
- /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
- * be done by byte */
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)(dest + i),
- *(uint32_t *)(src + i)) == HAL_OK)
- {
- /* Check the written value */
- if (*(uint32_t *)(src + i) != *(uint32_t *)(dest + i))
- {
- /* Flash content doesn't match SRAM content */
- return (1);
- }
- }
- else
- {
- /* Error occurred while writing data in Flash memory */
- return (2);
- }
- }
- return 0;
-}
-
-uint16_t dfu_erase_flash(uint32_t add)
-{
- HAL_FLASH_Unlock();
- uint32_t PageError;
- /* Variable contains Flash operation status */
- HAL_StatusTypeDef status;
- FLASH_EraseInitTypeDef eraseinitstruct;
-
- eraseinitstruct.TypeErase = FLASH_TYPEERASE_PAGES;
- eraseinitstruct.PageAddress = add;
- eraseinitstruct.NbPages = 1U;
- status = HAL_FLASHEx_Erase(&eraseinitstruct, &PageError);
- return 0;
-}
-
-void dfu_leave(void)
-{
- NVIC_SystemReset();
-}
-
-/* USER CODE END 0 */
-
-/**
- * @brief The application entry point.
- * @retval int
- */
-int main(void)
-{
- /* USER CODE BEGIN 1 */
- jump_app();
- /* USER CODE END 1 */
-
- /* MCU Configuration--------------------------------------------------------*/
-
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
-
- /* USER CODE BEGIN Init */
-
- /* USER CODE END Init */
-
- /* Configure the system clock */
- SystemClock_Config();
-
- /* USER CODE BEGIN SysInit */
-
- /* USER CODE END SysInit */
-
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_USART1_UART_Init();
- //MX_USB_PCD_Init();
- /* USER CODE BEGIN 2 */
-
-
-// extern void cdc_acm_msc_init(void);
-// cdc_acm_msc_init();
- extern void dfu_flash_init(void);
- dfu_flash_init();
-
- /* USER CODE END 2 */
-
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1) {
- /* USER CODE END WHILE */
-
- /* USER CODE BEGIN 3 */
-// extern void cdc_acm_data_send_with_dtr_test(void);
-// cdc_acm_data_send_with_dtr_test();
-// HAL_Delay(100);
- }
- /* USER CODE END 3 */
-}
-
-/**
- * @brief System Clock Configuration
- * @retval None
- */
-void SystemClock_Config(void)
-{
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
-
- /** Initializes the RCC Oscillators according to the specified parameters
- * in the RCC_OscInitTypeDef structure.
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /** Initializes the CPU, AHB and APB buses clocks
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
-
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
- {
- Error_Handler();
- }
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
- PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
- if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
- {
- Error_Handler();
- }
-}
-
-/**
- * @brief USART1 Initialization Function
- * @param None
- * @retval None
- */
-static void MX_USART1_UART_Init(void)
-{
-
- /* USER CODE BEGIN USART1_Init 0 */
-
- /* USER CODE END USART1_Init 0 */
-
- /* USER CODE BEGIN USART1_Init 1 */
-
- /* USER CODE END USART1_Init 1 */
- huart1.Instance = USART1;
- huart1.Init.BaudRate = 115200;
- huart1.Init.WordLength = UART_WORDLENGTH_8B;
- huart1.Init.StopBits = UART_STOPBITS_1;
- huart1.Init.Parity = UART_PARITY_NONE;
- huart1.Init.Mode = UART_MODE_TX_RX;
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
- if (HAL_UART_Init(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN USART1_Init 2 */
-
- /* USER CODE END USART1_Init 2 */
-
-}
-
-/**
- * @brief USB Initialization Function
- * @param None
- * @retval None
- */
-static void MX_USB_PCD_Init(void)
-{
-
- /* USER CODE BEGIN USB_Init 0 */
-
- /* USER CODE END USB_Init 0 */
-
- /* USER CODE BEGIN USB_Init 1 */
-
- /* USER CODE END USB_Init 1 */
- hpcd_USB_FS.Instance = USB;
- hpcd_USB_FS.Init.dev_endpoints = 8;
- hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
- hpcd_USB_FS.Init.low_power_enable = DISABLE;
- hpcd_USB_FS.Init.lpm_enable = DISABLE;
- hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
- if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN USB_Init 2 */
-
- /* USER CODE END USB_Init 2 */
-
-}
-
-/**
- * @brief GPIO Initialization Function
- * @param None
- * @retval None
- */
-static void MX_GPIO_Init(void)
-{
-
- /* GPIO Ports Clock Enable */
- __HAL_RCC_GPIOD_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
-
-}
-
-/* USER CODE BEGIN 4 */
-
-/* USER CODE END 4 */
-
-/**
- * @brief This function is executed in case of error occurrence.
- * @retval None
- */
-void Error_Handler(void)
-{
- /* USER CODE BEGIN Error_Handler_Debug */
- /* User can add his own implementation to report the HAL error return state */
- __disable_irq();
- while (1) {
- }
- /* USER CODE END Error_Handler_Debug */
-}
-
-#ifdef USE_FULL_ASSERT
-/**
- * @brief Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * @param file: pointer to the source file name
- * @param line: assert_param error line source number
- * @retval None
- */
-void assert_failed(uint8_t *file, uint32_t line)
-{
- /* USER CODE BEGIN 6 */
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- /* USER CODE END 6 */
-}
-#endif /* USE_FULL_ASSERT */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/demo/dfu_with_st_tool_template.c b/demo/dfu_template.c
index 0127c58a..0c0402e1 100644
--- a/demo/dfu_with_st_tool_template.c
+++ b/demo/dfu_template.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, sakumisu
+ * Copyright (c) 2022 ~ 2026, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,13 +7,13 @@
#include "usbd_dfu.h"
#define USBD_VID 0x0483
-#define USBD_PID 0xDF11
+#define USBD_PID 0xdf11
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
-#define FLASH_DESC_STR "@Internal Flash /0x08000000/16*001Ka,112*01Kg"
+#define USB_CONFIG_SIZE (9 + DFU_DESCRIPTOR_LEN)
-#define USB_CONFIG_SIZE (9 + 9 + 9)
+#define FLASH_DESC_STR "@Internal Flash /0x08000000/16*128Kg"
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
@@ -21,7 +21,7 @@ static const uint8_t device_descriptor[] = {
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
- DFU_DESCRIPTOR_INIT()
+ DFU_DESCRIPTOR_INIT(4)
};
static const uint8_t device_quality_descriptor[] = {
@@ -45,6 +45,7 @@ static const char *string_descriptors[] = {
"CherryUSB", /* Manufacturer */
"CherryUSB DFU DEMO", /* Product */
"2022123456", /* Serial Number */
+ FLASH_DESC_STR
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
@@ -64,13 +65,14 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
- if (index > 3) {
+ if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
return NULL;
}
+
return string_descriptors[index];
}
-const struct usb_descriptor dfu_flash_descriptor = {
+const struct usb_descriptor dfu_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
@@ -104,10 +106,52 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
struct usbd_interface intf0;
-void dfu_flash_init(uint8_t busid, uintptr_t reg_base)
+void dfu_init(uint8_t busid, uintptr_t reg_base)
{
- usbd_desc_register(busid, &dfu_flash_descriptor);
+ usbd_desc_register(busid, &dfu_descriptor);
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
usbd_initialize(busid, reg_base, usbd_event_handler);
}
+
+volatile uint32_t flash_start_address;
+
+void usbd_dfu_begin_load(void)
+{
+ flash_start_address = 0x08000000;
+}
+
+void usbd_dfu_end_load(void)
+{
+}
+
+void usbd_dfu_reset(void)
+{
+ //NVIC_SystemReset();
+}
+
+int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length)
+{
+ //usb_hexdump(data, length);
+
+ // patch for stm32 special command
+#if 1
+ if (value == 0) {
+ if (data[0] == DFU_SPECIAL_CMD_SET_ADDRESS_POINTER) {
+ memcpy((uint8_t *)&flash_start_address, data, 4);
+ } else if (data[0] == DFU_SPECIAL_CMD_ERASE) {
+ memcpy((uint8_t *)&flash_start_address, data, 4);
+ }
+ } else if (value > 1) {
+ uint32_t addr = (value - 2) * CONFIG_USBDEV_REQUEST_BUFFER_LEN + flash_start_address;
+ }
+#else
+ flash_start_address += length;
+#endif
+ return 0;
+}
+
+int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length)
+{
+ return 0;
+} \ No newline at end of file
diff --git a/tools/dfu-util/url b/tools/dfu-util/url
new file mode 100644
index 00000000..c211ed5c
--- /dev/null
+++ b/tools/dfu-util/url
@@ -0,0 +1,3 @@
+http://www.st.com/en/development-tools/stsw-stm32080.html
+
+https://dfu-util.sourceforge.net/ \ No newline at end of file
diff --git a/tools/stm32_dfuse/url b/tools/stm32_dfuse/url
deleted file mode 100644
index 808c6f73..00000000
--- a/tools/stm32_dfuse/url
+++ /dev/null
@@ -1 +0,0 @@
-http://www.st.com/en/development-tools/stsw-stm32080.html \ No newline at end of file