@@ -67,58 +67,72 @@ void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms){
67
67
68
68
// Invoked when space becomes available in TX buffer
69
69
void tud_cdc_tx_complete_cb (uint8_t itf){
70
- if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL && devices[itf]->tx_sem != NULL ){
71
- xSemaphoreGive (devices[itf]->tx_sem );
70
+ if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL ){
72
71
devices[itf]->_onTX ();
73
72
}
74
73
}
75
74
76
- static size_t tinyusb_cdc_write (uint8_t itf, const uint8_t *buffer, size_t size){
77
- if (itf >= MAX_USB_CDC_DEVICES || devices[itf] == NULL || devices[itf]->tx_sem == NULL ){
78
- return 0 ;
79
- }
75
+ static size_t ring_buf_flush (uint8_t itf, RingbufHandle_t ring_buf){
80
76
if (!tud_cdc_n_connected (itf)){
81
77
return 0 ;
82
78
}
83
- size_t tosend = size, sofar = 0 ;
84
- while (tosend){
85
- uint32_t space = tud_cdc_n_write_available (itf);
86
- if (!space){
87
- // make sure that we do not get previous semaphore
88
- xSemaphoreTake (devices[itf]->tx_sem , 0 );
89
- // wait for tx_complete
90
- if (xSemaphoreTake (devices[itf]->tx_sem , 200 / portTICK_PERIOD_MS) == pdTRUE){
91
- space = tud_cdc_n_write_available (itf);
92
- }
93
- if (!space){
94
- return sofar;
95
- }
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);
96
85
}
97
- if (tosend < space){
98
- space = tosend;
86
+ if (max_size == 0 ){
87
+ // no space and could not flush
88
+ return 0 ;
99
89
}
100
- uint32_t sent = tud_cdc_n_write (itf, buffer + sofar, space);
101
- if (!sent){
102
- return sofar;
103
- }
104
- sofar += sent;
105
- tosend -= sent;
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){
106
98
tud_cdc_n_write_flush (itf);
107
- // xSemaphoreTake(devices[itf]->tx_sem, portMAX_DELAY);
108
99
}
109
- return sofar;
100
+ vRingbufferReturnItem (ring_buf, queued_buff);
101
+ return sent;
110
102
}
111
103
112
- static void ARDUINO_ISR_ATTR cdc0_write_char (char c)
113
- {
114
- tinyusb_cdc_write (0 , (const uint8_t *)&c, 1 );
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
+ static void ARDUINO_ISR_ATTR cdc0_write_char (char c){
126
+ if (devices[0 ] != NULL ){
127
+ devices[0 ]->write (c);
128
+ }
115
129
}
116
130
117
131
static void usb_unplugged_cb (void * arg, esp_event_base_t event_base, int32_t event_id, void * event_data){
118
132
((USBCDC*)arg)->_onUnplugged ();
119
133
}
120
134
121
- 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_sem (NULL ) {
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 ) {
122
136
tinyusb_enable_interface (USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
123
137
if (itf < MAX_USB_CDC_DEVICES){
124
138
arduino_usb_event_handler_register_with (ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this );
@@ -151,13 +165,25 @@ size_t USBCDC::setRxBufferSize(size_t rx_queue_len){
151
165
return rx_queue_len;
152
166
}
153
167
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
+
154
183
void USBCDC::begin (unsigned long baud)
155
184
{
156
- if (tx_sem == NULL ){
157
- tx_sem = xSemaphoreCreateBinary ();
158
- xSemaphoreTake (tx_sem, 0 );
159
- }
160
185
setRxBufferSize (256 );// default if not preset
186
+ setTxBufferSize (256 );// default if not preset
161
187
devices[itf] = this ;
162
188
}
163
189
@@ -166,10 +192,7 @@ void USBCDC::end()
166
192
connected = false ;
167
193
devices[itf] = NULL ;
168
194
setRxBufferSize (0 );
169
- if (tx_sem != NULL ) {
170
- vSemaphoreDelete (tx_sem);
171
- tx_sem = NULL ;
172
- }
195
+ setTxBufferSize (0 );
173
196
}
174
197
175
198
void USBCDC::_onUnplugged (void ){
@@ -278,6 +301,7 @@ void USBCDC::_onRX(){
278
301
}
279
302
280
303
void USBCDC::_onTX (){
304
+ ring_buf_flush (itf, tx_ring_buf);
281
305
arduino_usb_cdc_event_data_t p = {0 };
282
306
arduino_usb_event_post (ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_TX_EVENT, &p, sizeof (arduino_usb_cdc_event_data_t ), portMAX_DELAY);
283
307
}
@@ -336,23 +360,38 @@ size_t USBCDC::read(uint8_t *buffer, size_t size)
336
360
337
361
void USBCDC::flush (void )
338
362
{
339
- if (itf >= MAX_USB_CDC_DEVICES || tx_sem == NULL ){
363
+ if (itf >= MAX_USB_CDC_DEVICES || tx_ring_buf == NULL ){
340
364
return ;
341
365
}
342
- tud_cdc_n_write_flush (itf);
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);
372
+ }
343
373
}
344
374
345
375
int USBCDC::availableForWrite (void )
346
376
{
347
- if (itf >= MAX_USB_CDC_DEVICES || tx_sem == NULL ){
348
- return - 1 ;
377
+ if (itf >= MAX_USB_CDC_DEVICES || tx_ring_buf == NULL ){
378
+ return 0 ;
349
379
}
350
- return tud_cdc_n_write_available (itf );
380
+ return xRingbufferGetCurFreeSize (tx_ring_buf );
351
381
}
352
382
353
383
size_t USBCDC::write (const uint8_t *buffer, size_t size)
354
384
{
355
- return tinyusb_cdc_write (itf, buffer, size);
385
+ if (itf >= MAX_USB_CDC_DEVICES || tx_ring_buf == NULL ){
386
+ return 0 ;
387
+ }
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)
393
+ }
394
+ return sent;
356
395
}
357
396
358
397
size_t USBCDC::write (uint8_t c)
0 commit comments