Skip to content

Commit 52dec69

Browse files
authored
feat(serialcdc): non block functions
modifies write and flush to do not clock in case CDC host is not connected to the CDC client from the C3/S3/C6/H2
1 parent 0e168aa commit 52dec69

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

cores/esp32/HWCDC.cpp

+25-2
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ static void hw_cdc_isr_handler(void *arg) {
9797
}
9898
} else {
9999
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
100+
// should we just flush internal CDC buffer??
100101
}
101102
}
102103

@@ -281,9 +282,23 @@ int HWCDC::availableForWrite(void)
281282
return a;
282283
}
283284

285+
static void flushTXBuffer()
286+
{
287+
if (!tx_ring_buf) return;
288+
UBaseType_t uxItemsWaiting = 0;
289+
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
290+
291+
size_t queued_size = 0;
292+
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpTo(tx_ring_buf, &queued_size, 0, uxItemsWaiting);
293+
if (queued_size && queued_buff != NULL) {
294+
vRingbufferReturnItem(tx_ring_buf, (void *)queued_buff);
295+
}
296+
// flush internal CDC
297+
}
298+
284299
size_t HWCDC::write(const uint8_t *buffer, size_t size)
285300
{
286-
uint32_t tx_timeout_ms = 0; // if not connected, no timeout
301+
uint32_t tx_timeout_ms = 0; // if not connected, no timeout
287302
if(buffer == NULL || size == 0 || tx_ring_buf == NULL || tx_lock == NULL){
288303
return 0;
289304
}
@@ -301,6 +316,7 @@ size_t HWCDC::write(const uint8_t *buffer, size_t size)
301316
space = size;
302317
}
303318
// Non-Blocking method, Sending data to ringbuffer, and handle the data in ISR.
319+
// USB may be plugged, but CDC may be not connected ==> do not block and flush TX buffer, keeping in the buffer just the lastest data
304320
if(xRingbufferSend(tx_ring_buf, (void*) (buffer), space, 0) != pdTRUE){
305321
size = 0;
306322
} else {
@@ -324,6 +340,8 @@ size_t HWCDC::write(const uint8_t *buffer, size_t size)
324340
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
325341
}
326342
}
343+
// there is no more space in CDC Endpoint internal buffer ==> flush all data from TX buffer and only keep last written data
344+
if(to_send && !usb_serial_jtag_ll_txfifo_writable()) flushTXBuffer();
327345
xSemaphoreGive(tx_lock);
328346
return size;
329347
}
@@ -345,16 +363,21 @@ void HWCDC::flush(void)
345363
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
346364
return;
347365
}
366+
// USB may be plugged, but CDC may be not connected ==> do not block and flush TX buffer, keeping in the buffer just the lastest data
348367
UBaseType_t uxItemsWaiting = 0;
349368
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
350369
if(uxItemsWaiting){
351370
// Now trigger the ISR to read data from the ring buffer.
352371
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
353372
}
354-
while(uxItemsWaiting){
373+
uint8_t tries = 3;
374+
while(tries && uxItemsWaiting){
355375
delay(5);
376+
UBaseType_t lastUxItemsWaiting = uxItemsWaiting; // is it flushing CDC?
356377
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
378+
if (lastUxItemsWaiting == uxItemsWaiting) tries--; // avoids locking when USB is plugged, but CDC is not connected
357379
}
380+
if (!tries) flushTXBuffer(); // flush TX Buffer
358381
xSemaphoreGive(tx_lock);
359382
}
360383

0 commit comments

Comments
 (0)