@@ -598,6 +598,19 @@ uint8_t USBDeviceClass::armRecv(uint32_t ep)
598598 return usbd.epBank0ByteCount (ep);
599599}
600600
601+ // Timeout for sends
602+ #define TX_TIMEOUT_MS 70
603+
604+ static char LastTransmitTimedOut[7 ] = {
605+ 0 ,
606+ 0 ,
607+ 0 ,
608+ 0 ,
609+ 0 ,
610+ 0 ,
611+ 0
612+ };
613+
601614// Blocking Send of data to an endpoint
602615uint32_t USBDeviceClass::send (uint32_t ep, const void *data, uint32_t len)
603616{
@@ -619,6 +632,29 @@ uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
619632 // Flash area
620633 while (len != 0 )
621634 {
635+ if (usbd.epBank1IsReady (ep)) {
636+ // previous transfer is still not complete
637+
638+ // convert the timeout from microseconds to a number of times through
639+ // the wait loop; it takes (roughly) 23 clock cycles per iteration.
640+ uint32_t timeout = microsecondsToClockCycles (TX_TIMEOUT_MS * 1000 ) / 23 ;
641+
642+ // Wait for (previous) transfer to complete
643+ // inspired by Paul Stoffregen's work on Teensy
644+ while (!usbd.epBank1IsTransferComplete (ep)) {
645+ if (LastTransmitTimedOut[ep] || timeout-- == 0 ) {
646+ LastTransmitTimedOut[ep] = 1 ;
647+
648+ // set byte count to zero, so that ZLP is sent
649+ // instead of stale data
650+ usbd.epBank1SetByteCount (ep, 0 );
651+ return -1 ;
652+ }
653+ }
654+ }
655+
656+ LastTransmitTimedOut[ep] = 0 ;
657+
622658 if (len >= EPX_SIZE) {
623659 length = EPX_SIZE - 1 ;
624660 } else {
@@ -637,10 +673,6 @@ uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
637673 // RAM buffer is full, we can send data (IN)
638674 usbd.epBank1SetReady (ep);
639675
640- // Wait for transfer to complete
641- while (!usbd.epBank1IsTransferComplete (ep)) {
642- ; // need fire exit.
643- }
644676 written += length;
645677 len -= length;
646678 data = (char *)data + length;
0 commit comments