-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Fixes USB CDC setRxBufferSize(), begin(), _onRX() #6413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1a5b3e2
84adb04
b7c6948
70d7983
9e9099e
b16f535
8044a38
8e83060
d993809
57d8e83
023b9ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,16 +114,42 @@ void USBCDC::onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback | |
} | ||
|
||
size_t USBCDC::setRxBufferSize(size_t rx_queue_len){ | ||
if(rx_queue){ | ||
if(!rx_queue_len){ | ||
vQueueDelete(rx_queue); | ||
rx_queue = NULL; | ||
size_t currentQueueSize = rx_queue ? | ||
uxQueueSpacesAvailable(rx_queue) + uxQueueMessagesWaiting(rx_queue) : 0; | ||
|
||
if (rx_queue_len != currentQueueSize) { | ||
xQueueHandle new_rx_queue = NULL; | ||
if (rx_queue_len) { | ||
new_rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t)); | ||
if(!new_rx_queue){ | ||
log_e("CDC Queue creation failed."); | ||
return 0; | ||
} | ||
if (rx_queue) { | ||
size_t copySize = uxQueueMessagesWaiting(rx_queue); | ||
if (copySize > 0) { | ||
for(size_t i = 0; i < copySize; i++) { | ||
uint8_t ch = 0; | ||
xQueueReceive(rx_queue, &ch, 0); | ||
if (!xQueueSend(new_rx_queue, &ch, 0)) { | ||
arduino_usb_cdc_event_data_t p; | ||
p.rx_overflow.dropped_bytes = copySize - i; | ||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_OVERFLOW_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | ||
log_e("CDC RX Overflow."); | ||
break; | ||
} | ||
} | ||
} | ||
vQueueDelete(rx_queue); | ||
} | ||
rx_queue = new_rx_queue; | ||
return rx_queue_len; | ||
} else { | ||
if (rx_queue) { | ||
vQueueDelete(rx_queue); | ||
rx_queue = NULL; | ||
} | ||
} | ||
return 0; | ||
} | ||
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t)); | ||
if(!rx_queue){ | ||
return 0; | ||
} | ||
return rx_queue_len; | ||
} | ||
|
@@ -133,7 +159,8 @@ void USBCDC::begin(unsigned long baud) | |
if(tx_lock == NULL) { | ||
tx_lock = xSemaphoreCreateMutex(); | ||
} | ||
setRxBufferSize(256);//default if not preset | ||
// if rx_queue was set before begin(), keep it | ||
if (!rx_queue) setRxBufferSize(256); //default if not preset | ||
devices[itf] = this; | ||
} | ||
|
||
|
@@ -144,6 +171,7 @@ void USBCDC::end() | |
setRxBufferSize(0); | ||
if(tx_lock != NULL) { | ||
vSemaphoreDelete(tx_lock); | ||
tx_lock = NULL; | ||
} | ||
} | ||
|
||
|
@@ -244,16 +272,22 @@ void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _pari | |
} | ||
|
||
void USBCDC::_onRX(){ | ||
arduino_usb_cdc_event_data_t p; | ||
uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE+1]; | ||
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE); | ||
for(uint32_t i=0; i<count; i++){ | ||
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 0)){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just changing the timeout here from 0 to something else would "fix" this issue. No need for the other changes (and no need for set delay). Can't stop stressing enough that you should use Arduino API when possible, not vTaskDelay There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, just doing it doesn't fix it because, data may be partially copied from TUD CDC and it will return when the Arduino CDC queue is full, not sending Arduino USB CDC event to the application and dropping data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Regarding using Arduino In the case of this issue, I think it is a lot clearer to use For example, executing Please let me know your thoughts on it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we talking about the same things? Doesn't the code below do exactly what we need? void USBCDC::_onRX(){
uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE+1];
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE);
for(uint32_t i=0; i<count; i++){
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 10)){
count = i;
break;
}
}
if (count) {
arduino_usb_cdc_event_data_t p;
p.rx.len = count;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. re There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe worth adding a new event to tell how many bytes were missed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should at least There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have created an event There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. log_e is always good for us. Will print even if the user is not listening to events There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All Done - including copying queue data in setRxBufferSize() |
||
return; | ||
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 10)) { | ||
p.rx_overflow.dropped_bytes = count - i; | ||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_OVERFLOW_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | ||
log_e("CDC RX Overflow."); | ||
count = i; | ||
break; | ||
} | ||
} | ||
arduino_usb_cdc_event_data_t p; | ||
p.rx.len = count; | ||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | ||
if (count) { | ||
SuGlider marked this conversation as resolved.
Show resolved
Hide resolved
|
||
p.rx.len = count; | ||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | ||
} | ||
} | ||
|
||
void USBCDC::_onTX(){ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point is this function to only be called before begin and never after. If you really want to make it changeable, you need to make sure that the old queue is either empty or you copy the data from it to the new one before deletion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I agree that in this case it shall copy data from the old queue to the new one. I'll implement it this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.