diff --git a/bootloaders/riotboot_dfu/Makefile b/bootloaders/riotboot_dfu/Makefile index 615e7dd09cb3..308cb8b489a1 100644 --- a/bootloaders/riotboot_dfu/Makefile +++ b/bootloaders/riotboot_dfu/Makefile @@ -4,10 +4,6 @@ APPLICATION = riotboot_dfu # Add RIOTBOOT USB DFU integration USEMODULE += riotboot_usb_dfu -# Use xtimer for scheduled reboot -USEMODULE += ztimer -USEMODULE += ztimer_init - # USB device vendor and product ID # pid.codes test VID/PID, not globally unique diff --git a/bootloaders/riotboot_dfu/main.c b/bootloaders/riotboot_dfu/main.c index 275213c4b6c7..49b695bab313 100644 --- a/bootloaders/riotboot_dfu/main.c +++ b/bootloaders/riotboot_dfu/main.c @@ -26,9 +26,8 @@ #include "panic.h" #include "riotboot/slot.h" #include "riotboot/usb_dfu.h" -#include "ztimer.h" - #include "riotboot/bootloader_selection.h" +#include "ztimer.h" #ifdef BTN_BOOTLOADER_PIN #include "periph/gpio.h" @@ -74,9 +73,9 @@ void kernel_init(void) } } - /* Init ztimer before starting DFU mode */ - ztimer_init(); - + if (IS_USED(MODULE_ZTIMER)) { + ztimer_init(); + } /* Flash the unused slot if magic word is set */ riotboot_usb_dfu_init(0); diff --git a/sys/Makefile.dep b/sys/Makefile.dep index 5cb8f3994500..7935777e0d6f 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -893,7 +893,6 @@ endif ifneq (,$(filter riotboot_usb_dfu, $(USEMODULE))) USEMODULE += usbus_dfu USEMODULE += riotboot_flashwrite - USEMODULE += ztimer_sec FEATURES_REQUIRED += no_idle_thread FEATURES_REQUIRED += periph_pm endif diff --git a/sys/include/usb/usbus.h b/sys/include/usb/usbus.h index ad0bb06b81aa..106e66b9990e 100644 --- a/sys/include/usb/usbus.h +++ b/sys/include/usb/usbus.h @@ -141,6 +141,7 @@ extern "C" { */ #define USBUS_HANDLER_FLAG_TR_FAIL (0x0010) #define USBUS_HANDLER_FLAG_TR_STALL (0x0020) /**< Report transfer stall complete */ +#define USBUS_HANDLER_FLAG_TR_EP0_FWD (0x0100) /**< Forward transfer complete */ /** @} */ /** diff --git a/sys/usb/usbus/dfu/dfu.c b/sys/usb/usbus/dfu/dfu.c index 288e39e7b838..f78e61a52c44 100644 --- a/sys/usb/usbus/dfu/dfu.c +++ b/sys/usb/usbus/dfu/dfu.c @@ -25,9 +25,6 @@ #include "usb/usbus/dfu.h" #include "riotboot/magic.h" #include "riotboot/usb_dfu.h" -#ifdef MODULE_RIOTBOOT_USB_DFU -#include "ztimer.h" -#endif #include "periph/pm.h" #include "riotboot/slot.h" @@ -46,12 +43,6 @@ static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler, usbdev_ep_t *ep, usbus_event_transfer_t event); static void _init(usbus_t *usbus, usbus_handler_t *handler); -#ifdef MODULE_RIOTBOOT_USB_DFU -static void _reboot(void *arg); -static ztimer_t scheduled_reboot = { .callback=_reboot }; -#define REBOOT_DELAY 2 -#endif - #define DEFAULT_XFER_SIZE 64 static size_t _gen_dfu_descriptor(usbus_t *usbus, void *arg) @@ -88,14 +79,6 @@ static const usbus_descr_gen_funcs_t _dfu_descriptor = { .len_type = USBUS_DESCR_LEN_FIXED, }; -#ifdef MODULE_RIOTBOOT_USB_DFU -static void _reboot(void *arg) -{ - (void)arg; - pm_reboot(); -} -#endif - void usbus_dfu_init(usbus_t *usbus, usbus_dfu_device_t *handler, unsigned mode) { DEBUG("DFU: initialization\n"); @@ -228,13 +211,13 @@ static int _dfu_class_control_req(usbus_t *usbus, usbus_dfu_device_t *dfu, usb_s if (dfu->dfu_state == USB_DFU_STATE_DFU_DL_SYNC) { dfu->dfu_state = USB_DFU_STATE_DFU_DL_IDLE; - DEBUG("GET STATUS GO TO IDLE\n"); } else if (dfu->dfu_state == USB_DFU_STATE_DFU_MANIFEST_SYNC) { /* Scheduled reboot, so we can answer back dfu-util before rebooting */ dfu->dfu_state = USB_DFU_STATE_DFU_DL_IDLE; #ifdef MODULE_RIOTBOOT_USB_DFU - ztimer_set(ZTIMER_SEC, &scheduled_reboot, 1); + /* Set specific flag to forward TRANSFER_COMPLETE event to this interface */ + usbus_handler_set_flag(&dfu->handler_ctrl, USBUS_HANDLER_FLAG_TR_EP0_FWD); #endif } memset(&buf, 0, sizeof(buf)); @@ -243,7 +226,6 @@ static int _dfu_class_control_req(usbus_t *usbus, usbus_dfu_device_t *dfu, usb_s buf.state = dfu->dfu_state; /* Send answer to host */ usbus_control_slicer_put_bytes(usbus, (uint8_t*)&buf, sizeof(buf)); - DEBUG("send answer\n"); break; } case DFU_CLR_STATUS: @@ -294,10 +276,17 @@ static int _control_handler(usbus_t *usbus, usbus_handler_t *handler, static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler, usbdev_ep_t *ep, usbus_event_transfer_t event) { - (void)event; - (void)usbus; (void)handler; - (void)ep; + usbus_control_handler_t *ep0_handler = (usbus_control_handler_t *)usbus->control; + + /* Ensure we did transmit the status packet before rebooting to application */ + if (ep->dir == USB_EP_DIR_OUT && event == USBUS_EVENT_TRANSFER_COMPLETE) { + + /* Wait to receive OUTACK event on EP0 before rebooting */ + if (ep0_handler->control_request_state == USBUS_CONTROL_REQUEST_STATE_READY) { + pm_reboot(); + } + } } static void _event_handler(usbus_t *usbus, usbus_handler_t *handler, diff --git a/sys/usb/usbus/usbus_control.c b/sys/usb/usbus/usbus_control.c index 4f669b67d691..1ddd78445446 100644 --- a/sys/usb/usbus/usbus_control.c +++ b/sys/usb/usbus/usbus_control.c @@ -496,6 +496,13 @@ static void _handler_ep0_transfer(usbus_t *usbus, usbus_handler_t *handler, switch (event) { case USBUS_EVENT_TRANSFER_COMPLETE: _handle_tr_complete(usbus, ep0_handler, ep); + /* Forward to every handler, EP0 transfer event, except the first + * handler as this is the current handler used for this event */ + for (usbus_handler_t *hdl = handler->next; hdl; hdl = hdl->next) { + if(usbus_handler_isset_flag(hdl, USBUS_HANDLER_FLAG_TR_EP0_FWD)) { + hdl->driver->transfer_handler(usbus, hdl, ep, USBUS_EVENT_TRANSFER_COMPLETE); + } + } break; default: break;