diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 676af237c8..3ae8f5e133 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -630,6 +630,48 @@ void dcd_sof_enable(uint8_t rhport, bool en) /* DCD Endpoint port *------------------------------------------------------------------*/ +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) + +// Check if IN/OUT endpoint is avaliable before opening it +static bool dcd_edpt_available(uint8_t rhport, uint8_t dir) +{ + // Verify that we have a vacant EP + if ((dwc_ep_config[rhport].in_ep + dwc_ep_config[rhport].out_ep) > (dwc_ep_config[rhport].ep_max_count - 1)) { + return false; + } + // Get the ep_count amount at the moment as a temporal variable and update it + uint8_t new_ep_count = (dir) ? dwc_ep_config[rhport].in_ep : dwc_ep_config[rhport].out_ep; + new_ep_count++; + + // Verify overflow for IN EP ESP32Sx + #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // ESP32Sx has 6 endpoints, from which only 5 can be confiugred as IN + if ((dir) && (new_ep_count > (dwc_ep_config[rhport].ep_max_count - 1))) { + return false; + } + #endif // TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // Write new value back + if(dir) { + dwc_ep_config[rhport].in_ep = new_ep_count; + } else { + dwc_ep_config[rhport].out_ep = new_ep_count; + } + return true; +} + +// Release an endpoint. +static void dcd_edpt_release(uint8_t rhport, uint8_t dir) +{ + if (dir) { + TU_ASSERT(dwc_ep_config[rhport].in_ep == 0); // Check if number of opened EPs is not zero + dwc_ep_config[rhport].in_ep--; // Release in_ep + } else { + TU_ASSERT(dwc_ep_config[rhport].out_ep == 0); + dwc_ep_config[rhport].out_ep--; + } +} +#endif + bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { (void) rhport; @@ -640,7 +682,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT(epnum < ep_count); + #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) + if (!dcd_edpt_available(rhport, dir)) { + TU_LOG(1, "No endpoints available (ep_max=%d) \r\n", dwc_ep_config[rhport].ep_max_count); + return false; + } + #endif xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = tu_edpt_packet_size(desc_edpt); @@ -721,6 +768,11 @@ void dcd_edpt_close_all (uint8_t rhport) dwc2_regs_t * dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; + #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) + dwc_ep_config[rhport].in_ep = 0; + dwc_ep_config[rhport].out_ep = 0; + #endif + // Disable non-control interrupt dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos); @@ -878,6 +930,13 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) dcd_edpt_disable(rhport, ep_addr, false); + #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) + // Release an endpoint if it is not the 0 EP + if (epnum) { + dcd_edpt_release(rhport, dir); + } + #endif + // Update max_size xfer_status[epnum][dir].max_size = 0; // max_size = 0 marks a disabled EP - required for changing FIFO allocation diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index 5653f0a0a1..695a4ff53f 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -55,7 +55,7 @@ #endif #if DWC2_FS_PERIPH_BASE - #define DWC2_FS_EP_MAX 6 // USB_OUT_EP_NUM. TODO ESP32Sx only has 5 tx fifo (5 endpoint IN) + #define DWC2_FS_EP_MAX 6 // USB_OUT_EP_NUM #define DWC2_FS_EP_FIFO_SIZE 1024 #endif @@ -82,6 +82,16 @@ static const dwc2_controller_t _dwc2_controller[] = #endif }; +static dwc_ep_config_t dwc_ep_config[] = +{ +#ifdef DWC2_FS_PERIPH_BASE + { .out_ep = 0, .in_ep = 0, .ep_max_count = DWC2_FS_EP_MAX }, +#endif +#ifdef DWC2_HS_PERIPH_BASE + { .out_ep = 0, .in_ep = 0, .ep_max_count = DWC2_HS_EP_MAX }, +#endif +}; + static intr_handle_t usb_ih[DWC2_PERIPH_COUNT]; static void dcd_int_handler_wrap(void* arg) diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 3fc979337d..2f5783c1ec 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -32,6 +32,14 @@ typedef struct uint32_t ep_fifo_size; }dwc2_controller_t; +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) +typedef struct { + uint8_t out_ep; + uint8_t in_ep; + const uint8_t ep_max_count; +}dwc_ep_config_t; +#endif + /* DWC OTG HW Release versions */ #define DWC2_CORE_REV_2_71a 0x4f54271a #define DWC2_CORE_REV_2_72a 0x4f54272a