From a54a974fa58c3c863ea6855ac911cecffb2afc04 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 7 Sep 2021 23:02:57 +0700 Subject: [PATCH 1/3] make synopsys usbcv compliance - implement dcd_edpt_close_all() - reset dtoggle when open endpoint - correct dev interrupt mask on bus reset --- src/portable/st/synopsys/dcd_synopsys.c | 63 +++++++++++++++---------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index fe165e830..93bbaf23b 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -213,17 +213,18 @@ static void bus_reset(uint8_t rhport) tu_memclr(xfer_status, sizeof(xfer_status)); _out_ep_closed = false; + // clear device address + dev->DCFG &= ~USB_OTG_DCFG_DAD_Msk; + + // 1. NAK for all OUT endpoints for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; } - // clear device address - dev->DCFG &= ~USB_OTG_DCFG_DAD_Msk; - - // TODO should probably assign value when reset rather than OR - dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); - dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; - dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; + // 2. Un-mask interrupt bits + dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); + dev->DOEPMSK = USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; + dev->DIEPMSK = USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture @@ -307,8 +308,6 @@ static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) // Turnaround timeout depends on the MCU clock uint32_t turnaround; - TU_LOG_INT(2, SystemCoreClock); - if ( SystemCoreClock >= 32000000U ) turnaround = 0x6U; else if ( SystemCoreClock >= 27500000U ) @@ -618,8 +617,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) usb_otg->GRXFSIZ = sz; } - out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | - (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | + out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); @@ -661,7 +661,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DIEPCTL_SD0PID_SEVNFRM : 0) | (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); @@ -670,10 +670,32 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +// Close all non-control endpoints, cancel all pending transfers if any. void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; - // TODO implement dcd_edpt_close_all() + +// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + // Disable non-control interrupt + dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); + + for(uint8_t n = 1; n < EP_MAX; n++) + { + // disable OUT endpoint + out_ep[n].DOEPCTL = 0; + xfer_status[n][TUSB_DIR_OUT].max_size = 0; + + // disable IN endpoint + in_ep[n].DIEPCTL = 0; + xfer_status[n][TUSB_DIR_IN].max_size = 0; + } + + // reset allocated fifo IN + _allocated_fifo_words_tx = 16; } bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) @@ -835,22 +857,13 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + // Clear stall and reset data toggle if(dir == TUSB_DIR_IN) { in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; - - uint8_t eptype = (in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP_Msk) >> USB_OTG_DIEPCTL_EPTYP_Pos; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. - if(eptype == 2 || eptype == 3) { - in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; - } + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; } else { out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; - - uint8_t eptype = (out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP_Msk) >> USB_OTG_DOEPCTL_EPTYP_Pos; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. - if(eptype == 2 || eptype == 3) { - out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; - } + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; } } From 4ac136d81d452ea1dcfc1e9e2e8afbf02749044d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Sep 2021 00:57:07 +0700 Subject: [PATCH 2/3] implement remote wakeup for stm synopsys --- src/portable/st/synopsys/dcd_synopsys.c | 38 +++++++++++++++++++------ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 93bbaf23b..b1435a6c8 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -555,13 +555,31 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } +static void remote_wakeup_delay(void) +{ + // try to delay for 1 ms + uint32_t count = SystemCoreClock / 1000; + while(count--) __NOP(); +} + void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - // TODO must manually clear this bit after 1-15 ms - // USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - // dev->DCTL |= USB_OTG_DCTL_RWUSIG; + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + + // set remote wakeup + dev->DCTL |= USB_OTG_DCTL_RWUSIG; + + // enable SOF to detect bus resume + usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF; + usb_otg->GINTMSK |= USB_OTG_GINTMSK_SOFM; + + // Per specs: remote wakeup signal bit must be clear within 1-15ms + remote_wakeup_delay(); + + dev->DCTL &= ~USB_OTG_DCTL_RWUSIG; } void dcd_connect(uint8_t rhport) @@ -1100,7 +1118,7 @@ void dcd_int_handler(uint8_t rhport) USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); - uint32_t int_status = usb_otg->GINTSTS; + uint32_t const int_status = usb_otg->GINTSTS & usb_otg->GINTMSK; if(int_status & USB_OTG_GINTSTS_USBRST) { @@ -1133,6 +1151,9 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } + // TODO check USB_OTG_GINTSTS_DISCINT for disconnect detection + // if(int_status & USB_OTG_GINTSTS_DISCINT) + if(int_status & USB_OTG_GINTSTS_OTGINT) { // OTG INT bit is read-only @@ -1146,13 +1167,15 @@ void dcd_int_handler(uint8_t rhport) usb_otg->GOTGINT = otg_int; } -#if USE_SOF if(int_status & USB_OTG_GINTSTS_SOF) { usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF; + + // Disable SOF interrupt since currently only used for remote wakeup detection + usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } -#endif // RxFIFO non-empty interrupt handling. if(int_status & USB_OTG_GINTSTS_RXFLVL) @@ -1166,8 +1189,7 @@ void dcd_int_handler(uint8_t rhport) do { handle_rxflvl_ints(rhport, out_ep); - int_status = usb_otg->GINTSTS; - } while(int_status & USB_OTG_GINTSTS_RXFLVL); + } while(usb_otg->GINTSTS & USB_OTG_GINTSTS_RXFLVL); // Manage RX FIFO size if (_out_ep_closed) From 67e80f60e3841497779a319bbd93133c05b013f8 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Sep 2021 13:35:11 +0700 Subject: [PATCH 3/3] fix build with gd32vf103 --- src/portable/st/synopsys/dcd_synopsys.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b1435a6c8..85abf940e 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -96,6 +96,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 #include "synopsys_common.h" +// for remote wakeup delay +#define __NOP() __asm volatile ("nop") + // These numbers are the same for the whole GD32VF103 family. #define OTG_FS_IRQn 86 #define EP_MAX_FS 4 @@ -559,7 +562,10 @@ static void remote_wakeup_delay(void) { // try to delay for 1 ms uint32_t count = SystemCoreClock / 1000; - while(count--) __NOP(); + while ( count-- ) + { + __NOP(); + } } void dcd_remote_wakeup(uint8_t rhport)