diff options
author | Jochen Hoenicke <hoenicke@gmail.com> | 2016-07-06 00:39:56 +0300 |
---|---|---|
committer | Karl Palsson <karlp@tweak.net.au> | 2017-03-31 00:48:07 +0300 |
commit | a4f1568b7d42cb5e63b19dc589de3e5914b2c6f7 (patch) | |
tree | 923156a4f0834b644198ce23da9eb8fe8070a115 /lib/usb | |
parent | 973efabddb56fc8454c1e27397d2a0a04064a18c (diff) |
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.
Diffstat (limited to 'lib/usb')
-rw-r--r-- | lib/usb/usb_fx07_common.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/lib/usb/usb_fx07_common.c b/lib/usb/usb_fx07_common.c index f09416cd..8e57f167 100644 --- a/lib/usb/usb_fx07_common.c +++ b/lib/usb/usb_fx07_common.c @@ -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; |