summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2012-08-28 23:36:58 +0000
committerpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2012-08-28 23:36:58 +0000
commit64319d5b4fada128a541d5b38cd6f6372fcb4988 (patch)
treee29c2a21977726ab80f9944978b70ea82e0592cb
parent298457d9a26dcc3d7ddefdee13fdf2dca62e3b27 (diff)
I think the STM32 UST OTG FS host driver is finally finished
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@5065 7fd9a85b-ad96-42d3-883c-3090e2eb8679
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfshost.c82
2 files changed, 53 insertions, 31 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index c3c81108ed..62b05931d1 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -3211,3 +3211,5 @@
is now required to enabled strerror(). Add an option
CONFIG_LIBC_STRERROR_SHORT that can be used to output shortened
strings by strerror().
+ * arch/arm/src/stm32/stm32_usbotghost.c: Finally... the USB OTG FS
+ appears to handle NAKing correctly is complete.
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
index 6849049254..ab5ef23ec7 100644
--- a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
@@ -809,7 +809,7 @@ static void stm32_chan_halt(FAR struct stm32_usbhost_s *priv, int chidx,
uint32_t eptype;
unsigned int avail;
- /* Save the recon for the halt. We need this in the channel halt interrrupt
+ /* Save the reason for the halt. We need this in the channel halt interrrupt
* handling logic to know what to do next.
*/
@@ -1474,6 +1474,9 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen)
{
FAR struct stm32_chan_s *chan;
+ uint16_t start;
+ uint16_t elapsed;
+ size_t xfrlen;
int ret = OK;
/* Loop until the transfer completes (i.e., buflen is decremented to zero)
@@ -1481,22 +1484,19 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
*/
chan = &priv->chan[chidx];
- chan->buffer = buffer;
- chan->buflen = buflen;
+ start = stm32_getframe();
- /* There is a bug in the code at present. With debug OFF, this driver
- * overruns the typical FLASH device and there are many problems with
- * NAKS. Sticking a big delay here allows the device (FLASH drive) to
- * catch up but sacrifices driver performance.
- */
+ while (buflen > 0)
+ {
+ /* Transfer one packet at a time. The hardware is capable of queueing
+ * multiple OUT packets, but I just haven't figured out how to handle
+ * the case where a single OUT packet in the group is NAKed.
+ */
-#if !defined(CONFIG_DEBUG_VERBOSE) || !defined(CONFIG_DEBUG_USB)
-#warning "REVISIT this delay"
- usleep(50*1000);
-#endif
+ xfrlen = MIN(chan->maxpacket, buflen);
+ chan->buffer = buffer;
+ chan->buflen = xfrlen;
- while (chan->buflen > 0)
- {
/* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan);
@@ -1556,29 +1556,49 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
ret = stm32_chan_wait(priv, chan);
- /* EAGAIN indicates that the device NAKed the transfer and we need
- * do try again. NAK retries are not yet supported for OUT transfers
- * so any unsuccessful response will cause us to abort the OUT
- * transfer.
- */
+ /* Handle transfer failures */
if (ret != OK)
{
udbg("Transfer failed: %d\n", ret);
- break;
- }
- }
- /* There is a bug in the code at present. With debug OFF, this driver
- * overruns the typical FLASH device and there are many problems with
- * NAKS. Sticking a big delay here allows the device (FLASH drive) to
- * catch up but sacrifices driver performance.
- */
+ /* Check for a special case: If (1) the transfer was NAKed and (2)
+ * no Tx FIFO empty or Rx FIFO not-empty event occurred, then we
+ * should be able to just flush the Rx and Tx FIFOs and try again.
+ * We can detect this latter case becasue the then the transfer
+ * buffer pointer and buffer size will be unaltered.
+ */
-#if !defined(CONFIG_DEBUG_VERBOSE) || !defined(CONFIG_DEBUG_USB)
-#warning "REVISIT this delay"
- usleep(50*1000);
-#endif
+ elapsed = stm32_getframe() - start;
+ if (ret != -EAGAIN || /* Not a NAK condition OR */
+ elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */
+ chan->buflen != xfrlen) /* Data has been partially transferred */
+ {
+ /* Break out and return the error */
+
+ break;
+ }
+
+ /* Is this flush really necessary? What does the hardware do with the
+ * data in the FIFO when the NAK occurs? Does it discard it?
+ */
+
+ stm32_flush_txfifos(OTGFS_GRSTCTL_TXFNUM_HALL);
+
+ /* Get the device a little time to catch up. Then retry the transfer
+ * using the same buffer pointer length.
+ */
+
+ usleep(20*1000);
+ }
+ else
+ {
+ /* Successfully transferred. Update the buffer pointer and length */
+
+ buffer += xfrlen;
+ buflen -= xfrlen;
+ }
+ }
return ret;
}