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

DWC2 Host Stack Fails to Detect Device Removal Due to HPRT_CONN_DETECT #2918

Open
1 task done
nickfox-taterli opened this issue Dec 27, 2024 · 0 comments
Open
1 task done
Labels

Comments

@nickfox-taterli
Copy link

Operating System

Linux

Board

STM32L4R5 Nucleo-144,STM32F412 Nucleo-144

Firmware

When the host stack is activated, it always happens.

Tested with GCC, IAR, Keil.

gcc version 13.3.1 20240614 (Arm GNU Toolchain 13.3.Rel1 (Build arm-13.24))

What happened ?

I've encountered an issue with the DWC2 Host stack where device removal events are not correctly detected. This problem arises because the HPRT_CONN_DETECT bit in the hprt register is not set when the conn_status changes from 1 to 0. As a result, the hcd_event_device_remove function is not called, leaving the system unaware that a device has been disconnected.

How to reproduce ?

  1. Connect a USB device to the host port.
  2. Observe that the device is correctly detected and hcd_event_device_attach is called.
  3. Disconnect the USB device.
  4. Notice that hcd_event_device_remove is not triggered because dwc2->hprt & HPRT_CONN_DETECT remains unset, even though hprt_bm.conn_status changes to 0.

My temporary solution:

static void handle_hprt_irq(uint8_t rhport, bool in_isr)
{
  dwc2_regs_t *dwc2 = DWC2_REG(rhport);
  uint32_t hprt = dwc2->hprt & ~HPRT_W1_MASK;
  const dwc2_hprt_t hprt_bm = dwc2->hprt_bm;

  // Static array to store the previous connection status of each rhport
  static bool previous_conn_status[2] = {false};

  // Get the current connection status
  bool current_conn_status = hprt_bm.conn_status;

  // Check if HPRT_CONN_DETECT interrupt is set
  if (dwc2->hprt & HPRT_CONN_DETECT)
  {
    // ...
  }

  // Handle case where HPRT_CONN_DETECT is not set but conn_status has changed
  if (previous_conn_status[rhport] && !current_conn_status)
  {
    // Connection status changed from 1 to 0, call device remove
    hcd_event_device_remove(rhport, in_isr);
  }

  // Update the previous connection status
  previous_conn_status[rhport] = current_conn_status;

  // ...
}

Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)

When plugging and unplugging the device several times it stops exactly at this assertion, which LOG observes precisely because the device did not perform a removal before.

static bool enum_request_set_addr(void) {
  tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;

  // Get new address
  uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
  TU_ASSERT(new_addr != 0);
  TU_LOG_USBH("Set Address = %d\r\n", new_addr);

  // ....
}

Screenshots

No response

I have checked existing issues, dicussion and documentation

  • I confirm I have checked existing issues, dicussion and documentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant