litex icon indicating copy to clipboard operation
litex copied to clipboard

UART RXEMPTY register does not clear when last character is read

Open swetland opened this issue 3 years ago • 3 comments

A simple loop of:

while (1) {
    while (rd32(UART0_RXEMPTY) != 0) ;
    printf("rx %02x\n", rd32(UART0_RXTX);
};

Will wait until one character arrives and then spin printing the same rx'd character over and over again.

To get RXEMPTY to reflect the new state one has to clear the RX bit in EV_PENDING.

Is this intentional? It's relatively unusual peripheral behavior for the state/status registers to not reflect current status.

Expected behaviour (assuming the rx fifo is initially empty):

When a character arrives:

  • RXEMPTY becomes nonzero
  • EV_STATUS.RX becomes set
  • EV_PENDING.RX becomes set
  • the IRQ is asserted if EV_ENABLE.RX is set

When that character is read from RXTX and the fifo is again empty:

  • RXEMPTY becomes zero
  • EV_STATUS.RX becomes cleared
  • EV_PENDING.RX remains set (and IRQ asserted) until cleared by a software write

swetland avatar Apr 30 '22 23:04 swetland

Thanks for the feedback @swetland, setting rx_fifo_rx_we to True here: https://github.com/enjoy-digital/litex/blob/master/litex/soc/cores/uart.py#L219 should provide the behaviour you are expecting, could you do a test?

enjoy-digital avatar May 03 '22 11:05 enjoy-digital

I can confirm that this does indeed result in RXEMPTY becoming nonzero when the last character is read from the fifo. Thanks!

The bios firmware does not appear to be impacted by the change (probably because it's doing interrupt driven UART io rather than polling, so I suspect it never looks at RXEMPTY). Serial console and serial boot continue to work as expected.

swetland avatar May 03 '22 11:05 swetland

Good, thanks. I'll have a closer look at this to see this if this could make sense to default to this behaviour.

enjoy-digital avatar May 03 '22 12:05 enjoy-digital