1515#include "esp_intr_alloc.h"
1616#include "driver/usb_serial_jtag.h"
1717#include "soc/periph_defs.h"
18+ #include "soc/soc_caps.h"
1819#include "esp_check.h"
20+ #include "esp_private/periph_ctrl.h"
1921
20- typedef enum {
21- FIFO_IDLE = 0 , /*!< Indicates the fifo is in idle state */
22- FIFO_BUSY = 1 , /*!< Indicates the fifo is in busy state */
23- } fifo_status_t ;
22+ /*
23+ Note: Before you add a workaround for an issue in this driver, please please try
24+ to figure out the actual root cause first. The USB-serial-JTAG is a simple device,
25+ it shouldn't need anything more than a simple, straightforward driver.
26+ */
2427
25- // The hardware buffer max size is 64
28+ // The hardware buffer max size is 64, both for RX and TX.
2629#define USB_SER_JTAG_ENDP_SIZE (64)
27- #define USB_SER_JTAG_RX_MAX_SIZE (64 )
30+ #define USB_SER_JTAG_RX_MAX_SIZE (USB_SER_JTAG_ENDP_SIZE )
2831
2932typedef struct {
3033 intr_handle_t intr_handle ; /*!< USB-SERIAL-JTAG interrupt handler */
31- portMUX_TYPE spinlock ; /*!< Spinlock for usb_serial_jtag */
32- _Atomic fifo_status_t fifo_status ; /*!< Record the status of fifo */
3334
3435 // RX parameters
3536 RingbufHandle_t rx_ring_buf ; /*!< RX ring buffer handler */
36- uint32_t rx_buf_size ; /*!< TX buffer size */
37- uint8_t rx_data_buf [USB_SER_JTAG_ENDP_SIZE ]; /*!< Data buffer to stash FIFO data */
3837
3938 // TX parameters
40- uint32_t tx_buf_size ; /*!< TX buffer size */
4139 RingbufHandle_t tx_ring_buf ; /*!< TX ring buffer handler */
42- uint8_t tx_data_buf [USB_SER_JTAG_ENDP_SIZE ]; /*!< Data buffer to stash TX FIFO data */
40+ uint8_t tx_stash_buf [USB_SER_JTAG_ENDP_SIZE ]; /*!< Data buffer to stash TX FIFO data */
4341 size_t tx_stash_cnt ; /*!< Number of stashed TX FIFO bytes */
4442} usb_serial_jtag_obj_t ;
4543
4644static usb_serial_jtag_obj_t * p_usb_serial_jtag_obj = NULL ;
4745
4846static const char * USB_SERIAL_JTAG_TAG = "usb_serial_jtag" ;
4947
50- static size_t usb_serial_jtag_write_and_flush ( const uint8_t * buf , uint32_t wr_len )
48+ static void usb_serial_jtag_isr_handler_default ( void * arg )
5149{
52- size_t size = usb_serial_jtag_ll_write_txfifo (buf , wr_len );
53- usb_serial_jtag_ll_txfifo_flush ();
54- return size ;
55- }
56-
57- static void usb_serial_jtag_isr_handler_default (void * arg ) {
58- portBASE_TYPE xTaskWoken = 0 ;
50+ BaseType_t xTaskWoken = 0 ;
5951 uint32_t usbjtag_intr_status = 0 ;
6052 usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask ();
6153
6254 if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY ) {
55+ //Clear interrupt so we won't be called until the next transfer finishes.
56+ usb_serial_jtag_ll_clr_intsts_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY );
57+
6358 // Interrupt tells us the host picked up the data we sent.
6459 // If we have more data, we can put it in the buffer and the host will pick that up next.
65- // Send data in isr.
66- // If the hardware fifo is available, write in it. Otherwise, do nothing.
60+ // We expect the TX FIFO to be writable for this. If it's not, somehow someone else
61+ // (ROM print routines?) have snuck in a full buffer before we got here. In that case,
62+ // we simply ignore the interrupt, a new one will come if the buffer is empty again.
6763 if (usb_serial_jtag_ll_txfifo_writable () == 1 ) {
68- // We disable the interrupt here so that the interrupt won't be triggered if there is no data to send.
69-
64+ // Retrieve data from either the stash buffer or, if that's empty, from the ring buffer.
7065 size_t queued_size ;
71- uint8_t * queued_buff = NULL ;
72- bool is_stashed_data = false;
66+ uint8_t * queued_buf = NULL ;
7367 if (p_usb_serial_jtag_obj -> tx_stash_cnt != 0 ) {
7468 // Send stashed tx bytes before reading bytes from ring buffer
75- queued_buff = p_usb_serial_jtag_obj -> tx_data_buf ;
69+ queued_buf = p_usb_serial_jtag_obj -> tx_stash_buf ;
7670 queued_size = p_usb_serial_jtag_obj -> tx_stash_cnt ;
77- is_stashed_data = true;
7871 } else {
7972 // Max 64 data payload size in a single EndPoint
80- queued_buff = (uint8_t * )xRingbufferReceiveUpToFromISR (p_usb_serial_jtag_obj -> tx_ring_buf , & queued_size , USB_SER_JTAG_ENDP_SIZE );
73+ queued_buf = (uint8_t * )xRingbufferReceiveUpToFromISR (p_usb_serial_jtag_obj -> tx_ring_buf , & queued_size , USB_SER_JTAG_ENDP_SIZE );
8174 }
8275
83- usb_serial_jtag_ll_clr_intsts_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY );
84-
85- if (queued_buff != NULL ) {
86-
87- // Although tx_queued_bytes may be larger than 0, we may have
88- // interrupted before xRingbufferSend() was called.
89- // Copy the queued buffer into the TX FIFO
90-
91- // On ringbuffer wrap-around the size can be 0 even though the buffer returned is not NULL
92- if (queued_size > 0 ) {
93- portENTER_CRITICAL_ISR (& p_usb_serial_jtag_obj -> spinlock );
94- atomic_store (& p_usb_serial_jtag_obj -> fifo_status , FIFO_BUSY );
95- uint32_t sent_size = usb_serial_jtag_write_and_flush (queued_buff , queued_size );
96- portEXIT_CRITICAL_ISR (& p_usb_serial_jtag_obj -> spinlock );
97-
98- if (sent_size < queued_size ) {
99- // Not all bytes could be sent at once; stash the unwritten bytes in a tx buffer
100- // stash_size will not larger than USB_SER_JTAG_ENDP_SIZE because queued_size is got from xRingbufferReceiveUpToFromISR
101- size_t stash_size = queued_size - sent_size ;
102- memcpy (p_usb_serial_jtag_obj -> tx_data_buf , & queued_buff [sent_size ], stash_size );
103- p_usb_serial_jtag_obj -> tx_stash_cnt = stash_size ;
104- } else {
105- p_usb_serial_jtag_obj -> tx_stash_cnt = 0 ;
106- // assert if sent_size is larger than queued_size.
107- assert (sent_size <= queued_size );
108- }
76+ if (queued_buf != NULL && queued_size > 0 ) {
77+ // We have some data to send. Send it.
78+ uint32_t sent_size = usb_serial_jtag_ll_write_txfifo (queued_buf , queued_size );
79+ usb_serial_jtag_ll_txfifo_flush ();
80+
81+ // Check if we were able to send everything.
82+ if (sent_size < queued_size ) {
83+ // Not all bytes could be sent at once; stash the unwritten bytes in a buffer
84+ // This will happen if e.g. the rom output functions manage to sneak a few bytes into the
85+ // TX FIFO before this interrupt triggers. Note stash_size will not larger than
86+ // USB_SER_JTAG_ENDP_SIZE because queued_size is obtained from xRingbufferReceiveUpToFromISR.
87+ size_t stash_size = queued_size - sent_size ;
88+ memcpy (p_usb_serial_jtag_obj -> tx_stash_buf , & queued_buf [sent_size ], stash_size );
89+ p_usb_serial_jtag_obj -> tx_stash_cnt = stash_size ;
90+ } else {
91+ p_usb_serial_jtag_obj -> tx_stash_cnt = 0 ;
10992 }
110- if (is_stashed_data == false) {
111- vRingbufferReturnItemFromISR (p_usb_serial_jtag_obj -> tx_ring_buf , queued_buff , & xTaskWoken );
93+ // Return the buffer if we got it from the ring buffer.
94+ if (queued_buf != p_usb_serial_jtag_obj -> tx_stash_buf ) {
95+ vRingbufferReturnItemFromISR (p_usb_serial_jtag_obj -> tx_ring_buf , queued_buf , & xTaskWoken );
11296 }
11397 } else {
98+ // No data to send.
11499 // The last transmit may have sent a full EP worth of data. The host will interpret
115100 // this as a transaction that hasn't finished yet and keep the data in its internal
116101 // buffers rather than releasing it to the program listening on the CDC serial port.
117102 // We need to flush again in order to send a 0-byte packet that ends the transaction.
118103 usb_serial_jtag_ll_txfifo_flush ();
119- // Note that since this doesn't re-enable USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY, the
120- // flush will not by itself cause this ISR to be called again.
104+
105+ // We will also disable the interrupt as for now there's no need to handle the
106+ // TX interrupt again. We'll re-enable this externally if we need data sent.
107+ usb_serial_jtag_ll_disable_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY );
121108 }
122- } else {
123- atomic_store (& p_usb_serial_jtag_obj -> fifo_status , FIFO_IDLE );
124- usb_serial_jtag_ll_clr_intsts_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY );
125109 }
126110 }
127111
128112 if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT ) {
129- // read rx buffer(max length is 64), and send avaliable data to ringbuffer.
130- // Ensure the rx buffer size is larger than RX_MAX_SIZE.
113+ // Acknowledge interrupt
131114 usb_serial_jtag_ll_clr_intsts_mask (USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT );
132- uint32_t rx_fifo_len = usb_serial_jtag_ll_read_rxfifo (p_usb_serial_jtag_obj -> rx_data_buf , USB_SER_JTAG_RX_MAX_SIZE );
133- xRingbufferSendFromISR (p_usb_serial_jtag_obj -> rx_ring_buf , p_usb_serial_jtag_obj -> rx_data_buf , rx_fifo_len , & xTaskWoken );
115+ // Read RX FIFO and send available data to ringbuffer.
116+ uint8_t buf [USB_SER_JTAG_RX_MAX_SIZE ];
117+ uint32_t rx_fifo_len = usb_serial_jtag_ll_read_rxfifo (buf , USB_SER_JTAG_RX_MAX_SIZE );
118+ xRingbufferSendFromISR (p_usb_serial_jtag_obj -> rx_ring_buf , buf , rx_fifo_len , & xTaskWoken );
134119 }
135120
136121 if (xTaskWoken == pdTRUE ) {
@@ -145,18 +130,16 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se
145130 ESP_RETURN_ON_FALSE ((usb_serial_jtag_config -> rx_buffer_size > 0 ), ESP_ERR_INVALID_ARG , USB_SERIAL_JTAG_TAG , "RX buffer is not prepared" );
146131 ESP_RETURN_ON_FALSE ((usb_serial_jtag_config -> rx_buffer_size > USB_SER_JTAG_RX_MAX_SIZE ), ESP_ERR_INVALID_ARG , USB_SERIAL_JTAG_TAG , "RX buffer prepared is so small, should larger than 64" );
147132 ESP_RETURN_ON_FALSE ((usb_serial_jtag_config -> tx_buffer_size > 0 ), ESP_ERR_INVALID_ARG , USB_SERIAL_JTAG_TAG , "TX buffer is not prepared" );
148- p_usb_serial_jtag_obj = (usb_serial_jtag_obj_t * ) heap_caps_calloc (1 , sizeof (usb_serial_jtag_obj_t ), MALLOC_CAP_INTERNAL |MALLOC_CAP_8BIT );
149- p_usb_serial_jtag_obj -> rx_buf_size = usb_serial_jtag_config -> rx_buffer_size ;
150- p_usb_serial_jtag_obj -> tx_buf_size = usb_serial_jtag_config -> tx_buffer_size ;
151- p_usb_serial_jtag_obj -> tx_stash_cnt = 0 ;
152- p_usb_serial_jtag_obj -> spinlock = (portMUX_TYPE )portMUX_INITIALIZER_UNLOCKED ;
133+ p_usb_serial_jtag_obj = (usb_serial_jtag_obj_t * ) heap_caps_calloc (1 , sizeof (usb_serial_jtag_obj_t ), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT );
153134 if (p_usb_serial_jtag_obj == NULL ) {
154135 ESP_LOGE (USB_SERIAL_JTAG_TAG , "memory allocate error" );
155- err = ESP_ERR_NO_MEM ;
156- goto _exit ;
136+ // no `goto _exit` here as there's nothing to clean up and that would make the uninstall
137+ // routine unhappy.
138+ return ESP_ERR_NO_MEM ;
157139 }
140+ p_usb_serial_jtag_obj -> tx_stash_cnt = 0 ;
158141
159- p_usb_serial_jtag_obj -> rx_ring_buf = xRingbufferCreate (p_usb_serial_jtag_obj -> rx_buf_size , RINGBUF_TYPE_BYTEBUF );
142+ p_usb_serial_jtag_obj -> rx_ring_buf = xRingbufferCreate (usb_serial_jtag_config -> rx_buffer_size , RINGBUF_TYPE_BYTEBUF );
160143 if (p_usb_serial_jtag_obj -> rx_ring_buf == NULL ) {
161144 ESP_LOGE (USB_SERIAL_JTAG_TAG , "ringbuffer create error" );
162145 err = ESP_ERR_NO_MEM ;
@@ -172,7 +155,6 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se
172155
173156 // Enable USB-Serial-JTAG peripheral module clock
174157 usb_serial_jtag_ll_enable_bus_clock (true);
175- atomic_store (& p_usb_serial_jtag_obj -> fifo_status , FIFO_IDLE );
176158
177159 // Configure PHY
178160#if USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED
@@ -231,37 +213,29 @@ int usb_serial_jtag_write_bytes(const void* src, size_t size, TickType_t ticks_t
231213 ESP_RETURN_ON_FALSE (src != NULL , ESP_ERR_INVALID_ARG , USB_SERIAL_JTAG_TAG , "Invalid buffer pointer." );
232214 ESP_RETURN_ON_FALSE (p_usb_serial_jtag_obj != NULL , ESP_ERR_INVALID_ARG , USB_SERIAL_JTAG_TAG , "The driver hasn't been initialized" );
233215
234- size_t sent_data = 0 ;
235216 BaseType_t result = pdTRUE ;
236- const uint8_t * buff = (const uint8_t * )src ;
237- if (p_usb_serial_jtag_obj -> fifo_status == FIFO_IDLE ) {
238- portENTER_CRITICAL (& p_usb_serial_jtag_obj -> spinlock );
239- atomic_store (& p_usb_serial_jtag_obj -> fifo_status , FIFO_BUSY );
240- sent_data = usb_serial_jtag_write_and_flush (src , size );
241- portEXIT_CRITICAL (& p_usb_serial_jtag_obj -> spinlock );
242- }
243-
244- // Blocking method, Sending data to ringbuffer, and handle the data in ISR.
245- if (size - sent_data > 0 ) {
246- result = xRingbufferSend (p_usb_serial_jtag_obj -> tx_ring_buf , (void * ) (buff + sent_data ), size - sent_data , ticks_to_wait );
247- } else {
248- atomic_store (& p_usb_serial_jtag_obj -> fifo_status , FIFO_IDLE );
249- }
217+ result = xRingbufferSend (p_usb_serial_jtag_obj -> tx_ring_buf , (void * )src , size , ticks_to_wait );
218+ // Re-enable the TX interrupt. If this was disabled, this will immediately trigger the ISR
219+ // and send the things we just put in the ringbuffer.
250220 usb_serial_jtag_ll_ena_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY );
251221 return (result == pdFALSE ) ? 0 : size ;
252222}
253223
224+ //Note that this is also called when usb_serial_jtag_driver_install errors out and as such should
225+ //work on a half-initialized driver as well.
254226esp_err_t usb_serial_jtag_driver_uninstall (void )
255227{
256- if (p_usb_serial_jtag_obj == NULL ) {
257- ESP_LOGI (USB_SERIAL_JTAG_TAG , "ALREADY NULL " );
228+ if (p_usb_serial_jtag_obj == NULL ) {
229+ ESP_LOGE (USB_SERIAL_JTAG_TAG , "uninstall without install called " );
258230 return ESP_OK ;
259231 }
260232
261- /* Not disable the module clock and usb_pad_enable here since the USJ stdout might still depends on it. */
262- //Disable tx/rx interrupt.
233+ /* Don't disable the module clock and usb_pad_enable here since the USJ stdout might still depends on it. */
234+
263235 usb_serial_jtag_ll_disable_intr_mask (USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT );
264- esp_intr_free (p_usb_serial_jtag_obj -> intr_handle );
236+ if (p_usb_serial_jtag_obj -> intr_handle ) {
237+ esp_intr_free (p_usb_serial_jtag_obj -> intr_handle );
238+ }
265239
266240 if (p_usb_serial_jtag_obj -> rx_ring_buf ) {
267241 vRingbufferDelete (p_usb_serial_jtag_obj -> rx_ring_buf );
0 commit comments