aboutsummaryrefslogtreecommitdiff
path: root/lib/usb
diff options
context:
space:
mode:
authorGareth McMullin2011-10-30 20:19:29 +1300
committerPiotr Esden-Tempski2011-10-31 14:09:41 -0700
commite0fe43357d1f2f986e7969a3d6efe723e6828fcf (patch)
treeba13d355c7524c657211e135d3279903b171f8d2 /lib/usb
parent1fea1df39abde97d1e84f5b99f9793701b1691b7 (diff)
usb_f107: Fixed lost 4 bytes on control OUT transaction.
Diffstat (limited to 'lib/usb')
-rw-r--r--lib/usb/usb_f107.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/lib/usb/usb_f107.c b/lib/usb/usb_f107.c
index 16630ee..8f03571 100644
--- a/lib/usb/usb_f107.c
+++ b/lib/usb/usb_f107.c
@@ -81,7 +81,7 @@ static void stm32f107_usbd_init(void)
/* Force peripheral only mode. */
- OTG_FS_GUSBCFG |= OTG_FS_GUSBCFG_FDMOD;
+ OTG_FS_GUSBCFG |= OTG_FS_GUSBCFG_FDMOD | OTG_FS_GUSBCFG_TRDT_MASK;
/* Full speed device */
OTG_FS_DCFG |= OTG_FS_DCFG_DSPD;
@@ -265,7 +265,7 @@ static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len)
* stm32f107_poll() which reads the packet status push register GRXSTSP
* for use in stm32f107_ep_read_packet().
*/
-static uint16_t rxbcnt[4];
+static uint16_t rxbcnt;
static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len)
{
@@ -273,8 +273,8 @@ static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len)
u32 *buf32 = buf;
u32 extra;
- len = MIN(len, rxbcnt[addr]);
- rxbcnt[addr] = 0;
+ len = MIN(len, rxbcnt);
+ rxbcnt -= len;
volatile u32 *fifo = OTG_FS_FIFO(addr);
for(i = len; i >= 4; i -= 4) {
@@ -286,9 +286,6 @@ static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len)
memcpy(buf32, &extra, i);
}
- if(len == 8)
- extra = *fifo++;
-
OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr];
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA |
(force_nak[addr] ? OTG_FS_DOEPCTL0_SNAK : OTG_FS_DOEPCTL0_CNAK);
@@ -327,10 +324,22 @@ static void stm32f107_poll(void)
type = USB_TRANSACTION_OUT;
/* Save packet size for stm32f107_ep_read_packet() */
- rxbcnt[ep] = (rxstsp & OTG_FS_GRXSTSP_BCNT_MASK) >> 4;
+ rxbcnt = (rxstsp & OTG_FS_GRXSTSP_BCNT_MASK) >> 4;
+
+ /* FIXME: Why is a delay needed here?
+ * This appears to fix a problem where the first 4 bytes
+ * of the DATA OUT stage of a control transaction are lost.
+ */
+ for(i = 0; i < 1000; i++) asm("nop");
if (_usbd_device.user_callback_ctr[ep][type])
_usbd_device.user_callback_ctr[ep][type] (ep);
+
+ /* Discard unread packet data */
+ for(i = 0; i < rxbcnt; i += 4)
+ (void)*OTG_FS_FIFO(ep);
+
+ rxbcnt = 0;
}
/* There is no global interrupt flag for transmit complete.