23
23
#include " esp_intr_alloc.h"
24
24
#include " soc/periph_defs.h"
25
25
#include " hal/usb_serial_jtag_ll.h"
26
+ #include " esp_private/startup_internal.h"
27
+ #include " esp_freertos_hooks.h"
26
28
27
29
ESP_EVENT_DEFINE_BASE (ARDUINO_HW_CDC_EVENTS);
28
30
@@ -33,8 +35,47 @@ static intr_handle_t intr_handle = NULL;
33
35
static volatile bool connected = false ;
34
36
static xSemaphoreHandle tx_lock = NULL ;
35
37
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
+ }
38
79
39
80
// timeout has no effect when USB CDC is unplugged
40
81
static uint32_t tx_timeout_ms = 100 ;
@@ -86,7 +127,7 @@ static void hw_cdc_isr_handler(void *arg) {
86
127
if (tx_ring_buf != NULL && usb_serial_jtag_ll_txfifo_writable () == 1 ) {
87
128
// We disable the interrupt here so that the interrupt won't be triggered if there is no data to send.
88
129
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 ;
90
131
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR (tx_ring_buf, &queued_size, 64 );
91
132
// If the hardware fifo is avaliable, write in it. Otherwise, do nothing.
92
133
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) {
128
169
connected = false ;
129
170
}
130
171
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
+ // }
135
176
136
177
if (xTaskWoken == pdTRUE) {
137
178
portYIELD_FROM_ISR ();
138
179
}
139
180
}
140
181
141
- inline bool HWCDC::isPlugged (void )
182
+ bool HWCDC::isPlugged (void )
142
183
{
143
- return (lastSOF_ms + SOF_TIMEOUT) >= millis ();
184
+ return s_usb_serial_jtag_conn_status; // (lastSOF_ms + SOF_TIMEOUT) >= millis();
144
185
}
145
186
146
187
bool HWCDC::isCDC_Connected ()
@@ -151,10 +192,10 @@ bool HWCDC::isCDC_Connected()
151
192
if (!isPlugged ()) {
152
193
connected = false ;
153
194
running = false ;
154
- SOF_TIMEOUT = 5 ; // SOF timeout when unplugged
195
+ // SOF_TIMEOUT = 5; // SOF timeout when unplugged
155
196
return false ;
156
- } else {
157
- SOF_TIMEOUT = 50 ; // SOF timeout when plugged
197
+ // } else {
198
+ // SOF_TIMEOUT = 50; // SOF timeout when plugged
158
199
}
159
200
160
201
if (connected) {
@@ -232,11 +273,12 @@ static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
232
273
xRingbufferSend (tx_ring_buf, (void *) (&c), 1 , tx_timeout_ms / portTICK_PERIOD_MS);
233
274
}
234
275
usb_serial_jtag_ll_txfifo_flush ();
276
+ usb_serial_jtag_ll_ena_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
235
277
}
236
278
237
279
HWCDC::HWCDC () {
238
- lastSOF_ms = 0 ;
239
- SOF_TIMEOUT = 5 ;
280
+ // lastSOF_ms = 0;
281
+ // SOF_TIMEOUT = 5;
240
282
}
241
283
242
284
HWCDC::~HWCDC (){
@@ -286,8 +328,8 @@ void HWCDC::begin(unsigned long baud)
286
328
}
287
329
288
330
// 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
291
333
292
334
// Configure PHY
293
335
// USB_Serial_JTAG use internal PHY
@@ -300,7 +342,7 @@ void HWCDC::begin(unsigned long baud)
300
342
USB_SERIAL_JTAG.conf0 .usb_pad_enable = 1 ;
301
343
usb_serial_jtag_ll_disable_intr_mask (USB_SERIAL_JTAG_LL_INTR_MASK);
302
344
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*/ );
304
346
if (!intr_handle && esp_intr_alloc (ETS_USB_SERIAL_JTAG_INTR_SOURCE, 0 , hw_cdc_isr_handler, NULL , &intr_handle) != ESP_OK){
305
347
isr_log_e (" HW USB CDC failed to init interrupts" );
306
348
end ();
@@ -554,9 +596,9 @@ void HWCDC::setDebugOutput(bool en)
554
596
{
555
597
if (en) {
556
598
uartSetDebug (NULL );
557
- ets_install_putc1 ((void (*)(char )) &cdc0_write_char);
599
+ ets_install_putc2 ((void (*)(char )) &cdc0_write_char);
558
600
} else {
559
- ets_install_putc1 (NULL );
601
+ ets_install_putc2 (NULL );
560
602
}
561
603
}
562
604
0 commit comments