Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 76 additions & 17 deletions source/hic_hal/maxim/max32625/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

/******************************************************************************/
Expand All @@ -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) {
Expand All @@ -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;
}
}
}
}
Expand Down
151 changes: 108 additions & 43 deletions source/hic_hal/maxim/max32625/usbd_max32625.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
Loading