2323#include " esp_intr_alloc.h"
2424#include " soc/periph_defs.h"
2525#include " hal/usb_serial_jtag_ll.h"
26+ #include " esp_private/startup_internal.h"
27+ #include " esp_freertos_hooks.h"
2628
2729ESP_EVENT_DEFINE_BASE (ARDUINO_HW_CDC_EVENTS);
2830
@@ -33,8 +35,47 @@ static intr_handle_t intr_handle = NULL;
3335static volatile bool connected = false ;
3436static xSemaphoreHandle tx_lock = NULL ;
3537
36- static volatile unsigned long lastSOF_ms;
37- static volatile uint8_t SOF_TIMEOUT;
38+ // SOF in ISR causes problems for uploading firmware
39+ // static volatile unsigned long lastSOF_ms;
40+ // static volatile uint8_t SOF_TIMEOUT;
41+ // detecting SOF from a timer seems to work with esptool.py
42+ static volatile bool s_usb_serial_jtag_conn_status;
43+ static volatile uint32_t remaining_allowed_no_sof_ticks;
44+ #define USJ_DISCONNECT_CONFIRM_PERIOD_MS 5
45+ #define ALLOWED_NO_SOF_TICKS pdMS_TO_TICKS (USJ_DISCONNECT_CONFIRM_PERIOD_MS)
46+
47+ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void )
48+ {
49+ // SOF packet is sent by the HOST every 1ms on a full speed bus
50+ // Between two consecutive tick hooks, there will be at least 1ms (selectable tick rate range is 1 - 1000Hz)
51+ // Therefore, SOF intr bit must have be raised at every tick hook if it is connected to a HOST
52+ // Here, the strategy is: Always assume USB Serial/JTAG is connected until we are sure it is not connected
53+ // Consider it is disconnected only if SOF intr bit is not raised within (ALLOWED_NO_SOF_TICKS + 1) tick periods
54+ bool sof_received = USB_SERIAL_JTAG.int_raw .sof_int_raw == 1 ;
55+ usb_serial_jtag_ll_clr_intsts_mask (USB_SERIAL_JTAG_INTR_SOF);
56+
57+ if (s_usb_serial_jtag_conn_status != sof_received) {
58+ if (!sof_received) {
59+ if (remaining_allowed_no_sof_ticks > 0 ) {
60+ remaining_allowed_no_sof_ticks--;
61+ } else {
62+ s_usb_serial_jtag_conn_status = false ;
63+ }
64+ } else {
65+ s_usb_serial_jtag_conn_status = true ;
66+ remaining_allowed_no_sof_ticks = ALLOWED_NO_SOF_TICKS;
67+ }
68+ }
69+
70+ }
71+
72+ // runs on Core 0
73+ ESP_SYSTEM_INIT_FN (usb_serial_jtag_conn_status_init, BIT(0 ))
74+ {
75+ s_usb_serial_jtag_conn_status = true ;
76+ remaining_allowed_no_sof_ticks = ALLOWED_NO_SOF_TICKS;
77+ esp_register_freertos_tick_hook (usb_serial_jtag_sof_tick_hook);
78+ }
3879
3980// timeout has no effect when USB CDC is unplugged
4081static uint32_t tx_timeout_ms = 100 ;
@@ -86,7 +127,7 @@ static void hw_cdc_isr_handler(void *arg) {
86127 if (tx_ring_buf != NULL && usb_serial_jtag_ll_txfifo_writable () == 1 ) {
87128 // We disable the interrupt here so that the interrupt won't be triggered if there is no data to send.
88129 usb_serial_jtag_ll_disable_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
89- size_t queued_size;
130+ size_t queued_size = 0 ;
90131 uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR (tx_ring_buf, &queued_size, 64 );
91132 // If the hardware fifo is avaliable, write in it. Otherwise, do nothing.
92133 if (queued_buff != NULL ) { // Although tx_queued_bytes may be larger than 0. We may have interrupt before xRingbufferSend() was called.
@@ -128,19 +169,19 @@ static void hw_cdc_isr_handler(void *arg) {
128169 connected = false ;
129170 }
130171
131- if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SOF) {
132- usb_serial_jtag_ll_clr_intsts_mask (USB_SERIAL_JTAG_INTR_SOF);
133- lastSOF_ms = millis ();
134- }
172+ // if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SOF) {
173+ // usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF);
174+ // lastSOF_ms = millis();
175+ // }
135176
136177 if (xTaskWoken == pdTRUE) {
137178 portYIELD_FROM_ISR ();
138179 }
139180}
140181
141- inline bool HWCDC::isPlugged (void )
182+ bool HWCDC::isPlugged (void )
142183{
143- return (lastSOF_ms + SOF_TIMEOUT) >= millis ();
184+ return s_usb_serial_jtag_conn_status; // (lastSOF_ms + SOF_TIMEOUT) >= millis();
144185}
145186
146187bool HWCDC::isCDC_Connected ()
@@ -151,10 +192,10 @@ bool HWCDC::isCDC_Connected()
151192 if (!isPlugged ()) {
152193 connected = false ;
153194 running = false ;
154- SOF_TIMEOUT = 5 ; // SOF timeout when unplugged
195+ // SOF_TIMEOUT = 5; // SOF timeout when unplugged
155196 return false ;
156- } else {
157- SOF_TIMEOUT = 50 ; // SOF timeout when plugged
197+ // } else {
198+ // SOF_TIMEOUT = 50; // SOF timeout when plugged
158199 }
159200
160201 if (connected) {
@@ -232,11 +273,12 @@ static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
232273 xRingbufferSend (tx_ring_buf, (void *) (&c), 1 , tx_timeout_ms / portTICK_PERIOD_MS);
233274 }
234275 usb_serial_jtag_ll_txfifo_flush ();
276+ usb_serial_jtag_ll_ena_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
235277}
236278
237279HWCDC::HWCDC () {
238- lastSOF_ms = 0 ;
239- SOF_TIMEOUT = 5 ;
280+ // lastSOF_ms = 0;
281+ // SOF_TIMEOUT = 5;
240282}
241283
242284HWCDC::~HWCDC (){
@@ -286,8 +328,8 @@ void HWCDC::begin(unsigned long baud)
286328 }
287329
288330 // the HW Serial pins needs to be first deinited in order to allow `if(Serial)` to work :-(
289- deinit ();
290- delay (10 ); // USB Host has to enumerate it again
331+ // deinit();
332+ // delay(10); // USB Host has to enumerate it again
291333
292334 // Configure PHY
293335 // USB_Serial_JTAG use internal PHY
@@ -300,7 +342,7 @@ void HWCDC::begin(unsigned long baud)
300342 USB_SERIAL_JTAG.conf0 .usb_pad_enable = 1 ;
301343 usb_serial_jtag_ll_disable_intr_mask (USB_SERIAL_JTAG_LL_INTR_MASK);
302344 usb_serial_jtag_ll_ena_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT
303- | USB_SERIAL_JTAG_INTR_BUS_RESET | USB_SERIAL_JTAG_INTR_SOF);
345+ | USB_SERIAL_JTAG_INTR_BUS_RESET /* | USB_SERIAL_JTAG_INTR_SOF*/ );
304346 if (!intr_handle && esp_intr_alloc (ETS_USB_SERIAL_JTAG_INTR_SOURCE, 0 , hw_cdc_isr_handler, NULL , &intr_handle) != ESP_OK){
305347 isr_log_e (" HW USB CDC failed to init interrupts" );
306348 end ();
@@ -554,9 +596,9 @@ void HWCDC::setDebugOutput(bool en)
554596{
555597 if (en) {
556598 uartSetDebug (NULL );
557- ets_install_putc1 ((void (*)(char )) &cdc0_write_char);
599+ ets_install_putc2 ((void (*)(char )) &cdc0_write_char);
558600 } else {
559- ets_install_putc1 (NULL );
601+ ets_install_putc2 (NULL );
560602 }
561603}
562604
0 commit comments