summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sidrane <david_s5@nscdg.com>2015-04-25 06:18:48 -1000
committerDavid Sidrane <david_s5@nscdg.com>2015-04-25 06:18:48 -1000
commitb5de8a25fac53b96216fc66cc2ca555eaae411f3 (patch)
treed2c951822dd4845b564db50a8e2cd9b7dd3aa473
parent94818ce16f63c4728a1d9316628a3651287f16df (diff)
downloadpx4-nuttx-b5de8a25fac53b96216fc66cc2ca555eaae411f3.tar.gz
px4-nuttx-b5de8a25fac53b96216fc66cc2ca555eaae411f3.tar.bz2
px4-nuttx-b5de8a25fac53b96216fc66cc2ca555eaae411f3.zip
Workaround for bad values read from the STM32_OTGFS_GRXSTSP register are 0xb4e48168 or 0xa80c9367 or 267E781c All of which provide out of range indexes for epout[epphy]master_usb_fix
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfsdev.c260
1 files changed, 134 insertions, 126 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
index 10fdc75bb..4caf460e6 100644
--- a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
@@ -3123,134 +3123,142 @@ static inline void stm32_rxinterrupt(FAR struct stm32_usbdev_s *priv)
/* Decode status fields */
epphy = (regval & OTGFS_GRXSTSD_EPNUM_MASK) >> OTGFS_GRXSTSD_EPNUM_SHIFT;
- privep = &priv->epout[epphy];
- /* Handle the RX event according to the packet status field */
-
- switch (regval & OTGFS_GRXSTSD_PKTSTS_MASK)
- {
- /* Global OUT NAK. This indicate that the global OUT NAK bit has taken
- * effect.
- *
- * PKTSTS = Global OUT NAK, BCNT = 0, EPNUM = Don't Care, DPID = Don't
- * Care.
- */
-
- case OTGFS_GRXSTSD_PKTSTS_OUTNAK:
- {
- usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTNAK), 0);
- }
- break;
-
- /* OUT data packet received.
- *
- * PKTSTS = DataOUT, BCNT = size of the received data OUT packet,
- * EPNUM = EPNUM on which the packet was received, DPID = Actual Data PID.
- */
-
- case OTGFS_GRXSTSD_PKTSTS_OUTRECVD:
- {
- usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTRECVD), epphy);
- bcnt = (regval & OTGFS_GRXSTSD_BCNT_MASK) >> OTGFS_GRXSTSD_BCNT_SHIFT;
- if (bcnt > 0)
- {
- stm32_epout_receive(privep, bcnt);
- }
- }
- break;
-
- /* OUT transfer completed. This indicates that an OUT data transfer for
- * the specified OUT endpoint has completed. After this entry is popped
- * from the receive FIFO, the core asserts a Transfer Completed interrupt
- * on the specified OUT endpoint.
- *
- * PKTSTS = Data OUT Transfer Done, BCNT = 0, EPNUM = OUT EP Num on
- * which the data transfer is complete, DPID = Don't Care.
- */
-
- case OTGFS_GRXSTSD_PKTSTS_OUTDONE:
- {
- usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTDONE), epphy);
- }
- break;
-
- /* SETUP transaction completed. This indicates that the Setup stage for
- * the specified endpoint has completed and the Data stage has started.
- * After this entry is popped from the receive FIFO, the core asserts a
- * Setup interrupt on the specified control OUT endpoint (triggers an
- * interrupt).
- *
- * PKTSTS = Setup Stage Done, BCNT = 0, EPNUM = Control EP Num,
- * DPID = Don't Care.
- */
-
- case OTGFS_GRXSTSD_PKTSTS_SETUPDONE:
- {
- usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPDONE), epphy);
- }
- break;
-
- /* SETUP data packet received. This indicates that a SETUP packet for the
- * specified endpoint is now available for reading from the receive FIFO.
- *
- * PKTSTS = SETUP, BCNT = 8, EPNUM = Control EP Num, DPID = D0.
- */
-
- case OTGFS_GRXSTSD_PKTSTS_SETUPRECVD:
- {
- uint16_t datlen;
-
- usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPRECVD), epphy);
-
- /* Read EP0 setup data. NOTE: If multiple SETUP packets are received,
- * the last one overwrites the previous setup packets and only that
- * last SETUP packet will be processed.
- */
-
- stm32_rxfifo_read(&priv->epout[EP0], (FAR uint8_t*)&priv->ctrlreq,
- USB_SIZEOF_CTRLREQ);
-
- /* Was this an IN or an OUT SETUP packet. If it is an OUT SETUP,
- * then we need to wait for the completion of the data phase to
- * process the setup command. If it is an IN SETUP packet, then
- * we must processing the command BEFORE we enter the DATA phase.
- *
- * If the data associated with the OUT SETUP packet is zero length,
- * then, of course, we don't need to wait.
- */
-
- datlen = GETUINT16(priv->ctrlreq.len);
- if (USB_REQ_ISOUT(priv->ctrlreq.type) && datlen > 0)
- {
- /* Clear NAKSTS so that we can receive the data */
-
- regval = stm32_getreg(STM32_OTGFS_DOEPCTL0);
- regval |= OTGFS_DOEPCTL0_CNAK;
- stm32_putreg(regval, STM32_OTGFS_DOEPCTL0);
-
- /* Wait for the data phase. */
-
- priv->ep0state = EP0STATE_SETUP_OUT;
- }
- else
- {
- /* We can process the setup data as soon as SETUP done word is
- * popped of the RxFIFO.
- */
-
- priv->ep0state = EP0STATE_SETUP_READY;
- }
- }
- break;
-
- default:
- {
- usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS),
- (regval & OTGFS_GRXSTSD_PKTSTS_MASK) >> OTGFS_GRXSTSD_PKTSTS_SHIFT);
- }
- break;
- }
+ /* Workaround for bad values read from the STM32_OTGFS_GRXSTSP register
+ * happens regval is 0xb4e48168 or 0xa80c9367 or 267E781c
+ * All of which provide out of range indexes for epout[epphy]
+ */
+ if (epphy < STM32_NENDPOINTS)
+ {
+ privep = &priv->epout[epphy];
+
+ /* Handle the RX event according to the packet status field */
+
+ switch (regval & OTGFS_GRXSTSD_PKTSTS_MASK)
+ {
+ /* Global OUT NAK. This indicate that the global OUT NAK bit has taken
+ * effect.
+ *
+ * PKTSTS = Global OUT NAK, BCNT = 0, EPNUM = Don't Care, DPID = Don't
+ * Care.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_OUTNAK:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTNAK), 0);
+ }
+ break;
+
+ /* OUT data packet received.
+ *
+ * PKTSTS = DataOUT, BCNT = size of the received data OUT packet,
+ * EPNUM = EPNUM on which the packet was received, DPID = Actual Data PID.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_OUTRECVD:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTRECVD), epphy);
+ bcnt = (regval & OTGFS_GRXSTSD_BCNT_MASK) >> OTGFS_GRXSTSD_BCNT_SHIFT;
+ if (bcnt > 0)
+ {
+ stm32_epout_receive(privep, bcnt);
+ }
+ }
+ break;
+
+ /* OUT transfer completed. This indicates that an OUT data transfer for
+ * the specified OUT endpoint has completed. After this entry is popped
+ * from the receive FIFO, the core asserts a Transfer Completed interrupt
+ * on the specified OUT endpoint.
+ *
+ * PKTSTS = Data OUT Transfer Done, BCNT = 0, EPNUM = OUT EP Num on
+ * which the data transfer is complete, DPID = Don't Care.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_OUTDONE:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_OUTDONE), epphy);
+ }
+ break;
+
+ /* SETUP transaction completed. This indicates that the Setup stage for
+ * the specified endpoint has completed and the Data stage has started.
+ * After this entry is popped from the receive FIFO, the core asserts a
+ * Setup interrupt on the specified control OUT endpoint (triggers an
+ * interrupt).
+ *
+ * PKTSTS = Setup Stage Done, BCNT = 0, EPNUM = Control EP Num,
+ * DPID = Don't Care.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_SETUPDONE:
+ {
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPDONE), epphy);
+ }
+ break;
+
+ /* SETUP data packet received. This indicates that a SETUP packet for the
+ * specified endpoint is now available for reading from the receive FIFO.
+ *
+ * PKTSTS = SETUP, BCNT = 8, EPNUM = Control EP Num, DPID = D0.
+ */
+
+ case OTGFS_GRXSTSD_PKTSTS_SETUPRECVD:
+ {
+ uint16_t datlen;
+
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_SETUPRECVD), epphy);
+
+ /* Read EP0 setup data. NOTE: If multiple SETUP packets are received,
+ * the last one overwrites the previous setup packets and only that
+ * last SETUP packet will be processed.
+ */
+
+ stm32_rxfifo_read(&priv->epout[EP0], (FAR uint8_t*)&priv->ctrlreq,
+ USB_SIZEOF_CTRLREQ);
+
+ /* Was this an IN or an OUT SETUP packet. If it is an OUT SETUP,
+ * then we need to wait for the completion of the data phase to
+ * process the setup command. If it is an IN SETUP packet, then
+ * we must processing the command BEFORE we enter the DATA phase.
+ *
+ * If the data associated with the OUT SETUP packet is zero length,
+ * then, of course, we don't need to wait.
+ */
+
+ datlen = GETUINT16(priv->ctrlreq.len);
+ if (USB_REQ_ISOUT(priv->ctrlreq.type) && datlen > 0)
+ {
+ /* Clear NAKSTS so that we can receive the data */
+
+ regval = stm32_getreg(STM32_OTGFS_DOEPCTL0);
+ regval |= OTGFS_DOEPCTL0_CNAK;
+ stm32_putreg(regval, STM32_OTGFS_DOEPCTL0);
+
+ /* Wait for the data phase. */
+
+ priv->ep0state = EP0STATE_SETUP_OUT;
+ }
+ else
+ {
+ /* We can process the setup data as soon as SETUP done word is
+ * popped of the RxFIFO.
+ */
+
+ priv->ep0state = EP0STATE_SETUP_READY;
+ }
+ }
+ break;
+
+ default:
+ {
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS),
+ (regval & OTGFS_GRXSTSD_PKTSTS_MASK) >> OTGFS_GRXSTSD_PKTSTS_SHIFT);
+ }
+ break;
+ }
+ }
/* Enable the Rx Status Queue Level interrupt */
regval = stm32_getreg(STM32_OTGFS_GINTMSK);