Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 078671d

Browse filesBrowse files
authored
[HWCDC] Improve HW CDC Implementation (espressif#5643)
This pull request contains a few fixes and improvements to the HWCDC implementation. - Rework `HWCDC::write()` to accept unlimited data - Add Semaphore to guard the TX Ring Buffer - Add events support - Remove unnecessary 1200bps touch for flashing over HWCDC - Fix `HardwareSerial::setDebugOutput()` not resetting `putc` if the port is already selected, causing debug output to also show on HWCDC even when not selected.
1 parent 541cef9 commit 078671d
Copy full SHA for 078671d

File tree

4 files changed

+144
-25
lines changed
Filter options

4 files changed

+144
-25
lines changed

‎boards.txt

Copy file name to clipboardExpand all lines: boards.txt
-7Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,6 @@ esp32c3.menu.CDCOnBoot.default.build.cdc_on_boot=0
5757
esp32c3.menu.CDCOnBoot.cdc=Enabled
5858
esp32c3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
5959

60-
esp32c3.menu.UploadMode.default=UART0
61-
esp32c3.menu.UploadMode.default.upload.use_1200bps_touch=false
62-
esp32c3.menu.UploadMode.default.upload.wait_for_upload_port=false
63-
esp32c3.menu.UploadMode.cdc=Internal USB
64-
esp32c3.menu.UploadMode.cdc.upload.use_1200bps_touch=true
65-
esp32c3.menu.UploadMode.cdc.upload.wait_for_upload_port=true
66-
6760
esp32c3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
6861
esp32c3.menu.PartitionScheme.default.build.partitions=default
6962
esp32c3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)

‎cores/esp32/HWCDC.cpp

Copy file name to clipboardExpand all lines: cores/esp32/HWCDC.cpp
+116-11Lines changed: 116 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,47 @@
2424
#include "soc/periph_defs.h"
2525
#include "hal/usb_serial_jtag_ll.h"
2626

27+
ESP_EVENT_DEFINE_BASE(ARDUINO_HW_CDC_EVENTS);
28+
2729
static RingbufHandle_t tx_ring_buf = NULL;
2830
static xQueueHandle rx_queue = NULL;
2931
static uint8_t rx_data_buf[64];
3032
static intr_handle_t intr_handle = NULL;
3133
static volatile bool initial_empty = false;
34+
static xSemaphoreHandle tx_lock = NULL;
35+
static uint32_t tx_timeout_ms = 200;
36+
static esp_event_loop_handle_t arduino_hw_cdc_event_loop_handle = NULL;
37+
38+
static esp_err_t arduino_hw_cdc_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, BaseType_t *task_unblocked){
39+
if(arduino_hw_cdc_event_loop_handle == NULL){
40+
return ESP_FAIL;
41+
}
42+
return esp_event_isr_post_to(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_data, event_data_size, task_unblocked);
43+
}
44+
45+
static esp_err_t arduino_hw_cdc_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg){
46+
if (!arduino_hw_cdc_event_loop_handle) {
47+
esp_event_loop_args_t event_task_args = {
48+
.queue_size = 5,
49+
.task_name = "arduino_hw_cdc_events",
50+
.task_priority = 5,
51+
.task_stack_size = 2048,
52+
.task_core_id = tskNO_AFFINITY
53+
};
54+
if (esp_event_loop_create(&event_task_args, &arduino_hw_cdc_event_loop_handle) != ESP_OK) {
55+
log_e("esp_event_loop_create failed");
56+
}
57+
}
58+
if(arduino_hw_cdc_event_loop_handle == NULL){
59+
return ESP_FAIL;
60+
}
61+
return esp_event_handler_register_with(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_handler, event_handler_arg);
62+
}
3263

3364
static void hw_cdc_isr_handler(void *arg) {
3465
portBASE_TYPE xTaskWoken = 0;
3566
uint32_t usbjtag_intr_status = 0;
67+
arduino_hw_cdc_event_data_t event = {0};
3668
usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask();
3769

3870
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) {
@@ -45,6 +77,7 @@ static void hw_cdc_isr_handler(void *arg) {
4577
initial_empty = true;
4678
//send event?
4779
//ets_printf("CONNECTED\n");
80+
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_CONNECTED_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
4881
}
4982
size_t queued_size;
5083
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR(tx_ring_buf, &queued_size, 64);
@@ -58,6 +91,8 @@ static void hw_cdc_isr_handler(void *arg) {
5891
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
5992
//send event?
6093
//ets_printf("TX:%u\n", queued_size);
94+
event.tx.len = queued_size;
95+
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_TX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
6196
}
6297
} else {
6398
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
@@ -77,13 +112,16 @@ static void hw_cdc_isr_handler(void *arg) {
77112
}
78113
//send event?
79114
//ets_printf("RX:%u/%u\n", i, rx_fifo_len);
115+
event.rx.len = i;
116+
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_RX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
80117
}
81118

82119
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_BUS_RESET) {
83120
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_BUS_RESET);
84121
initial_empty = false;
85122
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
86123
//ets_printf("BUS_RESET\n");
124+
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_BUS_RESET_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
87125
}
88126

89127
if (xTaskWoken == pdTRUE) {
@@ -95,13 +133,13 @@ static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
95133
if(xPortInIsrContext()){
96134
xRingbufferSendFromISR(tx_ring_buf, (void*) (&c), 1, NULL);
97135
} else {
98-
xRingbufferSend(tx_ring_buf, (void*) (&c), 1, 0);
136+
xRingbufferSend(tx_ring_buf, (void*) (&c), 1, tx_timeout_ms / portTICK_PERIOD_MS);
99137
}
100138
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
101139
}
102140

103141
HWCDC::HWCDC() {
104-
142+
105143
}
106144

107145
HWCDC::~HWCDC(){
@@ -113,8 +151,19 @@ HWCDC::operator bool() const
113151
return initial_empty;
114152
}
115153

154+
void HWCDC::onEvent(esp_event_handler_t callback){
155+
onEvent(ARDUINO_HW_CDC_ANY_EVENT, callback);
156+
}
157+
158+
void HWCDC::onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback){
159+
arduino_hw_cdc_event_handler_register_with(ARDUINO_HW_CDC_EVENTS, event, callback, this);
160+
}
161+
116162
void HWCDC::begin(unsigned long baud)
117163
{
164+
if(tx_lock == NULL) {
165+
tx_lock = xSemaphoreCreateMutex();
166+
}
118167
setRxBufferSize(256);//default if not preset
119168
setTxBufferSize(256);//default if not preset
120169

@@ -123,6 +172,7 @@ void HWCDC::begin(unsigned long baud)
123172
if(!intr_handle && esp_intr_alloc(ETS_USB_INTR_SOURCE/*ETS_USB_SERIAL_JTAG_INTR_SOURCE*/, 0, hw_cdc_isr_handler, NULL, &intr_handle) != ESP_OK){
124173
isr_log_e("HW USB CDC failed to init interrupts");
125174
end();
175+
return;
126176
}
127177
}
128178

@@ -132,8 +182,19 @@ void HWCDC::end()
132182
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_BUS_RESET);
133183
esp_intr_free(intr_handle);
134184
intr_handle = NULL;
185+
if(tx_lock != NULL) {
186+
vSemaphoreDelete(tx_lock);
187+
}
135188
setRxBufferSize(0);
136189
setTxBufferSize(0);
190+
if (arduino_hw_cdc_event_loop_handle) {
191+
esp_event_loop_delete(arduino_hw_cdc_event_loop_handle);
192+
arduino_hw_cdc_event_loop_handle = NULL;
193+
}
194+
}
195+
196+
void HWCDC::setTxTimeoutMs(uint32_t timeout){
197+
tx_timeout_ms = timeout;
137198
}
138199

139200
/*
@@ -157,21 +218,57 @@ size_t HWCDC::setTxBufferSize(size_t tx_queue_len){
157218

158219
int HWCDC::availableForWrite(void)
159220
{
160-
if(tx_ring_buf == NULL){
161-
return -1;
221+
if(tx_ring_buf == NULL || tx_lock == NULL){
222+
return 0;
223+
}
224+
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
225+
return 0;
162226
}
163-
return xRingbufferGetCurFreeSize(tx_ring_buf);
227+
size_t a = xRingbufferGetCurFreeSize(tx_ring_buf);
228+
xSemaphoreGive(tx_lock);
229+
return a;
164230
}
165231

166232
size_t HWCDC::write(const uint8_t *buffer, size_t size)
167233
{
168-
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
169-
if(xRingbufferSend(tx_ring_buf, (void*) (buffer), size, 200 / portTICK_PERIOD_MS) != pdTRUE){
170-
log_e("Write Failed");
234+
if(buffer == NULL || size == 0 || tx_ring_buf == NULL || tx_lock == NULL){
171235
return 0;
172236
}
173-
// Now trigger the ISR to read data from the ring buffer.
174-
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
237+
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
238+
return 0;
239+
}
240+
size_t max_size = xRingbufferGetMaxItemSize(tx_ring_buf);
241+
size_t space = xRingbufferGetCurFreeSize(tx_ring_buf);
242+
size_t to_send = size, so_far = 0;
243+
244+
if(space > size){
245+
space = size;
246+
}
247+
// Non-Blocking method, Sending data to ringbuffer, and handle the data in ISR.
248+
if(xRingbufferSend(tx_ring_buf, (void*) (buffer), space, 0) != pdTRUE){
249+
size = 0;
250+
} else {
251+
to_send -= space;
252+
so_far += space;
253+
// Now trigger the ISR to read data from the ring buffer.
254+
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
255+
256+
while(to_send){
257+
if(max_size > to_send){
258+
max_size = to_send;
259+
}
260+
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
261+
if(xRingbufferSend(tx_ring_buf, (void*) (buffer+so_far), max_size, tx_timeout_ms / portTICK_PERIOD_MS) != pdTRUE){
262+
size = so_far;
263+
break;
264+
}
265+
so_far += max_size;
266+
to_send -= max_size;
267+
// Now trigger the ISR to read data from the ring buffer.
268+
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
269+
}
270+
}
271+
xSemaphoreGive(tx_lock);
175272
return size;
176273
}
177274

@@ -182,15 +279,23 @@ size_t HWCDC::write(uint8_t c)
182279

183280
void HWCDC::flush(void)
184281
{
185-
if(tx_ring_buf == NULL){
282+
if(tx_ring_buf == NULL || tx_lock == NULL){
283+
return;
284+
}
285+
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
186286
return;
187287
}
188288
UBaseType_t uxItemsWaiting = 0;
189289
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
290+
if(uxItemsWaiting){
291+
// Now trigger the ISR to read data from the ring buffer.
292+
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
293+
}
190294
while(uxItemsWaiting){
191295
delay(5);
192296
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
193297
}
298+
xSemaphoreGive(tx_lock);
194299
}
195300

196301
/*

‎cores/esp32/HWCDC.h

Copy file name to clipboardExpand all lines: cores/esp32/HWCDC.h
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,41 @@
1717
#if CONFIG_IDF_TARGET_ESP32C3
1818

1919
#include <inttypes.h>
20+
#include "esp_event.h"
2021
#include "Stream.h"
2122

23+
ESP_EVENT_DECLARE_BASE(ARDUINO_HW_CDC_EVENTS);
24+
25+
typedef enum {
26+
ARDUINO_HW_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
27+
ARDUINO_HW_CDC_CONNECTED_EVENT = 0,
28+
ARDUINO_HW_CDC_BUS_RESET_EVENT,
29+
ARDUINO_HW_CDC_RX_EVENT,
30+
ARDUINO_HW_CDC_TX_EVENT,
31+
ARDUINO_HW_CDC_MAX_EVENT,
32+
} arduino_hw_cdc_event_t;
33+
34+
typedef union {
35+
struct {
36+
size_t len;
37+
} rx;
38+
struct {
39+
size_t len;
40+
} tx;
41+
} arduino_hw_cdc_event_data_t;
42+
2243
class HWCDC: public Stream
2344
{
2445
public:
2546
HWCDC();
2647
~HWCDC();
2748

49+
void onEvent(esp_event_handler_t callback);
50+
void onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback);
51+
2852
size_t setRxBufferSize(size_t);
2953
size_t setTxBufferSize(size_t);
54+
void setTxTimeoutMs(uint32_t timeout);
3055
void begin(unsigned long baud=0);
3156
void end();
3257

‎cores/esp32/esp32-hal-uart.c

Copy file name to clipboardExpand all lines: cores/esp32/esp32-hal-uart.c
+3-7Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -368,13 +368,9 @@ void uartSetDebug(uart_t* uart)
368368
{
369369
if(uart == NULL || uart->num >= SOC_UART_NUM) {
370370
s_uart_debug_nr = -1;
371-
//ets_install_putc1(NULL);
372-
//return;
373-
} else
374-
if(s_uart_debug_nr == uart->num) {
375-
return;
376-
} else
377-
s_uart_debug_nr = uart->num;
371+
} else {
372+
s_uart_debug_nr = uart->num;
373+
}
378374
uart_install_putc();
379375
}
380376

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.