<div dir="auto">I'm only asking where and how did this get tested? BSPs? Qemu/HW? Input?<div dir="auto"><br></div><div dir="auto">Long overdue. I just hope it stays fixed.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Aug 17, 2021, 3:39 AM  <<a href="mailto:chrisj@rtems.org">chrisj@rtems.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Chris Johns <<a href="mailto:chrisj@rtems.org" target="_blank" rel="noreferrer">chrisj@rtems.org</a>><br>
<br>
- Trigger on a single character entering the RX FIFO<br>
<br>
- Disable the RX timeout<br>
<br>
- Send up to a FIFO full of data<br>
---<br>
 bsps/include/dev/serial/zynq-uart.h       |  1 +<br>
 bsps/shared/dev/serial/zynq-uart-polled.c | 18 ++-----<br>
 bsps/shared/dev/serial/zynq-uart.c        | 66 +++++++++++------------<br>
 3 files changed, 36 insertions(+), 49 deletions(-)<br>
<br>
diff --git a/bsps/include/dev/serial/zynq-uart.h b/bsps/include/dev/serial/zynq-uart.h<br>
index 220d9b7717..b21e16f6de 100644<br>
--- a/bsps/include/dev/serial/zynq-uart.h<br>
+++ b/bsps/include/dev/serial/zynq-uart.h<br>
@@ -52,6 +52,7 @@ extern "C" {<br>
 typedef struct {<br>
   rtems_termios_device_context base;<br>
   volatile struct zynq_uart *regs;<br>
+  int tx_queued;<br>
   bool transmitting;<br>
   rtems_vector_number irq;<br>
 } zynq_uart_context;<br>
diff --git a/bsps/shared/dev/serial/zynq-uart-polled.c b/bsps/shared/dev/serial/zynq-uart-polled.c<br>
index 95c51dea11..201d9070d3 100644<br>
--- a/bsps/shared/dev/serial/zynq-uart-polled.c<br>
+++ b/bsps/shared/dev/serial/zynq-uart-polled.c<br>
@@ -126,30 +126,18 @@ void zynq_uart_initialize(rtems_termios_device_context *base)<br>
<br>
   zynq_cal_baud_rate(ZYNQ_UART_DEFAULT_BAUD, &brgr, &bauddiv, regs->mode);<br>
<br>
-  regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);<br>
-  regs->control = ZYNQ_UART_CONTROL_RXDIS<br>
-    | ZYNQ_UART_CONTROL_TXDIS;<br>
+  regs->control = ZYNQ_UART_CONTROL_RXDIS | ZYNQ_UART_CONTROL_TXDIS;<br>
   regs->mode = ZYNQ_UART_MODE_CHMODE(ZYNQ_UART_MODE_CHMODE_NORMAL)<br>
     | ZYNQ_UART_MODE_PAR(ZYNQ_UART_MODE_PAR_NONE)<br>
     | ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_8);<br>
   regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr);<br>
   regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv);<br>
   /* A Tx/Rx logic reset must be issued after baud rate manipulation */<br>
-  regs->control = ZYNQ_UART_CONTROL_RXDIS<br>
-    | ZYNQ_UART_CONTROL_TXDIS<br>
-    | ZYNQ_UART_CONTROL_RXRES<br>
-    | ZYNQ_UART_CONTROL_TXRES;<br>
+  regs->control = ZYNQ_UART_CONTROL_RXRES | ZYNQ_UART_CONTROL_TXRES;<br>
   regs->rx_fifo_trg_lvl = ZYNQ_UART_RX_FIFO_TRG_LVL_RTRIG(0);<br>
   regs->rx_timeout = ZYNQ_UART_RX_TIMEOUT_RTO(0);<br>
   regs->control = ZYNQ_UART_CONTROL_RXEN<br>
-    | ZYNQ_UART_CONTROL_TXEN<br>
-    | ZYNQ_UART_CONTROL_RSTTO;<br>
-<br>
-  /*<br>
-   * Some ZynqMP UARTs have a hardware bug that causes TX/RX logic restarts to<br>
-   * require a kick after baud rate registers are initialized.<br>
-   */<br>
-  zynq_uart_write_polled(base, 0);<br>
+    | ZYNQ_UART_CONTROL_TXEN;<br>
 }<br>
<br>
 int zynq_uart_read_polled(rtems_termios_device_context *base)<br>
diff --git a/bsps/shared/dev/serial/zynq-uart.c b/bsps/shared/dev/serial/zynq-uart.c<br>
index 8503e31d49..5906a015d9 100644<br>
--- a/bsps/shared/dev/serial/zynq-uart.c<br>
+++ b/bsps/shared/dev/serial/zynq-uart.c<br>
@@ -37,24 +37,25 @@ static void zynq_uart_interrupt(void *arg)<br>
   rtems_termios_tty *tty = arg;<br>
   zynq_uart_context *ctx = rtems_termios_get_device_context(tty);<br>
   volatile zynq_uart *regs = ctx->regs;<br>
-  uint32_t channel_sts;<br>
<br>
-  if ((regs->irq_sts & (ZYNQ_UART_TIMEOUT | ZYNQ_UART_RTRIG)) != 0) {<br>
-    regs->irq_sts = ZYNQ_UART_TIMEOUT | ZYNQ_UART_RTRIG;<br>
-<br>
-    do {<br>
-      char c = (char) ZYNQ_UART_TX_RX_FIFO_FIFO_GET(regs->tx_rx_fifo);<br>
-<br>
-      rtems_termios_enqueue_raw_characters(tty, &c, 1);<br>
-<br>
-      channel_sts = regs->channel_sts;<br>
-    } while ((channel_sts & ZYNQ_UART_CHANNEL_STS_REMPTY) == 0);<br>
-  } else {<br>
-    channel_sts = regs->channel_sts;<br>
+  if ((regs->irq_sts & ZYNQ_UART_RTRIG) != 0) {<br>
+    char buf[32];<br>
+    int c = 0;<br>
+    regs->irq_sts = ZYNQ_UART_RTRIG;<br>
+    while (c < sizeof(buf) &&<br>
+           (regs->channel_sts & ZYNQ_UART_CHANNEL_STS_REMPTY) == 0) {<br>
+       buf[c++] = (char) ZYNQ_UART_TX_RX_FIFO_FIFO_GET(regs->tx_rx_fifo);<br>
+    }<br>
+    rtems_termios_enqueue_raw_characters(tty, buf, c);<br>
   }<br>
<br>
-  if (ctx->transmitting && (channel_sts & ZYNQ_UART_CHANNEL_STS_TEMPTY) != 0) {<br>
-    rtems_termios_dequeue_characters(tty, 1);<br>
+  if (ctx->transmitting &&<br>
+      (regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TEMPTY) != 0) {<br>
+    int sent = ctx->tx_queued;<br>
+    regs->irq_dis = ZYNQ_UART_TEMPTY;<br>
+    ctx->transmitting = false;<br>
+    ctx->tx_queued = 0;<br>
+    rtems_termios_dequeue_characters(tty, sent);<br>
   }<br>
 }<br>
 #endif<br>
@@ -76,11 +77,10 @@ static bool zynq_uart_first_open(<br>
   zynq_uart_initialize(base);<br>
<br>
 #ifdef ZYNQ_CONSOLE_USE_INTERRUPTS<br>
-  regs->rx_timeout = 32;<br>
-  regs->rx_fifo_trg_lvl = ZYNQ_UART_FIFO_DEPTH / 2;<br>
+  regs->rx_fifo_trg_lvl = 1;<br>
   regs->irq_dis = 0xffffffff;<br>
   regs->irq_sts = 0xffffffff;<br>
-  regs->irq_en = ZYNQ_UART_RTRIG | ZYNQ_UART_TIMEOUT;<br>
+  regs->irq_en = ZYNQ_UART_RTRIG;<br>
   sc = rtems_interrupt_handler_install(<br>
     ctx->irq,<br>
     "UART",<br>
@@ -119,18 +119,22 @@ static void zynq_uart_write_support(<br>
   zynq_uart_context *ctx = (zynq_uart_context *) base;<br>
   volatile zynq_uart *regs = ctx->regs;<br>
<br>
+  regs->irq_dis = ZYNQ_UART_TEMPTY;<br>
+<br>
   if (len > 0) {<br>
-    ctx->transmitting = true;<br>
+    const char *p = &buf[0];<br>
     regs->irq_sts = ZYNQ_UART_TEMPTY;<br>
+    while (ctx->tx_queued < 32 && len > 0) {<br>
+      regs->tx_rx_fifo = ZYNQ_UART_TX_RX_FIFO_FIFO(*p);<br>
+      ++p;<br>
+      ++ctx->tx_queued;<br>
+      --len;<br>
+    }<br>
+    ctx->transmitting = true;<br>
     regs->irq_en = ZYNQ_UART_TEMPTY;<br>
-    regs->tx_rx_fifo = ZYNQ_UART_TX_RX_FIFO_FIFO(buf[0]);<br>
-  } else {<br>
-    ctx->transmitting = false;<br>
-    regs->irq_dis = ZYNQ_UART_TEMPTY;<br>
   }<br>
 #else<br>
   ssize_t i;<br>
-<br>
   for (i = 0; i < len; ++i) {<br>
     zynq_uart_write_polled(base, buf[i]);<br>
   }<br>
@@ -208,22 +212,16 @@ static bool zynq_uart_set_attributes(<br>
     mode |= ZYNQ_UART_MODE_NBSTOP(ZYNQ_UART_MODE_NBSTOP_STOP_1);<br>
   }<br>
<br>
-  regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);<br>
+  regs->control = ZYNQ_UART_CONTROL_RXDIS | ZYNQ_UART_CONTROL_TXDIS;<br>
   regs->mode = mode;<br>
   /* Ignore baud rate of B0. There are no modem control lines to de-assert */<br>
   if (baud > 0) {<br>
     regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr);<br>
     regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv);<br>
-    regs->control |= ZYNQ_UART_CONTROL_RXRES<br>
-      | ZYNQ_UART_CONTROL_TXRES;<br>
   }<br>
-  regs->control |= ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN;<br>
-<br>
-  /*<br>
-   * Some ZynqMP UARTs have a hardware bug that causes TX/RX logic restarts to<br>
-   * require a kick after baud rate registers are initialized.<br>
-   */<br>
-  zynq_uart_write_polled(context, 0);<br>
+  regs->control = ZYNQ_UART_CONTROL_RXRES | ZYNQ_UART_CONTROL_TXRES;<br>
+  regs->irq_sts = 0xffffffff;<br>
+  regs->control = ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN;<br>
<br>
   return true;<br>
 }<br>
-- <br>
2.24.1<br>
<br>
_______________________________________________<br>
devel mailing list<br>
<a href="mailto:devel@rtems.org" target="_blank" rel="noreferrer">devel@rtems.org</a><br>
<a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</blockquote></div>