From b42280a510f60203af17fb9492c6f7e2623b1dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Tue, 28 Apr 2020 13:41:14 +0200 Subject: [PATCH 1/2] Implement DfuSe upload command --- examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c | 10 +++++++--- examples/stm32/f1/other/usb_dfu/usbdfu.c | 9 +++++++-- examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c | 10 +++++++--- examples/stm32/f1/stm32-h103/usb_iap/usbiap.c | 10 +++++++--- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c b/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c index 1b089c12..301fa8a5 100644 --- a/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c @@ -63,7 +63,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -204,8 +204,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *usbd_d usbdfu_state = STATE_DFU_IDLE; return USBD_REQ_HANDLED; case DFU_UPLOAD: - /* Upload not supported for now. */ - return USBD_REQ_NOTSUPP; + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + uint32_t addr = prog.addr + + ((req->wValue - 2) * dfu_function.wTransferSize); + memcpy(*buf, (void*)addr, dfu_function.wTransferSize); + *len = dfu_function.wTransferSize; + return USBD_REQ_HANDLED; case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ (*buf)[0] = usbdfu_getstatus(&bwPollTimeout); diff --git a/examples/stm32/f1/other/usb_dfu/usbdfu.c b/examples/stm32/f1/other/usb_dfu/usbdfu.c index 3a310040..d7c85b03 100644 --- a/examples/stm32/f1/other/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/other/usb_dfu/usbdfu.c @@ -63,7 +63,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -204,7 +204,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *usbd_d usbdfu_state = STATE_DFU_IDLE; return USBD_REQ_HANDLED; case DFU_UPLOAD: - /* Upload not supported for now. */ + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + uint32_t addr = prog.addr + + ((req->wValue - 2) * dfu_function.wTransferSize); + memcpy(*buf, (void*)addr, dfu_function.wTransferSize); + *len = dfu_function.wTransferSize; + return USBD_REQ_HANDLED; return USBD_REQ_NOTSUPP; case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ diff --git a/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c b/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c index 1ac4fbaf..8aaa7ad1 100644 --- a/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c @@ -63,7 +63,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -204,8 +204,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *usbd_d usbdfu_state = STATE_DFU_IDLE; return USBD_REQ_HANDLED; case DFU_UPLOAD: - /* Upload not supported for now. */ - return USBD_REQ_NOTSUPP; + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + uint32_t addr = prog.addr + + ((req->wValue - 2) * dfu_function.wTransferSize); + memcpy(*buf, (void*)addr, dfu_function.wTransferSize); + *len = dfu_function.wTransferSize; + return USBD_REQ_HANDLED; case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ (*buf)[0] = usbdfu_getstatus(usbd_dev, &bwPollTimeout); diff --git a/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c b/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c index f385e050..ebf6d494 100644 --- a/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c +++ b/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c @@ -63,7 +63,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -204,8 +204,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *usbd_d usbdfu_state = STATE_DFU_IDLE; return USBD_REQ_HANDLED; case DFU_UPLOAD: - /* Upload not supported for now. */ - return USBD_REQ_NOTSUPP; + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + uint32_t addr = prog.addr + + ((req->wValue - 2) * dfu_function.wTransferSize); + memcpy(*buf, (void*)addr, dfu_function.wTransferSize); + *len = dfu_function.wTransferSize; + return USBD_REQ_HANDLED; case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ (*buf)[0] = usbdfu_getstatus(usbd_dev, &bwPollTimeout); From 408e20dddc66f112621d71c0ad21fc65fe2b081d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Tue, 28 Apr 2020 14:03:18 +0200 Subject: [PATCH 2/2] Add docs for DfuSe descriptor string --- examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c | 27 ++++++++++++++++-- examples/stm32/f1/other/usb_dfu/usbdfu.c | 28 +++++++++++++++++-- examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c | 28 +++++++++++++++++-- examples/stm32/f1/stm32-h103/usb_iap/usbiap.c | 28 +++++++++++++++++-- 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c b/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c index 301fa8a5..97b2f4d8 100644 --- a/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c @@ -79,8 +79,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ + /* The ST Microelectronics DfuSe application needs this string. */ .iInterface = 4, .extra = &dfu_function, @@ -109,8 +108,30 @@ static const char *usb_strings[] = { "Black Sphere Technologies", "DFU Demo", "DEMO", - /* This string is used by ST Microelectronics' DfuSe utility. */ + // DfuSe descriptor string, used by ST DfuSe utility and also + // supported by dfu-util, see UM0424 section 10.3.2: + // + // |----------[zone]----------| + // [segment] + // \-----/ "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + // start address of [zone]-^ | |--/| \-------/ + // | | | [segment] + // | | | + // | | ` [flags], "a"=readable + // [flags]: | ` 1K bytes per erase-block + // (a) readable `8 erase-blocks + // (b) earaseable + // (c) readable and earaseable + // (e) readable and writable + // (f) earaseable and writable + // (g) readable, earaseable and writable + // + // [zone]: a number of segments starting at given address, allowed + // to be non-contigous + // + // [segment]: a number of contigous erase blocks, or "sectors" in + // ST docs }; static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout) diff --git a/examples/stm32/f1/other/usb_dfu/usbdfu.c b/examples/stm32/f1/other/usb_dfu/usbdfu.c index d7c85b03..c0344b41 100644 --- a/examples/stm32/f1/other/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/other/usb_dfu/usbdfu.c @@ -79,8 +79,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ + /* The ST Microelectronics DfuSe application needs this string. */ .iInterface = 4, .extra = &dfu_function, @@ -109,8 +108,31 @@ static const char *usb_strings[] = { "Black Sphere Technologies", "DFU Demo", "DEMO", - /* This string is used by ST Microelectronics' DfuSe utility. */ + + // DfuSe descriptor string, used by ST DfuSe utility and also + // supported by dfu-util, see UM0424 section 10.3.2: + // + // |----------[zone]----------| + // [segment] + // \-----/ "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + // start address of [zone]-^ | |--/| \-------/ + // | | | [segment] + // | | | + // | | ` [flags], "a"=readable + // [flags]: | ` 1K bytes per erase-block + // (a) readable `8 erase-blocks + // (b) earaseable + // (c) readable and earaseable + // (e) readable and writable + // (f) earaseable and writable + // (g) readable, earaseable and writable + // + // [zone]: a number of segments starting at given address, allowed + // to be non-contigous + // + // [segment]: a number of contigous erase blocks, or "sectors" in + // ST docs }; static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout) diff --git a/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c b/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c index 8aaa7ad1..8aa5c1df 100644 --- a/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c @@ -79,8 +79,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ + /* The ST Microelectronics DfuSe application needs this string. */ .iInterface = 4, .extra = &dfu_function, @@ -109,8 +108,31 @@ static const char *usb_strings[] = { "Black Sphere Technologies", "DFU Demo", "DEMO", - /* This string is used by ST Microelectronics' DfuSe utility. */ + + // DfuSe descriptor string, used by ST DfuSe utility and also + // supported by dfu-util, see UM0424 section 10.3.2: + // + // |----------[zone]----------| + // [segment] + // \-----/ "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + // start address of [zone]-^ | |--/| \-------/ + // | | | [segment] + // | | | + // | | ` [flags], "a"=readable + // [flags]: | ` 1K bytes per erase-block + // (a) readable `8 erase-blocks + // (b) earaseable + // (c) readable and earaseable + // (e) readable and writable + // (f) earaseable and writable + // (g) readable, earaseable and writable + // + // [zone]: a number of segments starting at given address, allowed + // to be non-contigous + // + // [segment]: a number of contigous erase blocks, or "sectors" in + // ST docs }; static uint8_t usbdfu_getstatus(usbd_device *usbd_dev, uint32_t *bwPollTimeout) diff --git a/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c b/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c index ebf6d494..b29641fa 100644 --- a/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c +++ b/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c @@ -79,8 +79,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ + /* The ST Microelectronics DfuSe application needs this string. */ .iInterface = 4, .extra = &dfu_function, @@ -109,8 +108,31 @@ static const char *usb_strings[] = { "Black Sphere Technologies", "DFU Demo", "DEMO", - /* This string is used by ST Microelectronics' DfuSe utility. */ + + // DfuSe descriptor string, used by ST DfuSe utility and also + // supported by dfu-util, see UM0424 section 10.3.2: + // + // |----------[zone]----------| + // [segment] + // \-----/ "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + // start address of [zone]-^ | |--/| \-------/ + // | | | [segment] + // | | | + // | | ` [flags], "a"=readable + // [flags]: | ` 1K bytes per erase-block + // (a) readable `8 erase-blocks + // (b) earaseable + // (c) readable and earaseable + // (e) readable and writable + // (f) earaseable and writable + // (g) readable, earaseable and writable + // + // [zone]: a number of segments starting at given address, allowed + // to be non-contigous + // + // [segment]: a number of contigous erase blocks, or "sectors" in + // ST docs }; static uint8_t usbdfu_getstatus(usbd_device *usbd_dev, uint32_t *bwPollTimeout)