summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nuttx/ChangeLog8
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfshost.c147
2 files changed, 103 insertions, 52 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index c4e914658e..192af9dc35 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -3192,4 +3192,12 @@
* arch/arm/src/lpc17xx/lpc17_ethernet.c: Conditionally elide setting PHY
speed/duplex. This does not work for certain PHYs. Still some unresolved
issues (also from Kate).
+ * tools/Config.mk, Makefile, configs/*/Make.defs: Add a new Makefile
+ fragement to de-quoate certain strings from the Kconfig logic that
+ need to be used at path segments (Richard Cochran).
+ * arch/arm/src/stm32/stm32_usbotghost.c: The STM32 USB host driver only
+ works with debug turned on. The problem appears to be that with debug
+ OFF, there are more NAKs occuring in more places than before and this
+ reveals a variety of errors. This check in improves NAK robustness
+ for control transfers but does not resolve all of the issues.
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
index 0b09070dc6..61f2640d4e 100644
--- a/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfshost.c
@@ -141,14 +141,15 @@
#define STM32_EP0_MAX_PACKET_SIZE 64 /* EP0 FS max packet size */
#define STM32_MAX_TX_FIFOS 15 /* Max number of TX FIFOs */
#define STM32_MAX_PKTCOUNT 256 /* Max packet count */
-#define STM32_RETRY_COUNT 3 /* Number of retries */
+#define STM32_RETRY_COUNT 3 /* Number of ctrl transfer retries */
#define STM32_DEF_DEVADDR 0 /* Default device address */
/* Delays **********************************************************************/
-#define STM32_READY_DELAY 200000 /* In loop counts */
-#define STM32_FLUSH_DELAY 200000 /* In loop counts */
-#define STM32_NOTREADY_DELAY 5000 /* In frames */
+#define STM32_READY_DELAY 200000 /* In loop counts */
+#define STM32_FLUSH_DELAY 200000 /* In loop counts */
+#define STM32_SETUP_DELAY 5000 /* In frames */
+#define STM32_DATANAK_DELAY 5000 /* In frames */
/* Ever-present MIN/MAX macros */
@@ -376,10 +377,11 @@ static void stm32_disconnect(FAR struct usbhost_driver_s *drvr);
/* Initialization **************************************************************/
static void stm32_portreset(FAR struct stm32_usbhost_s *priv);
-static inline void stm32_flush_txfifos(uint32_t txfnum);
-static inline void stm32_flush_rxfifo(void);
+static void stm32_flush_txfifos(uint32_t txfnum);
+static void stm32_flush_rxfifo(void);
static void stm32_vbusdrive(FAR struct stm32_usbhost_s *priv, bool state);
static void stm32_host_initialize(FAR struct stm32_usbhost_s *priv);
+
static inline void stm32_sw_initialize(FAR struct stm32_usbhost_s *priv);
static inline int stm32_hw_initialize(FAR struct stm32_usbhost_s *priv);
@@ -1196,14 +1198,15 @@ static int stm32_ctrl_sendsetup(FAR struct stm32_usbhost_s *priv,
FAR const struct usb_ctrlreq_s *req)
{
FAR struct stm32_chan_s *chan;
- uint16_t start = stm32_getframe();
+ uint16_t start;
uint16_t elapsed;
int ret;
- chan = &priv->chan[priv->ep0out];
-
/* Loop while the device reports NAK (and a timeout is not exceeded */
+ chan = &priv->chan[priv->ep0out];
+ start = stm32_getframe();
+
do
{
/* Send the SETUP packet */
@@ -1248,11 +1251,11 @@ static int stm32_ctrl_sendsetup(FAR struct stm32_usbhost_s *priv,
return ret;
}
- /* Get the elpased time (in frames) */
+ /* Get the elapsed time (in frames) */
elapsed = stm32_getframe() - start;
}
- while (elapsed < STM32_NOTREADY_DELAY);
+ while (elapsed < STM32_SETUP_DELAY);
return -ETIMEDOUT;
}
@@ -3284,6 +3287,8 @@ static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr,
{
struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
uint16_t buflen;
+ uint16_t start;
+ uint16_t elapsed;
int retries;
int ret;
@@ -3300,7 +3305,7 @@ static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr,
stm32_takesem(&priv->exclsem);
- /* Loop, retrying until the retry count expires */
+ /* Loop, retrying until the retry time expires */
for (retries = 0; retries < STM32_RETRY_COUNT; retries++)
{
@@ -3308,38 +3313,55 @@ static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr,
ret = stm32_ctrl_sendsetup(priv, req);
if (ret < 0)
- {
+ {
udbg("stm32_ctrl_sendsetup failed: %d\n", ret);
- return ret;
+ continue;
}
- /* Handle the IN data phase (if any) */
+ /* Get the start time. Loop again until the timeout expires */
- if (buflen > 0)
+ start = stm32_getframe();
+ do
{
- ret = stm32_ctrl_recvdata(priv, buffer, buflen);
- if (ret < 0)
+ /* Handle the IN data phase (if any) */
+
+ if (buflen > 0)
{
- udbg("stm32_ctrl_recvdata failed: %d\n", ret);
- continue;
+ ret = stm32_ctrl_recvdata(priv, buffer, buflen);
+ if (ret < 0)
+ {
+ udbg("stm32_ctrl_recvdata failed: %d\n", ret);
+ }
}
- }
- /* Handle the status OUT phase */
+ /* Handle the status OUT phase */
- priv->chan[priv->ep0out].outdata1 ^= true;
- ret = stm32_ctrl_senddata(priv, NULL, 0);
- if (ret == OK)
- {
- break;
- }
+ if (ret == OK)
+ {
+ priv->chan[priv->ep0out].outdata1 ^= true;
+ ret = stm32_ctrl_senddata(priv, NULL, 0);
+ if (ret == OK)
+ {
+ /* All success transactions exit here */
+
+ stm32_givesem(&priv->exclsem);
+ return OK;
+ }
- udbg("stm32_ctrl_senddata failed: %d\n", ret);
- ret = -ETIMEDOUT;
+ udbg("stm32_ctrl_senddata failed: %d\n", ret);
+ }
+
+ /* Get the elapsed time (in frames) */
+
+ elapsed = stm32_getframe() - start;
+ }
+ while (elapsed < STM32_DATANAK_DELAY);
}
+ /* All failures exit here after all retries and timeouts have been exhausted */
+
stm32_givesem(&priv->exclsem);
- return ret;
+ return -ETIMEDOUT;
}
static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr,
@@ -3348,6 +3370,8 @@ static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr,
{
struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
uint16_t buflen;
+ uint16_t start;
+ uint16_t elapsed;
int retries;
int ret;
@@ -3364,12 +3388,14 @@ static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr,
stm32_takesem(&priv->exclsem);
- /* Loop, retrying until the retry count expires */
+ /* Loop, retrying until the retry time expires */
for (retries = 0; retries < STM32_RETRY_COUNT; retries++)
{
/* Send the SETUP request */
+ /* Send the SETUP request */
+
ret = stm32_ctrl_sendsetup(priv, req);
if (ret < 0)
{
@@ -3377,35 +3403,52 @@ static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr,
continue;
}
- /* Handle the data OUT phase (if any) */
+ /* Get the start time. Loop again until the timeout expires */
- if (buflen > 0)
+ start = stm32_getframe();
+ do
{
- /* Start DATA out transfer (only one DATA packet) */
+ /* Handle the data OUT phase (if any) */
- priv->chan[priv->ep0out].outdata1 = true;
- ret = stm32_ctrl_senddata(priv, NULL, 0);
- if (ret < 0)
+ if (buflen > 0)
{
- udbg("stm32_ctrl_senddata failed: %d\n", ret);
- continue;
+ /* Start DATA out transfer (only one DATA packet) */
+
+ priv->chan[priv->ep0out].outdata1 = true;
+ ret = stm32_ctrl_senddata(priv, NULL, 0);
+ if (ret < 0)
+ {
+ udbg("stm32_ctrl_senddata failed: %d\n", ret);
+ }
}
- }
- /* Handle the status IN phase */
+ /* Handle the status IN phase */
- ret = stm32_ctrl_recvdata(priv, NULL, 0);
- if (ret == OK)
- {
- break;
- }
+ if (ret == OK)
+ {
+ ret = stm32_ctrl_recvdata(priv, NULL, 0);
+ if (ret == OK)
+ {
+ /* All success transactins exit here */
- udbg("stm32_ctrl_recvdata failed: %d\n", ret);
- ret = -ETIMEDOUT;
+ stm32_givesem(&priv->exclsem);
+ return OK;
+ }
+
+ udbg("stm32_ctrl_recvdata failed: %d\n", ret);
+ }
+
+ /* Get the elapsed time (in frames) */
+
+ elapsed = stm32_getframe() - start;
+ }
+ while (elapsed < STM32_DATANAK_DELAY);
}
+ /* All failures exit here after all retries and timeouts have been exhausted */
+
stm32_givesem(&priv->exclsem);
- return ret;
+ return -ETIMEDOUT;
}
/*******************************************************************************
@@ -3660,7 +3703,7 @@ static void stm32_portreset(FAR struct stm32_usbhost_s *priv)
*
*******************************************************************************/
-static inline void stm32_flush_txfifos(uint32_t txfnum)
+static void stm32_flush_txfifos(uint32_t txfnum)
{
uint32_t regval;
uint32_t timeout;
@@ -3700,7 +3743,7 @@ static inline void stm32_flush_txfifos(uint32_t txfnum)
*
*******************************************************************************/
-static inline void stm32_flush_rxfifo(void)
+static void stm32_flush_rxfifo(void)
{
uint32_t regval;
uint32_t timeout;