summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/arch/arm/src/stm32/stm32_otgfsdev.c')
-rwxr-xr-xnuttx/arch/arm/src/stm32/stm32_otgfsdev.c79
1 files changed, 67 insertions, 12 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
index f84f289d9..d3f11977f 100755
--- a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
@@ -262,16 +262,16 @@ enum stm32_devstate_e
enum stm32_ep0state_e
{
- EP0STATE_IDLE = 0, /* Idle State, leave on receiving a setup packet or
+ EP0STATE_IDLE = 0, /* Idle State, leave on receiving a SETUP packet or
* epsubmit:
* SET: In stm32_epin() and stm32_epout() when
* we revert from request processing to
* SETUP processing.
* TESTED: Never */
- EP0STATE_SETUP, /* Setup Packet received by stm32_ep0out_setup():
+ EP0STATE_SETUP, /* SETUP packet beign processing in stm32_ep0out_setup():
* SET: When SETUP packet received in EP0 OUT
* TESTED: Never */
- EP0STATE_SETUPRESPONSE, /* Short setup response write (without a USB request):
+ EP0STATE_SETUPRESPONSE, /* Short SETUP response write (without a USB request):
* SET: When SETUP response is sent by
* stm32_ep0in_setupresponse()
* TESTED: Never */
@@ -418,6 +418,7 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
static void stm32_rxfifo_read(FAR struct stm32_ep_s *privep,
FAR uint8_t *dest, uint16_t len);
+static void stm32_rxfifo_discard(FAR struct stm32_ep_s *privep, int len);
static void stm32_epout_complete(FAR struct stm32_usbdev_s *priv,
FAR struct stm32_ep_s *privep);
static inline void stm32_epout_receive(FAR struct stm32_ep_s *privep, int bcnt);
@@ -427,7 +428,8 @@ static void stm32_epout_request(FAR struct stm32_usbdev_s *priv,
/* General request handling */
static void stm32_ep_flush(FAR struct stm32_ep_s *privep);
-static void stm32_req_complete(FAR struct stm32_ep_s *privep, int16_t result);
+static void stm32_req_complete(FAR struct stm32_ep_s *privep,
+ int16_t result);
static void stm32_req_cancel(FAR struct stm32_ep_s *privep,
int16_t status);
@@ -1163,7 +1165,7 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
* Name: stm32_rxfifo_read
*
* Description:
- * Read packet from the EP0 RxFIFO.
+ * Read packet from the RxFIFO into a read request.
*
*******************************************************************************/
@@ -1201,6 +1203,35 @@ static void stm32_rxfifo_read(FAR struct stm32_ep_s *privep,
}
/*******************************************************************************
+ * Name: stm32_rxfifo_discard
+ *
+ * Description:
+ * Discard packet data from the RxFIFO.
+ *
+ *******************************************************************************/
+
+static void stm32_rxfifo_discard(FAR struct stm32_ep_s *privep, int len)
+{
+ if (len > 0)
+ {
+ uint32_t regaddr;
+ int i;
+
+ /* Get the address of the endpoint FIFO */
+
+ regaddr = STM32_OTGFS_DFIFO_DEP(privep->epphy);
+
+ /* Read 32-bits at time */
+
+ for (i = 0; i < len; i += 4)
+ {
+ volatile uint32_t data = stm32_getreg(regaddr);
+ (void)data;
+ }
+ }
+}
+
+/*******************************************************************************
* Name: stm32_epout_complete
*
* Description:
@@ -1255,7 +1286,7 @@ static void stm32_epout_complete(FAR struct stm32_usbdev_s *priv,
* Description:
* This function is called from the RXFLVL interrupt handler when new incoming
* data is available in the endpoint's RxFIFO. This function will simply
- * copy the incoming data into pending requests data buffer.
+ * copy the incoming data into pending request's data buffer.
*
*******************************************************************************/
@@ -1266,19 +1297,37 @@ static inline void stm32_epout_receive(FAR struct stm32_ep_s *privep, int bcnt)
int buflen;
int readlen;
- /* Get a reference to the request at the head of the endpoint's request queue */
+ /* Get a reference to the request at the head of the endpoint's request
+ * queue.
+ *
+ * TODO: There is no mechanism in place to handle EP0 OUT data transfers.
+ * There are two aspects to this problem, neither are easy to fix (only
+ * because of the number of drivers that would be impacted):
+ *
+ * 1. The class drivers only send EP0 write requests and these are only
+ * queued on EP0 IN by this drivers. There is never a read request
+ * queued on EP0 OUT.
+ * 2. But EP0 OUT data could be buffered in a buffer in the driver data
+ * structure. However, there is no method currently defined in
+ * the USB device interface to obtain the EP0 data.
+ */
privreq = stm32_rqpeek(privep);
- DEBUGASSERT(privreq);
-
if (!privreq)
{
/* Incoming data is available in the RxFIFO, but there is no read setup
- * to receive the receive the data. In this case, the endpoint should have
- * been NAKing but apparently was not. The data is lost!
+ * to receive the receive the data. In this case, the endpoint should
+ * have been NAKing but apparently was not. The data is lost!
+ *
+ * NOTE: EP0 data may still be received in this case because it will
+ * not be NAKing.
*/
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTQEMPTY), privep->epphy);
+
+ /* Discard the data in the RxFIFO */
+
+ stm32_rxfifo_discard(privep, bcnt);
privep->active = false;
return;
}
@@ -1300,6 +1349,12 @@ static inline void stm32_epout_receive(FAR struct stm32_ep_s *privep, int bcnt)
stm32_rxfifo_read(privep, dest, readlen);
+ /* If there were more bytes in the RxFIFO than could be held in the read
+ * request, then we will have to discard those.
+ */
+
+ stm32_rxfifo_discard(privep, bcnt - readlen);
+
/* Update the number of bytes transferred */
privreq->req.xfrd += readlen;
@@ -2298,7 +2353,7 @@ static inline void stm32_epout_interrupt(FAR struct stm32_usbdev_s *priv)
stm32_putreg(OTGFS_DOEPINT_XFRC, STM32_OTGFS_DOEPINT(epno));
- /* Handle the RX transer data ready event */
+ /* Handle the RX transfer data ready event */
stm32_epout(priv, epno);
}