From 811d77a88a08e1726b3f459c47ba80d2485a9abb Mon Sep 17 00:00:00 2001 From: Immo Birnbaum Date: Thu, 15 Jul 2021 14:26:11 +0200 Subject: [PATCH] drivers: serial: xlnx_xuartps: Fix interrupt-driven operation Fixes interrupt-driven operation. With the previous way of handling the TX FIFO and the interrupt flags, the operation of the UART was prone to stalling when using it as the console I/O device. Signed-off-by: Immo Birnbaum --- drivers/serial/uart_xlnx_ps.c | 42 +++++++++++++---------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/serial/uart_xlnx_ps.c b/drivers/serial/uart_xlnx_ps.c index 57349a681b5..49ce4a30cef 100644 --- a/drivers/serial/uart_xlnx_ps.c +++ b/drivers/serial/uart_xlnx_ps.c @@ -303,9 +303,6 @@ static int uart_xlnx_ps_init(const struct device *dev) /* Set RX FIFO trigger at 1 data bytes. */ sys_write32(0x01U, reg_base + XUARTPS_RXWM_OFFSET); - /* Set RX timeout to 1, which will be 4 character time */ - sys_write32(0x1U, reg_base + XUARTPS_RXTOUT_OFFSET); - /* Disable all interrupts, polling mode is default */ sys_write32(XUARTPS_IXR_MASK, reg_base + XUARTPS_IDR_OFFSET); @@ -845,20 +842,18 @@ static int uart_xlnx_ps_fifo_fill(const struct device *dev, int size) { const struct uart_xlnx_ps_dev_config *dev_cfg = DEV_CFG(dev); - uint32_t reg_val; - uint32_t reg_base; - int onum = 0; + uint32_t reg_base = dev_cfg->uconf.regs; + uint32_t data_iter = 0; - reg_base = dev_cfg->uconf.regs; - reg_val = sys_read32(reg_base + XUARTPS_SR_OFFSET); - while (onum < size && (reg_val & XUARTPS_SR_TXFULL) == 0) { - sys_write32((uint32_t)(tx_data[onum] & 0xFF), - reg_base + XUARTPS_FIFO_OFFSET); - onum++; - reg_val = sys_read32(reg_base + XUARTPS_SR_OFFSET); + sys_write32(XUARTPS_IXR_TXEMPTY, reg_base + XUARTPS_IDR_OFFSET); + while (size--) { + while ((sys_read32(reg_base + XUARTPS_SR_OFFSET) & XUARTPS_SR_TXFULL) != 0) { + } + sys_write32((uint32_t)tx_data[data_iter++], reg_base + XUARTPS_FIFO_OFFSET); } + sys_write32(XUARTPS_IXR_TXEMPTY, reg_base + XUARTPS_IER_OFFSET); - return onum; + return data_iter; } /** @@ -937,17 +932,12 @@ static void uart_xlnx_ps_irq_tx_disable(const struct device *dev) static int uart_xlnx_ps_irq_tx_ready(const struct device *dev) { const struct uart_xlnx_ps_dev_config *dev_cfg = DEV_CFG(dev); - uint32_t reg_base; - uint32_t reg_val; + uint32_t reg_base = dev_cfg->uconf.regs; + uint32_t reg_val = sys_read32(reg_base + XUARTPS_SR_OFFSET); - reg_base = dev_cfg->uconf.regs; - reg_val = sys_read32(reg_base + XUARTPS_ISR_OFFSET); - if ((reg_val & (XUARTPS_IXR_TTRIG | XUARTPS_IXR_TXEMPTY)) == 0) { + if ((reg_val & (XUARTPS_SR_TTRIG | XUARTPS_SR_TXEMPTY)) == 0) { return 0; } else { - sys_write32( - (XUARTPS_IXR_TTRIG | XUARTPS_IXR_TXEMPTY), - reg_base + XUARTPS_ISR_OFFSET); return 1; } } @@ -1016,11 +1006,9 @@ static void uart_xlnx_ps_irq_rx_disable(const struct device *dev) static int uart_xlnx_ps_irq_rx_ready(const struct device *dev) { const struct uart_xlnx_ps_dev_config *dev_cfg = DEV_CFG(dev); - uint32_t reg_base; - uint32_t reg_val; + uint32_t reg_base = dev_cfg->uconf.regs; + uint32_t reg_val = sys_read32(reg_base + XUARTPS_ISR_OFFSET); - reg_base = dev_cfg->uconf.regs; - reg_val = sys_read32(reg_base + XUARTPS_ISR_OFFSET); if ((reg_val & XUARTPS_IXR_RTRIG) == 0) { return 0; } else { @@ -1107,7 +1095,7 @@ static int uart_xlnx_ps_irq_is_pending(const struct device *dev) */ static int uart_xlnx_ps_irq_update(const struct device *dev) { - (void)dev; + ARG_UNUSED(dev); return 1; }