Skip to content

Commit 82d6510

Browse files
projectgusiabdalkader
authored andcommitted
shared/tinyusb/mp_usbd_cdc: Rewrite USB CDC TX loop.
This is related to the previous commit (where due to the new config flag this loop could end up stuck indefinitely if the USB host was disconnected). The previous loop could maybe still get stuck if the low-level USB state and the high-level USB state got out of sync. (Not clearly possible, but hard to say definitely not possible.) To be "belts and braces" careful: - Always run mp_usbd_task() each time around the loop to progress the state. - Always evaluate the timeout if we fail to write anything to the FIFO. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <[email protected]>
1 parent 869e01e commit 82d6510

File tree

1 file changed

+29
-16
lines changed

1 file changed

+29
-16
lines changed

shared/tinyusb/mp_usbd_cdc.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -98,32 +98,45 @@ mp_uint_t mp_usbd_cdc_tx_strn(const char *str, mp_uint_t len) {
9898
if (!tusb_inited()) {
9999
return 0;
100100
}
101+
mp_uint_t last_write = mp_hal_ticks_ms();
101102
size_t i = 0;
102103
while (i < len) {
103104
uint32_t n = len - i;
104-
if (n > CFG_TUD_CDC_EP_BUFSIZE) {
105-
n = CFG_TUD_CDC_EP_BUFSIZE;
106-
}
105+
107106
if (tud_cdc_connected()) {
108-
// If CDC port is connected but the buffer is full, wait for up to USC_CDC_TIMEOUT ms.
109-
mp_uint_t t0 = mp_hal_ticks_ms();
110-
while (n > tud_cdc_write_available() && (mp_uint_t)(mp_hal_ticks_ms() - t0) < MICROPY_HW_USB_CDC_TX_TIMEOUT) {
111-
mp_event_wait_ms(1);
112-
113-
// Explicitly run the USB stack as the scheduler may be locked (eg we
114-
// are in an interrupt handler), while there is data pending.
115-
mp_usbd_task();
116-
}
117107
// Limit write to available space in tx buffer when connected.
108+
//
109+
// (If not connected then we write everything to the fifo, expecting
110+
// it to overwrite old data so it will have latest data buffered
111+
// when host connects.)
118112
n = MIN(n, tud_cdc_write_available());
119-
if (n == 0) {
120-
break;
121-
}
122113
}
123-
// When not connected we always write to usb fifo, ensuring it has latest data.
114+
124115
uint32_t n2 = tud_cdc_write(str + i, n);
125116
tud_cdc_write_flush();
126117
i += n2;
118+
119+
if (i < len) {
120+
if (n2 > 0) {
121+
// reset the timeout each time we successfully write to the FIFO
122+
last_write = mp_hal_ticks_ms();
123+
} else {
124+
if ((mp_uint_t)(mp_hal_ticks_ms() - last_write) >= MICROPY_HW_USB_CDC_TX_TIMEOUT) {
125+
break; // Timeout
126+
}
127+
128+
if (tud_cdc_connected()) {
129+
// If we know we're connected then we can wait for host to make
130+
// more space
131+
mp_event_wait_ms(1);
132+
}
133+
}
134+
135+
// Always explicitly run the USB stack as the scheduler may be
136+
// locked (eg we are in an interrupt handler), while there is data
137+
// or a state change pending.
138+
mp_usbd_task();
139+
}
127140
}
128141
return i;
129142
}

0 commit comments

Comments
 (0)