From 6b0ec0e16f82c4b869ccc373a2a284b3a4085115 Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Thu, 5 Feb 2026 20:39:38 +0800 Subject: [PATCH] refactor(class/dfu): refactor dfu device driver Signed-off-by: sakumisu <1203593632@qq.com> --- Kconfig | 4 + Kconfig.rtt | 4 + Kconfig.rttpkg | 4 + README.md | 1 + README_zh.md | 1 + SConscript | 2 + class/dfu/usb_dfu.h | 57 +- class/dfu/usbd_dfu.c | 722 +++++++----------- class/dfu/usbd_dfu.h | 14 +- demo/dfu_st_cubemx_main.c | 372 --------- ...with_st_tool_template.c => dfu_template.c} | 62 +- tools/dfu-util/url | 3 + tools/stm32_dfuse/url | 1 - 13 files changed, 387 insertions(+), 860 deletions(-) delete mode 100644 demo/dfu_st_cubemx_main.c rename demo/{dfu_with_st_tool_template.c => dfu_template.c} (64%) create mode 100644 tools/dfu-util/url delete mode 100644 tools/stm32_dfuse/url 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,431 +1,28 @@ /* - * 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)); - - 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; - - g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE; - 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; - g_usbd_dfu.dev_status[4] = DFU_STATE_DFU_IDLE; - g_usbd_dfu.dev_status[5] = 0U; -} - -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; - break; - - case DFU_MEDIA_ERASE: - buffer[1] = (uint8_t)FLASH_ERASE_TIME; - buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8); - buffer[3] = 0; - default: - - 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; - - /* 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; - - /* 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"); - } - } - /* 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); - } - } -} - -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; - - USB_LOG_DBG("Erase start add %08x \r\n", g_usbd_dfu.data_ptr); - /*!< Erase */ - dfu_erase_flash(g_usbd_dfu.data_ptr); - } else { - 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; - - 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; - - 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_MANIFEST_SYNC: - if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS) { - g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST; - - 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; - } - } - break; - - default: - break; - } - - /* Send the status data over EP0 */ - memcpy(*data, g_usbd_dfu.dev_status, 6); - *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; - } -} - -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; - } -} +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" +}; static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) { @@ -433,33 +30,260 @@ static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_p "bRequest 0x%02x\r\n", setup->bRequest); - switch (setup->bRequest) { - case DFU_REQUEST_DETACH: - dfu_request_detach(); + USB_LOG_DBG("dfu state:%s\r\n", usbd_dfu_state_string[g_usbd_dfu.dfu_state]); + + 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; + + default: + return -1; + } break; - case DFU_REQUEST_DNLOAD: - dfu_request_dnload(setup, data, len); + 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; + + default: + return -1; + } break; - case DFU_REQUEST_UPLOAD: - dfu_request_upload(setup, data, len); + 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(); + + 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; + + default: + return -1; + } break; - case DFU_REQUEST_GETSTATUS: - dfu_request_getstatus(setup, data, len); + case DFU_STATE_DFU_DNLOAD_SYNC: + switch (setup->bRequest) { + case DFU_REQUEST_GETSTATUS: + g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_BUSY; + + (*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: + return -1; + } break; - case DFU_REQUEST_CLRSTATUS: - dfu_request_clrstatus(); + case DFU_STATE_DFU_DNLOAD_BUSY: + switch (setup->bRequest) { + case DFU_REQUEST_GETSTATUS: + g_usbd_dfu.dfu_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; + + default: + return -1; + } break; - case DFU_REQUEST_GETSTATE: - dfu_request_getstate(setup, data, len); + 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; + } + } + + 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: + return -1; + } break; - case DFU_REQUEST_ABORT: - dfu_request_abort(); + 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: + 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; + + (*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; + + usbd_dfu_reset(); + break; + case DFU_REQUEST_GETSTATE: + (*data)[0] = g_usbd_dfu.dfu_state; + *len = 1; + break; + + default: + return -1; + } + break; + 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) +{ +} + +__WEAK void usbd_dfu_end_load(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 uint16_t dfu_erase_flash(uint32_t add) +__WEAK int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length) { return 0; -} - -__WEAK void dfu_leave(void) -{ -} +} \ 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 - * - *

© Copyright (c) 2021 STMicroelectronics. - * All rights reserved.

- * - * 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 similarity index 64% rename from demo/dfu_with_st_tool_template.c rename to 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