stmfx07: usb: flush txfifo if not empty after SETUP

After a SETUP packet on a control endpoint the transmit FIFO
should usually be empty.  If something bad happened, e.g. PC
and device got out of sync, we want to clear the fifo.
This should fix #668.
This commit is contained in:
Jochen Hoenicke 2016-07-05 23:39:56 +02:00 committed by Karl Palsson
parent 973efabddb
commit a4f1568b7d

View File

@ -248,6 +248,30 @@ uint16_t stm32fx07_ep_read_packet(usbd_device *usbd_dev, uint8_t addr,
return len;
}
static void stm32fx07_flush_txfifo(usbd_device *usbd_dev, int ep)
{
uint32_t fifo;
/* set IN endpoint NAK */
REBASE(OTG_DIEPCTL(ep)) |= OTG_DIEPCTL0_SNAK;
/* wait for core to respond */
while (!(REBASE(OTG_DIEPINT(ep)) & OTG_DIEPINTX_INEPNE)) {
/* idle */
}
/* get fifo for this endpoint */
fifo = (REBASE(OTG_DIEPCTL(ep)) & OTG_DIEPCTL0_TXFNUM_MASK) >> 22;
/* wait for core to idle */
while (!(REBASE(OTG_GRSTCTL) & OTG_GRSTCTL_AHBIDL)) {
/* idle */
}
/* flush tx fifo */
REBASE(OTG_GRSTCTL) = (fifo << 6) | OTG_GRSTCTL_TXFFLSH;
/* reset packet counter */
REBASE(OTG_DIEPTSIZ(ep)) = 0;
while ((REBASE(OTG_GRSTCTL) & OTG_GRSTCTL_TXFFLSH)) {
/* idle */
}
}
void stm32fx07_poll(usbd_device *usbd_dev)
{
/* Read interrupt status register. */
@ -297,6 +321,14 @@ void stm32fx07_poll(usbd_device *usbd_dev)
type = USB_TRANSACTION_OUT;
}
if (type == USB_TRANSACTION_SETUP
&& (REBASE(OTG_DIEPTSIZ(ep)) & OTG_DIEPSIZ0_PKTCNT)) {
/* SETUP received but there is still something stuck
* in the transmit fifo. Flush it.
*/
stm32fx07_flush_txfifo(usbd_dev, ep);
}
/* Save packet size for stm32f107_ep_read_packet(). */
usbd_dev->rxbcnt = (rxstsp & OTG_GRXSTSP_BCNT_MASK) >> 4;