Skip to content

Commit b627e00

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 5dd2adc commit b627e00

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

@@ -598,6 +599,9 @@ uint8_t USBDeviceClass::armRecv(uint32_t ep)
598599
return usbd.epBank0ByteCount(ep);
599600
}
600601

602+
// Timeout for sends
603+
#define TX_TIMEOUT_MS 70
604+
601605
// Blocking Send of data to an endpoint
602606
uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
603607
{
@@ -619,6 +623,28 @@ uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
619623
// Flash area
620624
while (len != 0)
621625
{
626+
if (usbd.epBank1IsReady(ep)) {
627+
// previous transfer is still not complete
628+
629+
// convert the timeout from microseconds to a number of times through
630+
// the wait loop; it takes (roughly) 18 clock cycles per iteration.
631+
uint32_t timeout = microsecondsToClockCycles(TX_TIMEOUT_MS * 1000) / 18;
632+
633+
// Wait for (previous) transfer to complete
634+
while (!usbd.epBank1IsTransferComplete(ep)) {
635+
if (lastTransmitTimedOut || timeout-- == 0) {
636+
lastTransmitTimedOut = 1;
637+
638+
// set byte count to zero, so that ZLP is sent
639+
// instead of stale data
640+
usbd.epBank1SetByteCount(ep, 0);
641+
return -1;
642+
}
643+
}
644+
}
645+
646+
lastTransmitTimedOut = 0;
647+
622648
if (len >= EPX_SIZE) {
623649
length = EPX_SIZE - 1;
624650
} else {
@@ -637,10 +663,6 @@ uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
637663
// RAM buffer is full, we can send data (IN)
638664
usbd.epBank1SetReady(ep);
639665

640-
// Wait for transfer to complete
641-
while (!usbd.epBank1IsTransferComplete(ep)) {
642-
; // need fire exit.
643-
}
644666
written += length;
645667
len -= length;
646668
data = (char *)data + length;

0 commit comments

Comments
 (0)