diff --git a/arch/arm/src/stm32/stm32_otgfshost.c b/arch/arm/src/stm32/stm32_otgfshost.c index 7451289b277..2163b2eae9a 100644 --- a/arch/arm/src/stm32/stm32_otgfshost.c +++ b/arch/arm/src/stm32/stm32_otgfshost.c @@ -212,6 +212,7 @@ struct stm32_chan_s uint8_t eptype; /* See OTGFS_EPTYPE_* definitions */ uint8_t funcaddr; /* Device function address */ uint8_t speed; /* Device speed */ + uint8_t interval; /* Interrupt/isochronous EP polling interval */ uint8_t pid; /* Data PID */ uint8_t npackets; /* Number of packets (for data toggle) */ bool inuse; /* True: This channel is "in use" */ @@ -1210,6 +1211,7 @@ static int stm32_ctrlchan_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = OTGFS_EPTYPE_CTRL; chan->funcaddr = funcaddr; chan->speed = speed; + chan->interval = 0; chan->maxpacket = STM32_EP0_DEF_PACKET_SIZE; chan->indata1 = false; chan->outdata1 = false; @@ -1234,6 +1236,7 @@ static int stm32_ctrlchan_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = OTGFS_EPTYPE_CTRL; chan->funcaddr = funcaddr; chan->speed = speed; + chan->interval = 0; chan->maxpacket = STM32_EP0_DEF_PACKET_SIZE; chan->indata1 = false; chan->outdata1 = false; @@ -1363,6 +1366,7 @@ static int stm32_xfrep_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = epdesc->xfrtype; chan->funcaddr = hport->funcaddr; chan->speed = hport->speed; + chan->interval = epdesc->interval; chan->maxpacket = epdesc->mxpacketsize; chan->indata1 = false; chan->outdata1 = false; @@ -1893,6 +1897,8 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, } else { + useconds_t delay; + /* Get the elapsed time. Has the timeout elapsed? * if not then try again. */ @@ -1907,13 +1913,46 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, return (ssize_t)ret; } - /* Wait a bit before retrying after a NAK. - * - * REVISIT: This is intended to give the CPU a break from - * the tight polling loop. But are there performance issues? - */ + /* Wait a bit before retrying after a NAK. */ - usleep(1000); + if (chan->eptype == OTGFS_HCCHAR_EPTYP_INTR) + { + /* For interrupt (and isochronous) endpoints, the + * polling rate is determined by the bInterval field + * of the endpoint descriptor (in units of frames + * which we treat as milliseconds here). + */ + + if (chan->interval > 0) + { + /* Convert the delay to units of microseconds */ + + delay = (useconds_t)chan->interval * 1000; + } + else + { + /* Out of range! For interrupt endpoints, the valid + * range is 1-255 frames. Assume one frame. + */ + + delay = 1000; + } + } + else + { + /* For Isochronous endpoints, bInterval must be 1. Bulk + * endpoints do not have a polling interval. Rather, + * the should wait until data is received. + * + * REVISIT: For bulk endpoints this 1 msec delay is only + * intended to give the CPU a break from the bulk EP tight + * polling loop. But are there performance issues? + */ + + delay = 1000; + } + + usleep(delay); } } else diff --git a/arch/arm/src/stm32/stm32_otghshost.c b/arch/arm/src/stm32/stm32_otghshost.c index 85092d89a96..7f16593f630 100644 --- a/arch/arm/src/stm32/stm32_otghshost.c +++ b/arch/arm/src/stm32/stm32_otghshost.c @@ -217,6 +217,7 @@ struct stm32_chan_s uint8_t eptype; /* See OTGHS_EPTYPE_* definitions */ uint8_t funcaddr; /* Device function address */ uint8_t speed; /* Device speed */ + uint8_t interval; /* Interrupt/isochronous EP polling interval */ uint8_t pid; /* Data PID */ uint8_t npackets; /* Number of packets (for data toggle) */ bool inuse; /* True: This channel is "in use" */ @@ -1215,6 +1216,7 @@ static int stm32_ctrlchan_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = OTGHS_EPTYPE_CTRL; chan->funcaddr = funcaddr; chan->speed = speed; + chan->interval = 0; chan->maxpacket = STM32_EP0_DEF_PACKET_SIZE; chan->indata1 = false; chan->outdata1 = false; @@ -1239,6 +1241,7 @@ static int stm32_ctrlchan_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = OTGHS_EPTYPE_CTRL; chan->funcaddr = funcaddr; chan->speed = speed; + chan->interval = 0; chan->maxpacket = STM32_EP0_DEF_PACKET_SIZE; chan->indata1 = false; chan->outdata1 = false; @@ -1368,6 +1371,7 @@ static int stm32_xfrep_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = epdesc->xfrtype; chan->funcaddr = hport->funcaddr; chan->speed = hport->speed; + chan->interval = epdesc->interval; chan->maxpacket = epdesc->mxpacketsize; chan->indata1 = false; chan->outdata1 = false; @@ -1898,6 +1902,8 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, } else { + useconds_t delay; + /* Get the elapsed time. Has the timeout elapsed? * if not then try again. */ @@ -1912,13 +1918,46 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, return (ssize_t)ret; } - /* Wait a bit before retrying after a NAK. - * - * REVISIT: This is intended to give the CPU a break from - * the tight polling loop. But are there performance issues? - */ + /* Wait a bit before retrying after a NAK. */ - usleep(1000); + if (chan->eptype == OTGFS_HCCHAR_EPTYP_INTR) + { + /* For interrupt (and isochronous) endpoints, the + * polling rate is determined by the bInterval field + * of the endpoint descriptor (in units of frames + * which we treat as milliseconds here). + */ + + if (chan->interval > 0) + { + /* Convert the delay to units of microseconds */ + + delay = (useconds_t)chan->interval * 1000; + } + else + { + /* Out of range! For interrupt endpoints, the valid + * range is 1-255 frames. Assume one frame. + */ + + delay = 1000; + } + } + else + { + /* For Isochronous endpoints, bInterval must be 1. Bulk + * endpoints do not have a polling interval. Rather, + * the should wait until data is received. + * + * REVISIT: For bulk endpoints this 1 msec delay is only + * intended to give the CPU a break from the bulk EP tight + * polling loop. But are there performance issues? + */ + + delay = 1000; + } + + usleep(delay); } } else diff --git a/arch/arm/src/stm32f7/stm32_otghost.c b/arch/arm/src/stm32f7/stm32_otghost.c index a89be679b9b..0d2dfd24c88 100644 --- a/arch/arm/src/stm32f7/stm32_otghost.c +++ b/arch/arm/src/stm32f7/stm32_otghost.c @@ -214,6 +214,7 @@ struct stm32_chan_s uint8_t eptype; /* See OTG_EPTYPE_* definitions */ uint8_t funcaddr; /* Device function address */ uint8_t speed; /* Device speed */ + uint8_t interval; /* Interrupt/isochronous EP polling interval */ uint8_t pid; /* Data PID */ uint8_t npackets; /* Number of packets (for data toggle) */ bool inuse; /* True: This channel is "in use" */ @@ -1209,6 +1210,7 @@ static int stm32_ctrlchan_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = OTG_EPTYPE_CTRL; chan->funcaddr = funcaddr; chan->speed = speed; + chan->interval = 0; chan->maxpacket = STM32_EP0_DEF_PACKET_SIZE; chan->indata1 = false; chan->outdata1 = false; @@ -1233,6 +1235,7 @@ static int stm32_ctrlchan_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = OTG_EPTYPE_CTRL; chan->funcaddr = funcaddr; chan->speed = speed; + chan->interval = 0; chan->maxpacket = STM32_EP0_DEF_PACKET_SIZE; chan->indata1 = false; chan->outdata1 = false; @@ -1362,6 +1365,7 @@ static int stm32_xfrep_alloc(FAR struct stm32_usbhost_s *priv, chan->eptype = epdesc->xfrtype; chan->funcaddr = hport->funcaddr; chan->speed = hport->speed; + chan->interval = epdesc->interval; chan->maxpacket = epdesc->mxpacketsize; chan->indata1 = false; chan->outdata1 = false; @@ -1892,6 +1896,8 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, } else { + useconds_t delay; + /* Get the elapsed time. Has the timeout elapsed? * if not then try again. */ @@ -1906,13 +1912,46 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, return (ssize_t)ret; } - /* Wait a bit before retrying after a NAK. - * - * REVISIT: This is intended to give the CPU a break from - * the tight polling loop. But are there performance issues? - */ + /* Wait a bit before retrying after a NAK. */ - usleep(1000); + if (chan->eptype == OTGFS_HCCHAR_EPTYP_INTR) + { + /* For interrupt (and isochronous) endpoints, the + * polling rate is determined by the bInterval field + * of the endpoint descriptor (in units of frames + * which we treat as milliseconds here). + */ + + if (chan->interval > 0) + { + /* Convert the delay to units of microseconds */ + + delay = (useconds_t)chan->interval * 1000; + } + else + { + /* Out of range! For interrupt endpoints, the valid + * range is 1-255 frames. Assume one frame. + */ + + delay = 1000; + } + } + else + { + /* For Isochronous endpoints, bInterval must be 1. Bulk + * endpoints do not have a polling interval. Rather, + * the should wait until data is received. + * + * REVISIT: For bulk endpoints this 1 msec delay is only + * intended to give the CPU a break from the bulk EP tight + * polling loop. But are there performance issues? + */ + + delay = 1000; + } + + usleep(delay); } } else diff --git a/arch/arm/src/stm32l4/stm32l4_otgfshost.c b/arch/arm/src/stm32l4/stm32l4_otgfshost.c index a488825b9c7..5b62256f145 100644 --- a/arch/arm/src/stm32l4/stm32l4_otgfshost.c +++ b/arch/arm/src/stm32l4/stm32l4_otgfshost.c @@ -213,6 +213,7 @@ struct stm32l4_chan_s uint8_t eptype; /* See OTGFS_EPTYPE_* definitions */ uint8_t funcaddr; /* Device function address */ uint8_t speed; /* Device speed */ + uint8_t interval; /* Interrupt/isochronous EP polling interval */ uint8_t pid; /* Data PID */ uint8_t npackets; /* Number of packets (for data toggle) */ bool inuse; /* True: This channel is "in use" */ @@ -1212,6 +1213,7 @@ static int stm32l4_ctrlchan_alloc(FAR struct stm32l4_usbhost_s *priv, chan->eptype = OTGFS_EPTYPE_CTRL; chan->funcaddr = funcaddr; chan->speed = speed; + chan->interval = 0; chan->maxpacket = STM32L4_EP0_DEF_PACKET_SIZE; chan->indata1 = false; chan->outdata1 = false; @@ -1236,6 +1238,7 @@ static int stm32l4_ctrlchan_alloc(FAR struct stm32l4_usbhost_s *priv, chan->eptype = OTGFS_EPTYPE_CTRL; chan->funcaddr = funcaddr; chan->speed = speed; + chan->interval = 0; chan->maxpacket = STM32L4_EP0_DEF_PACKET_SIZE; chan->indata1 = false; chan->outdata1 = false; @@ -1365,6 +1368,7 @@ static int stm32l4_xfrep_alloc(FAR struct stm32l4_usbhost_s *priv, chan->eptype = epdesc->xfrtype; chan->funcaddr = hport->funcaddr; chan->speed = hport->speed; + chan->interval = epdesc->interval; chan->maxpacket = epdesc->mxpacketsize; chan->indata1 = false; chan->outdata1 = false; @@ -1897,6 +1901,8 @@ static ssize_t stm32l4_in_transfer(FAR struct stm32l4_usbhost_s *priv, } else { + useconds_t delay; + /* Get the elapsed time. Has the timeout elapsed? * if not then try again. */ @@ -1911,13 +1917,46 @@ static ssize_t stm32l4_in_transfer(FAR struct stm32l4_usbhost_s *priv, return (ssize_t)ret; } - /* Wait a bit before retrying after a NAK. - * - * REVISIT: This is intended to give the CPU a break from - * the tight polling loop. But are there performance issues? - */ + /* Wait a bit before retrying after a NAK. */ - usleep(1000); + if (chan->eptype == OTGFS_HCCHAR_EPTYP_INTR) + { + /* For interrupt (and isochronous) endpoints, the + * polling rate is determined by the bInterval field + * of the endpoint descriptor (in units of frames + * which we treat as milliseconds here). + */ + + if (chan->interval > 0) + { + /* Convert the delay to units of microseconds */ + + delay = (useconds_t)chan->interval * 1000; + } + else + { + /* Out of range! For interrupt endpoints, the valid + * range is 1-255 frames. Assume one frame. + */ + + delay = 1000; + } + } + else + { + /* For Isochronous endpoints, bInterval must be 1. Bulk + * endpoints do not have a polling interval. Rather, + * the should wait until data is received. + * + * REVISIT: For bulk endpoints this 1 msec delay is only + * intended to give the CPU a break from the bulk EP tight + * polling loop. But are there performance issues? + */ + + delay = 1000; + } + + usleep(delay); } } else