Skip to content

Commit 316eccf

Browse files
committed
Add USB send timeout
Timeout is checked on the next send attempt. Initial timeout is set to 70ms, after a time out occurs and the previous transfer is still not complete a send will report as failed. If a send times out, a ZLP will be in the send queue to check for future timeouts.
1 parent 3646856 commit 316eccf

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

cores/arduino/USB/USBCore.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static volatile uint8_t rxLEDPulse; /**< Milliseconds remaining for data Rx LED
3838
#endif
3939
static char isRemoteWakeUpEnabled = 0;
4040
static char isEndpointHalt = 0;
41+
static char lastTransmitTimedOut = 0;
4142

4243
extern void (*gpf_isr)(void);
4344

@@ -602,6 +603,9 @@ uint8_t USBDeviceClass::armRecv(uint32_t ep)
602603
return usbd.epBank0ByteCount(ep);
603604
}
604605

606+
// Timeout for sends
607+
#define TX_TIMEOUT_MS 70
608+
605609
// Blocking Send of data to an endpoint
606610
uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
607611
{
@@ -654,6 +658,28 @@ uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
654658
// Flash area
655659
while (len != 0)
656660
{
661+
if (usbd.epBank1IsReady(ep)) {
662+
// previous transfer is still not complete
663+
664+
// convert the timeout from microseconds to a number of times through
665+
// the wait loop; it takes (roughly) 18 clock cycles per iteration.
666+
uint32_t timeout = microsecondsToClockCycles(TX_TIMEOUT_MS * 1000) / 18;
667+
668+
// Wait for (previous) transfer to complete
669+
while (!usbd.epBank1IsTransferComplete(ep)) {
670+
if (lastTransmitTimedOut || timeout-- == 0) {
671+
lastTransmitTimedOut = 1;
672+
673+
// set byte count to zero, so that ZLP is sent
674+
// instead of stale data
675+
usbd.epBank1SetByteCount(ep, 0);
676+
return -1;
677+
}
678+
}
679+
}
680+
681+
lastTransmitTimedOut = 0;
682+
657683
if (len >= 64) {
658684
length = 64;
659685
} else {
@@ -672,10 +698,6 @@ uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
672698
// RAM buffer is full, we can send data (IN)
673699
usbd.epBank1SetReady(ep);
674700

675-
// Wait for transfer to complete
676-
while (!usbd.epBank1IsTransferComplete(ep)) {
677-
; // need fire exit.
678-
}
679701
written += length;
680702
len -= length;
681703
data = (char *)data + length;

0 commit comments

Comments
 (0)