STM32; OTG host implementations of stm32_in_transfer() must obey the polling interval for the case of isochronous and itnerrupt endpoints.

This commit is contained in:
Gregory Nutt
2017-03-12 08:39:30 -06:00
parent 98a98a0c8b
commit d9cdb6c383
4 changed files with 180 additions and 24 deletions
+45 -6
View File
@@ -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
+45 -6
View File
@@ -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
+45 -6
View File
@@ -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
+45 -6
View File
@@ -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