summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/arch/arm/src/sama5/sam_udphs.c21
2 files changed, 19 insertions, 4 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 6b5db2577..546bd402b 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -7145,4 +7145,6 @@
* nuttx/arch/arm/src/armv7-a/mmu.h: Bufferable bit did not do what
I thought it was going to do. Result was the NOR FLASH accesses
were very slow (2014-4-3).
+ * arch/arm/src/sama5/sam_udphs.c: Fix a case where received status
+ was not clear, causing OUT SETUP commands to fail (2014-4-6).
diff --git a/nuttx/arch/arm/src/sama5/sam_udphs.c b/nuttx/arch/arm/src/sama5/sam_udphs.c
index d71abc82c..96356dfe7 100644
--- a/nuttx/arch/arm/src/sama5/sam_udphs.c
+++ b/nuttx/arch/arm/src/sama5/sam_udphs.c
@@ -2587,7 +2587,9 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno)
((eptsta & UDPHS_EPTSTA_BYTECNT_MASK) >>
UDPHS_EPTSTA_BYTECNT_SHIFT);
- /* And continue processing the read request */
+ /* And continue processing the read request, clearing RXRDYTXKL in
+ * order to receive more data.
+ */
privep->epstate = UDPHS_EPSTATE_IDLE;
sam_req_read(priv, privep, pktsize);
@@ -2615,9 +2617,12 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno)
len = GETUINT16(priv->ctrl.len);
if (len == pktsize)
{
- /* Copy the OUT data from the EP0 FIFO into special EP0 buffer. */
+ /* Copy the OUT data from the EP0 FIFO into special EP0 buffer
+ * and clear RXRDYTXKL in order to receive more data.
+ */
sam_ep0_read(priv->ep0out, len);
+ sam_putreg(UDPHS_EPTSTA_RXRDYTXKL, SAM_UDPHS_EPTCLRSTA(epno));
/* And handle the EP0 SETUP now. */
@@ -2626,7 +2631,11 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno)
else
{
usbtrace(TRACE_DEVERROR(SAM_TRACEERR_EP0SETUPOUTSIZE), pktsize);
+
+ /* STALL and discard received data. */
+
(void)sam_ep_stall(&privep->ep, false);
+ sam_putreg(UDPHS_EPTSTA_RXRDYTXKL, SAM_UDPHS_EPTCLRSTA(epno));
}
}
else
@@ -2636,14 +2645,12 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno)
if (eptype == UDPHS_EPTCFG_TYPE_CTRL8 &&
(eptsta & UDPHS_EPTSTA_BYTECNT_MASK) == 0)
{
- sam_putreg(UDPHS_EPTSTA_RXRDYTXKL, SAM_UDPHS_EPTCLRSTA(epno));
}
/* Data has been STALLed */
else if ((eptsta & UDPHS_EPTSTA_FRCESTALL) != 0)
{
- sam_putreg(UDPHS_EPTSTA_RXRDYTXKL, SAM_UDPHS_EPTCLRSTA(epno));
}
/* NAK the data */
@@ -2654,6 +2661,12 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno)
regval &= ~UDPHS_INT_EPT(epno);
sam_putreg(regval, SAM_UDPHS_IEN);
}
+
+ /* Discard any received data and clear UDPHS_EPTSTA_RXRDYTXKL so that we
+ * may receive more data.
+ */
+
+ sam_putreg(UDPHS_EPTSTA_RXRDYTXKL, SAM_UDPHS_EPTCLRSTA(epno));
}
}