Skip to content

Commit c1d8182

Browse files
committed
esp32: Flush usb_serial_jtag TXFIFO from ISR.
This was necessary to un-wedge the USJ TX path on ESP32-P4, I think because the bootloader prints a lot on this chip. I think it might be possible to hit it on other chips, though. The implementation is based on the ESP-IDF driver, which will always add an extra flush when the TXFIFO is empty in case the host is expecting a ZLP. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <[email protected]>
1 parent 0eb2fbb commit c1d8182

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

ports/esp32/usb_serial_jtag.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,31 @@ static void usb_serial_jtag_handle_rx(void) {
7171

7272
static void usb_serial_jtag_isr_handler(void *arg) {
7373
uint32_t flags = usb_serial_jtag_ll_get_intsts_mask();
74-
75-
if (flags & USB_SERIAL_JTAG_INTR_SOF) {
76-
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF);
77-
}
74+
usb_serial_jtag_ll_clr_intsts_mask(flags);
7875

7976
if (flags & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT) {
80-
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
8177
usb_serial_jtag_handle_rx();
8278
mp_hal_wake_main_task_from_isr();
8379
}
80+
81+
if (flags & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) {
82+
// As per the ESP-IDF driver, allow for the possibility the USJ just sent a full
83+
// 64-bit endpoint to the host and now it's waiting for another ZLP to flush the result
84+
// to the OS
85+
usb_serial_jtag_ll_txfifo_flush();
86+
87+
// Disable this interrupt until next time we write into the FIFO
88+
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
89+
}
8490
}
8591

8692
void usb_serial_jtag_init(void) {
93+
// Note: Don't clear the SERIAL_IN_EMPTY interrupt, as it's possible the
94+
// bootloader wrote enough data to the host that we need the interrupt to flush it.
8795
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT |
8896
USB_SERIAL_JTAG_INTR_SOF);
8997
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT |
90-
USB_SERIAL_JTAG_INTR_SOF);
98+
USB_SERIAL_JTAG_INTR_SOF | USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
9199
ESP_ERROR_CHECK(esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1,
92100
usb_serial_jtag_isr_handler, NULL, NULL));
93101
}
@@ -114,10 +122,11 @@ void usb_serial_jtag_tx_strn(const char *str, size_t len) {
114122
}
115123
terminal_connected = true;
116124
l = usb_serial_jtag_ll_write_txfifo((const uint8_t *)str, l);
117-
usb_serial_jtag_ll_txfifo_flush();
118125
str += l;
119126
len -= l;
127+
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
120128
}
129+
usb_serial_jtag_ll_txfifo_flush();
121130
}
122131

123132
#endif // MICROPY_HW_ESP_USB_SERIAL_JTAG

0 commit comments

Comments
 (0)