@@ -62,7 +62,7 @@ void tud_cdc_rx_cb(uint8_t itf)
62
62
63
63
// Invoked when received send break
64
64
void tud_cdc_send_break_cb (uint8_t itf, uint16_t duration_ms){
65
- // isr_log_v ("itf: %u, duration_ms: %u", itf, duration_ms);
65
+ // log_v ("itf: %u, duration_ms: %u", itf, duration_ms);
66
66
}
67
67
68
68
// Invoked when space becomes available in TX buffer
@@ -72,56 +72,6 @@ void tud_cdc_tx_complete_cb(uint8_t itf){
72
72
}
73
73
}
74
74
75
- static size_t ring_buf_flush (uint8_t itf, RingbufHandle_t ring_buf){
76
- if (!tud_cdc_n_connected (itf)){
77
- return 0 ;
78
- }
79
- size_t max_size = tud_cdc_n_write_available (itf);
80
- size_t queued_size = 0 ;
81
- if (max_size == 0 ){
82
- if (tud_cdc_n_write_flush (itf) > 0 ){
83
- // no space but we were able to flush some out
84
- max_size = tud_cdc_n_write_available (itf);
85
- }
86
- if (max_size == 0 ){
87
- // no space and could not flush
88
- return 0 ;
89
- }
90
- }
91
- uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpTo (ring_buf, &queued_size, 0 , max_size);
92
- if (queued_buff == NULL ) {
93
- // log_d("nothing to send");
94
- return 0 ;
95
- }
96
- size_t sent = tud_cdc_n_write (itf, queued_buff, queued_size);
97
- if (sent && sent < max_size){
98
- tud_cdc_n_write_flush (itf);
99
- }
100
- vRingbufferReturnItem (ring_buf, queued_buff);
101
- return sent;
102
- }
103
-
104
- static size_t ring_buf_write_nb (uint8_t itf, RingbufHandle_t ring_buf, const uint8_t *buffer, size_t size){
105
- if (buffer == NULL || ring_buf == NULL || size == 0 ){
106
- return 0 ;
107
- }
108
- size_t space = xRingbufferGetCurFreeSize (ring_buf);
109
- if (space == 0 ){
110
- // ring buff is full, maybe we can flush some?
111
- if (ring_buf_flush (itf, ring_buf)){
112
- space = xRingbufferGetCurFreeSize (ring_buf);
113
- }
114
- }
115
- if (size > space){
116
- size = space;
117
- }
118
- if (size && xRingbufferSend (ring_buf, (void *) (buffer), size, 0 ) != pdTRUE){
119
- return 0 ;
120
- }
121
- ring_buf_flush (itf, ring_buf);
122
- return size;
123
- }
124
-
125
75
static void ARDUINO_ISR_ATTR cdc0_write_char (char c){
126
76
if (devices[0 ] != NULL ){
127
77
devices[0 ]->write (c);
@@ -132,7 +82,20 @@ static void usb_unplugged_cb(void* arg, esp_event_base_t event_base, int32_t eve
132
82
((USBCDC*)arg)->_onUnplugged ();
133
83
}
134
84
135
- USBCDC::USBCDC (uint8_t itfn) : itf(itfn), bit_rate(0 ), stop_bits(0 ), parity(0 ), data_bits(0 ), dtr(false ), rts(false ), connected(false ), reboot_enable(true ), rx_queue(NULL ), tx_ring_buf(NULL ) {
85
+ USBCDC::USBCDC (uint8_t itfn)
86
+ : itf(itfn)
87
+ , bit_rate(0 )
88
+ , stop_bits(0 )
89
+ , parity(0 )
90
+ , data_bits(0 )
91
+ , dtr(false )
92
+ , rts(false )
93
+ , connected(false )
94
+ , reboot_enable(true )
95
+ , rx_queue(NULL )
96
+ , tx_lock(NULL )
97
+ , tx_timeout_ms(250 )
98
+ {
136
99
tinyusb_enable_interface (USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
137
100
if (itf < MAX_USB_CDC_DEVICES){
138
101
arduino_usb_event_handler_register_with (ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this );
@@ -165,25 +128,12 @@ size_t USBCDC::setRxBufferSize(size_t rx_queue_len){
165
128
return rx_queue_len;
166
129
}
167
130
168
- size_t USBCDC::setTxBufferSize (size_t tx_queue_len){
169
- if (tx_ring_buf){
170
- if (!tx_queue_len){
171
- vRingbufferDelete (tx_ring_buf);
172
- tx_ring_buf = NULL ;
173
- }
174
- return 0 ;
175
- }
176
- tx_ring_buf = xRingbufferCreate (tx_queue_len, RINGBUF_TYPE_BYTEBUF);
177
- if (!tx_ring_buf){
178
- return 0 ;
179
- }
180
- return tx_queue_len;
181
- }
182
-
183
131
void USBCDC::begin (unsigned long baud)
184
132
{
133
+ if (tx_lock == NULL ) {
134
+ tx_lock = xSemaphoreCreateMutex ();
135
+ }
185
136
setRxBufferSize (256 );// default if not preset
186
- setTxBufferSize (256 );// default if not preset
187
137
devices[itf] = this ;
188
138
}
189
139
@@ -192,7 +142,13 @@ void USBCDC::end()
192
142
connected = false ;
193
143
devices[itf] = NULL ;
194
144
setRxBufferSize (0 );
195
- setTxBufferSize (0 );
145
+ if (tx_lock != NULL ) {
146
+ vSemaphoreDelete (tx_lock);
147
+ }
148
+ }
149
+
150
+ void USBCDC::setTxTimeoutMs (uint32_t timeout){
151
+ tx_timeout_ms = timeout;
196
152
}
197
153
198
154
void USBCDC::_onUnplugged (void ){
@@ -301,7 +257,6 @@ void USBCDC::_onRX(){
301
257
}
302
258
303
259
void USBCDC::_onTX (){
304
- ring_buf_flush (itf, tx_ring_buf);
305
260
arduino_usb_cdc_event_data_t p = {0 };
306
261
arduino_usb_event_post (ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_TX_EVENT, &p, sizeof (arduino_usb_cdc_event_data_t ), portMAX_DELAY);
307
262
}
@@ -360,38 +315,73 @@ size_t USBCDC::read(uint8_t *buffer, size_t size)
360
315
361
316
void USBCDC::flush (void )
362
317
{
363
- if (itf >= MAX_USB_CDC_DEVICES || tx_ring_buf == NULL ){
318
+ if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || ! tud_cdc_n_connected (itf) ){
364
319
return ;
365
320
}
366
- UBaseType_t uxItemsWaiting = 0 ;
367
- vRingbufferGetInfo (tx_ring_buf, NULL , NULL , NULL , NULL , &uxItemsWaiting);
368
- while (uxItemsWaiting){
369
- ring_buf_flush (itf, tx_ring_buf);
370
- delay (5 );
371
- vRingbufferGetInfo (tx_ring_buf, NULL , NULL , NULL , NULL , &uxItemsWaiting);
321
+ if (xSemaphoreTake (tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
322
+ return ;
372
323
}
324
+ tud_cdc_n_write_flush (itf);
325
+ xSemaphoreGive (tx_lock);
373
326
}
374
327
375
328
int USBCDC::availableForWrite (void )
376
329
{
377
- if (itf >= MAX_USB_CDC_DEVICES || tx_ring_buf == NULL ){
330
+ if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected (itf)){
331
+ return 0 ;
332
+ }
333
+ if (xSemaphoreTake (tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
378
334
return 0 ;
379
335
}
380
- return xRingbufferGetCurFreeSize (tx_ring_buf);
336
+ size_t a = tud_cdc_n_write_available (itf);
337
+ xSemaphoreGive (tx_lock);
338
+ return a;
381
339
}
382
340
383
341
size_t USBCDC::write (const uint8_t *buffer, size_t size)
384
342
{
385
- if (itf >= MAX_USB_CDC_DEVICES || tx_ring_buf == NULL ){
343
+ if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || buffer == NULL || size == 0 || ! tud_cdc_n_connected (itf) ){
386
344
return 0 ;
387
345
}
388
- size_t sent = ring_buf_write_nb (itf, tx_ring_buf, buffer, size);
389
- if (sent < size){
390
- // log_w("sent %u less bytes", size - sent);
391
- // maybe wait to send the rest?
392
- // xRingbufferSend(tx_ring_buf, (void*) (buffer+sent), size-sent, timeout_ms / portTICK_PERIOD_MS)
346
+ if (xPortInIsrContext ()){
347
+ BaseType_t taskWoken = false ;
348
+ if (xSemaphoreTakeFromISR (tx_lock, &taskWoken) != pdPASS){
349
+ return 0 ;
350
+ }
351
+ } else if (xSemaphoreTake (tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
352
+ return 0 ;
353
+ }
354
+ size_t to_send = size, so_far = 0 ;
355
+ while (to_send){
356
+ if (!tud_cdc_n_connected (itf)){
357
+ size = so_far;
358
+ break ;
359
+ }
360
+ size_t space = tud_cdc_n_write_available (itf);
361
+ if (!space){
362
+ tud_cdc_n_write_flush (itf);
363
+ continue ;
364
+ }
365
+ if (space > to_send){
366
+ space = to_send;
367
+ }
368
+ size_t sent = tud_cdc_n_write (itf, buffer+so_far, space);
369
+ if (sent){
370
+ so_far += sent;
371
+ to_send -= sent;
372
+ tud_cdc_n_write_flush (itf);
373
+ } else {
374
+ size = so_far;
375
+ break ;
376
+ }
393
377
}
394
- return sent;
378
+ if (xPortInIsrContext ()){
379
+ BaseType_t taskWoken = false ;
380
+ xSemaphoreGiveFromISR (tx_lock, &taskWoken);
381
+ } else {
382
+ xSemaphoreGive (tx_lock);
383
+ }
384
+ return size;
395
385
}
396
386
397
387
size_t USBCDC::write (uint8_t c)
0 commit comments