Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dcd_dwc2): Reset opened EP counters on bus_reset event #23

Merged
merged 2 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 32 additions & 19 deletions src/portable/synopsys/dwc2/dcd_dwc2.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,46 +632,57 @@ void dcd_sof_enable(uint8_t rhport, bool en)

#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4)

// Check if IN/OUT endpoint is available before opening it
static bool dcd_edpt_available(uint8_t rhport, uint8_t dir)
// Reset opened IN/OUT endpoint counters
static void dcd_edpt_counters_reset(uint8_t rhport)
{
dwc2_ep_counters[rhport].active_in = 0;
dwc2_ep_counters[rhport].active_out = 0;
}

// Check if IN/OUT endpoint counter is available before opening endpoint
// return values:
// true : Endpoint available, value increased by one
// false : No more endpoints available, counter value reached maximum value
static bool dcd_edpt_counter_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)) {
if ((dwc2_ep_counters[rhport].active_in + dwc2_ep_counters[rhport].active_out) >
(dwc2_ep_counters[rhport].max_total - 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;
uint8_t new_ep_count = (dir) ? dwc2_ep_counters[rhport].active_in : dwc2_ep_counters[rhport].active_out;
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 configured as IN
if ((dir) && (new_ep_count > (dwc_ep_config[rhport].ep_max_count - 1))) {
if ((dir) && (new_ep_count > (dwc2_ep_counters[rhport].max_total - 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;
dwc2_ep_counters[rhport].active_in = new_ep_count;
} else {
dwc_ep_config[rhport].out_ep = new_ep_count;
dwc2_ep_counters[rhport].active_out = new_ep_count;
}
return true;
}

// Release an endpoint.
static bool dcd_edpt_release(uint8_t rhport, uint8_t dir)
static bool dcd_edpt_counter_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
TU_ASSERT(dwc2_ep_counters[rhport].active_in == 0); // Check if number of opened EPs is not zero
dwc2_ep_counters[rhport].active_in--; // Decrease endpoint counter
} else {
TU_ASSERT(dwc_ep_config[rhport].out_ep == 0);
dwc_ep_config[rhport].out_ep--;
TU_ASSERT(dwc2_ep_counters[rhport].active_out == 0);
dwc2_ep_counters[rhport].active_out--;
}
return true;
}
#endif
#endif // OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4

bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
{
Expand All @@ -684,11 +695,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);

#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);
if (!dcd_edpt_counter_available(rhport, dir)) {
TU_LOG(1, "No endpoints available (ep_max=%d) \r\n", dwc2_ep_counters[rhport].max_total);
return false;
}
#endif
#endif // OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4

xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
xfer->max_size = tu_edpt_packet_size(desc_edpt);
Expand Down Expand Up @@ -770,8 +781,7 @@ void dcd_edpt_close_all (uint8_t 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;
dcd_edpt_counters_reset(rhport);
#endif

// Disable non-control interrupt
Expand Down Expand Up @@ -934,7 +944,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
#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);
dcd_edpt_counter_release(rhport, dir);
}
#endif

Expand Down Expand Up @@ -1290,6 +1300,9 @@ void dcd_int_handler(uint8_t rhport)
// USBRST is start of reset.
dwc2->gintsts = GINTSTS_USBRST;
bus_reset(rhport);
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4)
dcd_edpt_counters_reset(rhport);
#endif // OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4
}

if(int_status & GINTSTS_ENUMDNE)
Expand Down
6 changes: 3 additions & 3 deletions src/portable/synopsys/dwc2/dwc2_esp32.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ static const dwc2_controller_t _dwc2_controller[] =
#endif
};

static dwc_ep_config_t dwc_ep_config[] =
static dwc2_ep_counters_t dwc2_ep_counters[] =
{
#ifdef DWC2_FS_PERIPH_BASE
{ .out_ep = 0, .in_ep = 0, .ep_max_count = DWC2_FS_EP_MAX },
{ .active_out = 0, .active_in = 0, .max_total = DWC2_FS_EP_MAX },
#endif
#ifdef DWC2_HS_PERIPH_BASE
{ .out_ep = 0, .in_ep = 0, .ep_max_count = DWC2_HS_EP_MAX },
{ .active_out = 0, .active_in = 0, .max_total = DWC2_HS_EP_MAX },
#endif
};

Expand Down
8 changes: 4 additions & 4 deletions src/portable/synopsys/dwc2/dwc2_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ typedef struct

#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;
uint8_t active_out;
uint8_t active_in;
const uint8_t max_total;
}dwc2_ep_counters_t;
#endif

/* DWC OTG HW Release versions */
Expand Down