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+
2729static RingbufHandle_t tx_ring_buf = NULL ;
2830static xQueueHandle rx_queue = NULL ;
2931static uint8_t rx_data_buf[64 ];
3032static intr_handle_t intr_handle = NULL ;
3133static 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
3364static 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
103141HWCDC::HWCDC () {
104-
142+
105143}
106144
107145HWCDC::~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+
116162void 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
158219int 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
166232size_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
183280void 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/*
0 commit comments