chenzhihong007 opened a new issue, #10802: URL: https://github.com/apache/nuttx/issues/10802
## Issue Description When usb as host to connect cdcacm device, using read() API to get data from cdcacm device many times, EHCI driver, such as **sam_transfer() - sam_ioc_setup()**, will trigger assert in **sam_ioc_setup()**, because **epinfo->iocwait** is true. ``` c DEBUGASSERT(rhport && epinfo && !epinfo->iocwait); ``` ## Analysis read() API caller as follows: read() - uart_read() - uart_disablerxint()【usbhost_rxint()】 - uart_enablerxint()【usbhost_rxint()】 - usbhost_rxdata_work() - DRVR_TRANSFER()【sam_transfer()】. In **usbhost_rxdata_work()**, while loop call **DRVR_TRANSFER()【sam_transfer()】** to excute usb IN transition. DRVR_TRANSFER() is a blocking method, this functions will not return until the transfer has completed, the comments as follows: ``` * Name: sam_transfer * * Description: * Process a request to handle a transfer descriptor. This method will * enqueue the transfer request, blocking until the transfer completes. * Only one transfer may be queued; Neither this method nor the ctrlin or * ctrlout methods can be called again until this function returns. * * This is a blocking method; this functions will not return until the * transfer has completed. ``` But every read() operation, call uart_disablerxint() first, then call uart_enablerxint(). So excute read() one time, call DRVR_TRANSFER() one time, even DRVR_TRANSFER() in progress or not finish. Thus will cause usb transfer abnormal, such as **epinfo->iocwait** is true. ## Solution I have two sulution ideas. - fix uart_read() logic,delete serial.c 986 line —— uart_disablerxint(dev). - fix usbhost_rxint() logic, cancel disable opertion. When rx is enabled, keep **priv->rxena** always enable. ``` static void usbhost_rxint(FAR struct uart_dev_s *uartdev, bool enable) { FAR struct usbhost_cdcacm_s *priv; int ret; DEBUGASSERT(uartdev && uartdev->priv); priv = (FAR struct usbhost_cdcacm_s *)uartdev->priv; /* Are we enabling or disabling RX reception? */ if (enable && !priv->rxena) { /* Cancel any pending, delayed RX data reception work */ work_cancel(LPWORK, &priv->rxwork); /* Restart immediate RX data reception work (unless RX flow control * is in effect. */ #ifdef CONFIG_SERIAL_IFLOWCONTROL if (priv->rts) #endif { ret = work_queue(LPWORK, &priv->rxwork, usbhost_rxdata_work, priv, 0); DEBUGASSERT(ret >= 0); UNUSED(ret); } /* Save the new RX enable state */ priv->rxena = enable; } } ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org