diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-08-27 19:23:40 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-08-27 19:23:40 +0000 |
commit | 645bd0a83bed8cc38fbf8fdd51f72217c69d9e5f (patch) | |
tree | 0e8f349ae4c03539e3dbd4036a73f8ad07f726cb /nuttx | |
parent | 5143ed1c74e8f1817a7a8b62321cfe9a288741be (diff) | |
download | px4-nuttx-645bd0a83bed8cc38fbf8fdd51f72217c69d9e5f.tar.gz px4-nuttx-645bd0a83bed8cc38fbf8fdd51f72217c69d9e5f.tar.bz2 px4-nuttx-645bd0a83bed8cc38fbf8fdd51f72217c69d9e5f.zip |
Fix some NAK race conditions in control transfers (there are more)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5058 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/ChangeLog | 8 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_otgfshost.c | 147 |
2 files changed, 103 insertions, 52 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index c4e914658..192af9dc3 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 0b09070dc..61f2640d4 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; |