cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Observer
Observer
365 Views
Registered: ‎05-08-2018

UART 16550 v2.0 In FIFO mode receives interrupt on every byte

I am running AXI UART 16550 implemented for ZCU102 evaluation board (UltraScale+). 

Only Rx interrupt is enabled (Tx is disabled). FIFO is configured for any thrigger level other than 1, I have tried 14, 8, 4. I have cretated an example to count number of interrupt received and figured out that an interrupt is triggered for every incoming byte

What am I doing wrong?

Thanks

 

Here is my initialization and IRQ function:

    /* Set word length, stop bits, and parity based off configuration */

    *REG_PTR(vaddr, LCR) |= (LCR_WLS(uart_conf->word_len) | (uart_conf->stop_bits * LCR_STB));

    if (uart_conf->parity != UART16650_PARITY_NO) {

        *REG_PTR(vaddr, LCR) |= (LCR_PEN | (uart_conf->parity * LCR_EPS));

    }

 

    *REG_PTR(vaddr, IIR);  // clear Tx interrupt

    *REG_PTR(vaddr, FCR) = FCR_FIFOEN | FCR_RCFR | FCR_XMFR | FCR_RFTL(3);

    *REG_PTR(m_vaddr, IER) = (IER_EFBFI | IER_ELSI);

And interrupt processing (this function gets called from IRQ handler:

int axi_process_interrupt(int uartIndex, char *pbuf, int *nbytes)

{

                unsigned int vLSR;

                ps_chardevice_t* d = uarts[uartIndex].dev;

                unsigned int vIIR = *REG_PTR(d->vaddr, IIR);

                if ((vIIR & INTERRUPT_PENDING_MASK) == 0)

                {// interrupt pending

                                unsigned int iir = (vIIR & INTERRUPT_ID_MASK) >> 1;

                                switch (iir)

                                {

                                case uart16550_RECEIVER_LINE_STATUS:

                                                // clear interrupt

                                                vLSR = *REG_PTR(d->vaddr, LSR);

                                                if ((vLSR & 0x80) != 0)

                                                return uart16550_RECEIVER_LINE_STATUS;

                                                break;

                                case uart16550_CHARACTER_TIMEOUT:

                                case uart16550_DATA_AVAILABLE:

                                                // read date from FIFO. This interrupt is cleared when the Receiver FIFO drops below the trigger level.

                                                *nbytes = 0;

                                                while (true)

                                                {

                                                                unsigned int vLSR = *REG_PTR(d->vaddr, LSR);

                                                                if ((vLSR & 0x2) != 0)

                                                                             return -1; // Overrun Error.

                                                                if ((vLSR & 0x1) == 0)

                                                                              break;

                                                                // data is available

                                                                pbuf[*nbytes] = (*REG_PTR(d->vaddr, RBR)) & 0xFF;

                                                                (*nbytes)++;

                                                }

                                                return uart16550_DATA_AVAILABLE;

                                                break;

                                case uart16550_TX_IS_EMPTY:

                                                return uart16550_TX_IS_EMPTY;

                                                break;

                                }

                }

                return -2;

}

0 Kudos