24
24
#include " soc/periph_defs.h"
25
25
#include " hal/usb_serial_jtag_ll.h"
26
26
27
+ ESP_EVENT_DEFINE_BASE (ARDUINO_HW_CDC_EVENTS);
28
+
27
29
static RingbufHandle_t tx_ring_buf = NULL ;
28
30
static xQueueHandle rx_queue = NULL ;
29
31
static uint8_t rx_data_buf[64 ];
30
32
static intr_handle_t intr_handle = NULL ;
31
33
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
+ }
32
63
33
64
static void hw_cdc_isr_handler (void *arg) {
34
65
portBASE_TYPE xTaskWoken = 0 ;
35
66
uint32_t usbjtag_intr_status = 0 ;
67
+ arduino_hw_cdc_event_data_t event = {0 };
36
68
usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask ();
37
69
38
70
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) {
@@ -45,6 +77,7 @@ static void hw_cdc_isr_handler(void *arg) {
45
77
initial_empty = true ;
46
78
// send event?
47
79
// 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);
48
81
}
49
82
size_t queued_size;
50
83
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) {
58
91
usb_serial_jtag_ll_ena_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
59
92
// send event?
60
93
// 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);
61
96
}
62
97
} else {
63
98
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) {
77
112
}
78
113
// send event?
79
114
// 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);
80
117
}
81
118
82
119
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_BUS_RESET) {
83
120
usb_serial_jtag_ll_clr_intsts_mask (USB_SERIAL_JTAG_INTR_BUS_RESET);
84
121
initial_empty = false ;
85
122
usb_serial_jtag_ll_ena_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
86
123
// 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);
87
125
}
88
126
89
127
if (xTaskWoken == pdTRUE) {
@@ -95,13 +133,13 @@ static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
95
133
if (xPortInIsrContext ()){
96
134
xRingbufferSendFromISR (tx_ring_buf, (void *) (&c), 1 , NULL );
97
135
} else {
98
- xRingbufferSend (tx_ring_buf, (void *) (&c), 1 , 0 );
136
+ xRingbufferSend (tx_ring_buf, (void *) (&c), 1 , tx_timeout_ms / portTICK_PERIOD_MS );
99
137
}
100
138
usb_serial_jtag_ll_ena_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
101
139
}
102
140
103
141
HWCDC::HWCDC () {
104
-
142
+
105
143
}
106
144
107
145
HWCDC::~HWCDC (){
@@ -113,8 +151,19 @@ HWCDC::operator bool() const
113
151
return initial_empty;
114
152
}
115
153
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
+
116
162
void HWCDC::begin (unsigned long baud)
117
163
{
164
+ if (tx_lock == NULL ) {
165
+ tx_lock = xSemaphoreCreateMutex ();
166
+ }
118
167
setRxBufferSize (256 );// default if not preset
119
168
setTxBufferSize (256 );// default if not preset
120
169
@@ -123,6 +172,7 @@ void HWCDC::begin(unsigned long baud)
123
172
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){
124
173
isr_log_e (" HW USB CDC failed to init interrupts" );
125
174
end ();
175
+ return ;
126
176
}
127
177
}
128
178
@@ -132,8 +182,19 @@ void HWCDC::end()
132
182
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);
133
183
esp_intr_free (intr_handle);
134
184
intr_handle = NULL ;
185
+ if (tx_lock != NULL ) {
186
+ vSemaphoreDelete (tx_lock);
187
+ }
135
188
setRxBufferSize (0 );
136
189
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;
137
198
}
138
199
139
200
/*
@@ -157,21 +218,57 @@ size_t HWCDC::setTxBufferSize(size_t tx_queue_len){
157
218
158
219
int HWCDC::availableForWrite (void )
159
220
{
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 ;
162
226
}
163
- return xRingbufferGetCurFreeSize (tx_ring_buf);
227
+ size_t a = xRingbufferGetCurFreeSize (tx_ring_buf);
228
+ xSemaphoreGive (tx_lock);
229
+ return a;
164
230
}
165
231
166
232
size_t HWCDC::write (const uint8_t *buffer, size_t size)
167
233
{
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 ){
171
235
return 0 ;
172
236
}
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);
175
272
return size;
176
273
}
177
274
@@ -182,15 +279,23 @@ size_t HWCDC::write(uint8_t c)
182
279
183
280
void HWCDC::flush (void )
184
281
{
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){
186
286
return ;
187
287
}
188
288
UBaseType_t uxItemsWaiting = 0 ;
189
289
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
+ }
190
294
while (uxItemsWaiting){
191
295
delay (5 );
192
296
vRingbufferGetInfo (tx_ring_buf, NULL , NULL , NULL , NULL , &uxItemsWaiting);
193
297
}
298
+ xSemaphoreGive (tx_lock);
194
299
}
195
300
196
301
/*
0 commit comments