Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/thirdpin/libopencm3.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib/usb
diff options
context:
space:
mode:
authorJochen Hoenicke <hoenicke@gmail.com>2016-07-06 00:39:56 +0300
committerKarl Palsson <karlp@tweak.net.au>2017-03-31 00:48:07 +0300
commita4f1568b7d42cb5e63b19dc589de3e5914b2c6f7 (patch)
tree923156a4f0834b644198ce23da9eb8fe8070a115 /lib/usb
parent973efabddb56fc8454c1e27397d2a0a04064a18c (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.c32
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;