From aa9b73c50b575fc2fcb4f56a4dd5995d1d844e63 Mon Sep 17 00:00:00 2001 From: Ahmet Alincak Date: Fri, 3 Jul 2026 14:51:30 +0300 Subject: [PATCH] Do not reset USB baudrate after a bus reset event received to preserve existing UART comm. --- source/hic_hal/maxim/max32625/uart.c | 93 +++++++++-- source/hic_hal/maxim/max32625/usbd_max32625.c | 151 +++++++++++++----- 2 files changed, 184 insertions(+), 60 deletions(-) diff --git a/source/hic_hal/maxim/max32625/uart.c b/source/hic_hal/maxim/max32625/uart.c index acad019a50..274a927fc4 100755 --- a/source/hic_hal/maxim/max32625/uart.c +++ b/source/hic_hal/maxim/max32625/uart.c @@ -30,6 +30,7 @@ // Track bit rate to avoid calculation from bus clock, clock scaler and baud divisor values static uint32_t baudrate; +static uint8_t is_reset = 0; static mxc_uart_regs_t *CdcAcmUart = NULL; static mxc_uart_fifo_regs_t *CdcAcmUartFifo = NULL; @@ -51,6 +52,10 @@ static void set_bitrate(uint32_t target_baud) uint32_t baud, diff_baud; uint32_t baud_1, diff_baud_1; + if (is_reset) { + is_reset = 0; + return; // Do not change the baudrate if the UART is in reset state since host does not reconfigure the baudrate. + } // Setup system clock divider for given bit rate clk_scale = 0; do { @@ -185,6 +190,7 @@ int32_t uart_initialize(void) // Enable receive and transmit fifos CdcAcmUart->ctrl |= (MXC_F_UART_CTRL_RX_FIFO_EN | MXC_F_UART_CTRL_TX_FIFO_EN); + NVIC_SetPriority(CdcAcmUartIrqNumber, 3); NVIC_EnableIRQ(CdcAcmUartIrqNumber); // Set transmit almost empty level to three-quarters of the fifo size @@ -230,7 +236,7 @@ int32_t uart_reset(void) { circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data)); circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data)); - + is_reset = 1; return 1; } @@ -328,35 +334,77 @@ int32_t uart_get_configuration(UART_Configuration *config) /******************************************************************************/ int32_t uart_write_free(void) { - return circ_buf_count_free(&write_buffer); + uint32_t cnt; + + /* Disable UART IRQ to get consistent view of head/tail */ + NVIC_DisableIRQ(CdcAcmUartIrqNumber); + + if (write_buffer.tail >= write_buffer.head) { + cnt = write_buffer.size - (write_buffer.tail - write_buffer.head) - 1; + } else { + cnt = write_buffer.head - write_buffer.tail - 1; + } + + NVIC_EnableIRQ(CdcAcmUartIrqNumber); + return cnt; } /******************************************************************************/ int32_t uart_write_data(uint8_t *data, uint16_t size) { uint16_t xfer_count = size; + uint16_t written = 0; + NVIC_DisableIRQ(CdcAcmUartIrqNumber); // Prioritize writes to TX FIFO, then to write_buffer - if (circ_buf_count_used(&write_buffer) == 0) { + if (write_buffer.head == write_buffer.tail) { while ((((CdcAcmUart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) >> MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY_POS) < MXC_UART_FIFO_DEPTH) && (xfer_count > 0)) { - NVIC_DisableIRQ(CdcAcmUartIrqNumber); CdcAcmUart->intfl = MXC_F_UART_INTFL_TX_FIFO_AE; CdcAcmUartFifo->tx = *data++; xfer_count--; - NVIC_EnableIRQ(CdcAcmUartIrqNumber); + written++; } } - xfer_count = circ_buf_write(&write_buffer, data, xfer_count); - - return size - xfer_count; + while (xfer_count > 0) { + uint32_t next_tail = write_buffer.tail + 1; + if (next_tail >= write_buffer.size) { + next_tail = 0; + } + if (next_tail == write_buffer.head) { + break; // Buffer full + } + write_buffer.buf[write_buffer.tail] = *data++; + write_buffer.tail = next_tail; + xfer_count--; + written++; + } + NVIC_EnableIRQ(CdcAcmUartIrqNumber); + + return written; } /******************************************************************************/ int32_t uart_read_data(uint8_t *data, uint16_t size) { - return circ_buf_read(&read_buffer, data, size); + uint16_t read_count = 0; + + /* Disable UART IRQ to protect buffer state from concurrent ISR access. + * We read read_buffer.tail (written by ISR) so need protection. */ + NVIC_DisableIRQ(CdcAcmUartIrqNumber); + + while ((read_count < size) && (read_buffer.head != read_buffer.tail)) { + data[read_count++] = read_buffer.buf[read_buffer.head]; + uint32_t next_head = read_buffer.head + 1; + if (next_head >= read_buffer.size) { + next_head = 0; + } + read_buffer.head = next_head; + } + + NVIC_EnableIRQ(CdcAcmUartIrqNumber); + return read_count; } /******************************************************************************/ @@ -374,11 +422,18 @@ void UART_IRQHandler(void) } if (intfl & MXC_F_UART_INTFL_RX_FIFO_NOT_EMPTY) { - while ((CdcAcmUart->rx_fifo_ctrl & MXC_F_UART_RX_FIFO_CTRL_FIFO_ENTRY) && - circ_buf_count_free(&read_buffer)) { - circ_buf_push(&read_buffer, CdcAcmUartFifo->rx); - CdcAcmUart->intfl = MXC_F_UART_INTFL_RX_FIFO_NOT_EMPTY; - } + while (CdcAcmUart->rx_fifo_ctrl & MXC_F_UART_RX_FIFO_CTRL_FIFO_ENTRY) { + uint32_t next_tail = read_buffer.tail + 1; + if (next_tail >= read_buffer.size) { + next_tail = 0; + } + if (next_tail == read_buffer.head) { + break; /* Buffer full */ + } + read_buffer.buf[read_buffer.tail] = CdcAcmUartFifo->rx; + read_buffer.tail = next_tail; + CdcAcmUart->intfl = MXC_F_UART_INTFL_RX_FIFO_NOT_EMPTY; + } } if (intfl & MXC_F_UART_INTFL_TX_FIFO_AE) { @@ -387,9 +442,13 @@ void UART_IRQHandler(void) a) write buffer contains data and b) transmit FIFO is not full */ - while (circ_buf_count_used(&write_buffer) && - (((CdcAcmUart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) >> MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY_POS) < MXC_UART_FIFO_DEPTH)) { - CdcAcmUartFifo->tx = circ_buf_pop(&write_buffer); + while (write_buffer.head != write_buffer.tail && + (((CdcAcmUart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) >> MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY_POS) < MXC_UART_FIFO_DEPTH)) { + CdcAcmUartFifo->tx = write_buffer.buf[write_buffer.head]; + write_buffer.head++; + if (write_buffer.head >= write_buffer.size) { + write_buffer.head = 0; + } } } } diff --git a/source/hic_hal/maxim/max32625/usbd_max32625.c b/source/hic_hal/maxim/max32625/usbd_max32625.c index 37cbd1e9f7..de7162c3da 100755 --- a/source/hic_hal/maxim/max32625/usbd_max32625.c +++ b/source/hic_hal/maxim/max32625/usbd_max32625.c @@ -30,7 +30,7 @@ #define EPNUM_MASK (~USB_ENDPOINT_DIRECTION_MASK) #define INIT_INTS (MXC_F_USB_DEV_INTEN_BRST | MXC_F_USB_DEV_INTFL_BRST_DN | MXC_F_USB_DEV_INTEN_VBUS | MXC_F_USB_DEV_INTFL_NO_VBUS) -#define CONNECT_INTS (MXC_F_USB_DEV_INTEN_SETUP | MXC_F_USB_DEV_INTEN_EP_IN | MXC_F_USB_DEV_INTEN_EP_OUT | MXC_F_USB_DEV_INTEN_DMA_ERR) +#define CONNECT_INTS (MXC_F_USB_DEV_INTEN_SETUP | MXC_F_USB_DEV_INTEN_EP_IN | MXC_F_USB_DEV_INTEN_EP_OUT | MXC_F_USB_DEV_INTEN_DMA_ERR | MXC_F_USB_DEV_INTEN_BUF_OVR) typedef struct { volatile uint32_t buf0_desc; @@ -69,14 +69,18 @@ static volatile int ep0_expect_zlp; * of Maxim's microcontrollers does not provide and SOF interrupt. A periodic * timer interrupt is used instead. */ +extern void main_board_event(void); + /******************************************************************************/ void TMR0_IRQHandler(void) { MXC_TMR0->intfl = MXC_TMR0->intfl; + main_board_event(); /* Signal main task, don't process in ISR */ +} - if (usbd_configured()) { - USBD_CDC_ACM_SOF_Event(); - } +void board_custom_event(void) +{ + USBD_CDC_ACM_SOF_Event(); } #endif @@ -176,6 +180,9 @@ void USBD_Init (void) /* enable some interrupts */ MXC_USB->dev_inten = INIT_INTS; + + /* Set USB to higher priority than UART/Timer to ensure USB completes transfers */ + NVIC_SetPriority(USB_IRQn, 0); /* Highest priority */ NVIC_EnableIRQ(USB_IRQn); } @@ -241,6 +248,7 @@ void USBD_Configure (BOOL cfg) // Enable the interrupt MXC_TMR0->intfl = MXC_TMR0->intfl; + NVIC_SetPriority(TMR0_0_IRQn, 2); /* Lower priority than USB */ NVIC_EnableIRQ(TMR0_0_IRQn); MXC_TMR0->inten = MXC_F_TMR_INTEN_TIMER0; @@ -493,6 +501,86 @@ void USB_IRQHandler (void) USBD_SignalHandler(); } +uint32_t USBD_Handler_MSC(uint32_t ep_int_in, uint32_t ep_int_out) +{ + uint32_t ret = 0; + uint32_t mask = 1; + + mask = 1 << USBD_MSC_EP_BULKIN; + if (ep_int_in & mask) { + if (USBD_P_EP[USBD_MSC_EP_BULKIN]) { + USBD_P_EP[USBD_MSC_EP_BULKIN](USBD_EVT_IN); + ret |= (mask << 16); + } + } + + mask = 1 << USBD_MSC_EP_BULKOUT; + if (ep_int_out & mask) { + if (USBD_P_EP[USBD_MSC_EP_BULKOUT]) { + USBD_P_EP[USBD_MSC_EP_BULKOUT](USBD_EVT_OUT); + ret |= mask; + } + } + + return ret; +} + +uint32_t USBD_Handler_CDC(uint32_t ep_int_in, uint32_t ep_int_out) +{ + uint32_t ret = 0; + uint32_t mask = 1; + + mask = 1 << USBD_CDC_ACM_EP_INTIN; + if (ep_int_in & mask) { + if (USBD_P_EP[USBD_CDC_ACM_EP_INTIN]) { + USBD_P_EP[USBD_CDC_ACM_EP_INTIN](USBD_EVT_IN); + ret |= (mask << 16); + } + } + + mask = 1 << USBD_CDC_ACM_EP_BULKIN; + if (ep_int_in & mask) { + if (USBD_P_EP[USBD_CDC_ACM_EP_BULKIN]) { + USBD_P_EP[USBD_CDC_ACM_EP_BULKIN](USBD_EVT_IN); + ret |= (mask << 16); + } + } + + mask = 1 << USBD_CDC_ACM_EP_BULKOUT; + if (ep_int_out & mask) { + if (USBD_P_EP[USBD_CDC_ACM_EP_BULKOUT]) { + USBD_P_EP[USBD_CDC_ACM_EP_BULKOUT](USBD_EVT_OUT); + ret |= mask; + } + } + + return ret; +} + +uint32_t USBD_Handler_HID(uint32_t ep_int_in, uint32_t ep_int_out) +{ + uint32_t ret = 0; + uint32_t mask = 1; + + mask = 1 << USBD_HID_EP_INTIN; + if (ep_int_in & mask) { + if (USBD_P_EP[USBD_HID_EP_INTIN]) { + USBD_P_EP[USBD_HID_EP_INTIN](USBD_EVT_IN); + ret |= (mask << 16); + } + } + + mask = 1 << USBD_HID_EP_INTOUT; + if (ep_int_out & mask) { + if (USBD_P_EP[USBD_HID_EP_INTOUT]) { + USBD_P_EP[USBD_HID_EP_INTOUT](USBD_EVT_OUT); + ret |= mask; + } + } + + return ret; +} + void USBD_Handler(void) { uint32_t irq_flags; @@ -589,52 +677,29 @@ void USBD_Handler(void) #endif } - if (irq_flags & MXC_F_USB_DEV_INTFL_EP_IN) { + if (irq_flags & MXC_F_USB_DEV_INTFL_EP_IN || irq_flags & MXC_F_USB_DEV_INTFL_EP_OUT) { + uint32_t ep_in_int = MXC_USB->in_int; + uint32_t ep_out_int = MXC_USB->out_int; - // Read and clear endpoint interrupts - ep_int = MXC_USB->in_int; - MXC_USB->in_int = ep_int; + MXC_USB->in_int = ep_in_int; + MXC_USB->out_int = ep_out_int; - mask = 1; - for (ep = 0; ep < MXC_USB_NUM_EP; ep++) { - if (ep_int & mask) { -#ifdef __RTX - if (USBD_RTX_EPTask[ep]) { - isr_evt_set(USBD_EVT_IN, USBD_RTX_EPTask[ep]); - } -#else - if (USBD_P_EP[ep]) { - USBD_P_EP[ep](USBD_EVT_IN); - } -#endif - } - - mask <<= 1; + if (ep_in_int & 1) { + USBD_P_EP[0](USBD_EVT_IN); } - } - - if (irq_flags & MXC_F_USB_DEV_INTFL_EP_OUT) { - // Read and clear endpoint interrupts - ep_int = MXC_USB->out_int; - MXC_USB->out_int = ep_int; + USBD_Handler_HID(ep_in_int, 0); + USBD_Handler_MSC(ep_in_int, 0); - mask = 1; - for (ep = 0; ep < MXC_USB_NUM_EP; ep++) { - if (ep_int & mask) { -#ifdef __RTX - if (USBD_RTX_EPTask[ep]) { - isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[ep]); - } -#else - if (USBD_P_EP[ep]) { - USBD_P_EP[ep](USBD_EVT_OUT); - } -#endif - } - mask <<= 1; + if (ep_out_int & 1) { + USBD_P_EP[0](USBD_EVT_OUT); } + + // Read and clear endpoint interrupts + USBD_Handler_HID(0, ep_out_int); + USBD_Handler_MSC(0, ep_out_int); + USBD_Handler_CDC(ep_in_int, ep_out_int); } if (irq_flags & MXC_F_USB_DEV_INTFL_DMA_ERR) {