zephyr/drivers/serial
Gustavo Romero 5f40b5d4f9 drivers: uart: uart_cmsdk_apb: Fix uart_irq_is_pending
Currently CMSDK uart_irq_is_pending does not use RX and TX interrupt
bits found in INTSTATUS register to check for pending interrutps but
rather it checks for pending interrupts indirectly by checking if RX and
TX buffers are, respectively, full and empty, i.e. it checks bits 0 and
1 in STATE register instead of bits meant for interrupt status found in
INTSTATUS register.

That is particularly problematic because although a RX interrupt implies
a RX buffer full and a TX interrupt implies a TX buffer empty, the
converse is not true. For instance, a TX buffer might be empty for all
data was processed (sent to serial line) already and no further data was
pushed into TX buffer so it remained empty, without generating any
additional TX interrupt. In that case the current uart_irq_is_pending
implementation reports that there are pending interrupts because of the
following logic:

/* Return true if rx buffer full or tx buffer empty */
return (UART_STRUCT(dev)->state & (UART_RX_BF | UART_TX_BF))
                                != UART_TX_BF;

which will return 1 (true) if STATE[0] = 0 (TX buffer is empty), since
UART_TX_BF = 1, so STATE[0] != UART_TX_BF, which is true (assuming here
for the sake of simplicity that UART_RX_BF = 0, i.e. RX buffer is empty
too).

One of the common uses of uart_irq_is_pending is in ISR in contructs
like the following:

while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
  if (uart_irq_rx_ready(dev) == 0) { // RX buffer is empty
    continue;
  }
  // RX buffer is full, process RX data
}

So the ISR can be called due to a RX interrupt. Upon finishing
processing the RX data uart_irq_is_pending is called to check for any
pending IRQs and if it happens that TX buffer is empty (like in the case
that TX interrupt is totally disabled) execution gets stuck in the while
loop because TX buffer will never transition to full again, i.e. it will
never have a chance to have STATE[0] = 1, so STATE[0] != UART_TX_BF is
always true.

This commit fixes that undesirable and problematic behavior by making
uart_irq_is_pending use the proper bits in the interrupt status register
(INTSTATUS) to determine if there is indeed any pending interrupts.

That, on the other hand, requires that the pending interrupt flags are
not clearly automatically when calling the ISR, otherwise
uart_irq_is_pending() will return immediatly false on the first call
without any data being really processed inside the ISR. Thus, because
both RX and TX buffer (FIFO) are only 1 byte long, that commit clears
the proper interrupts flags precisely when data is processed (fifo_read
and fifo_fill) or when the interrupts are disabled (irq_rx_disable and
irq_tx_disable).

Finally, that commits also takes the chance to update some comments,
specially regarding the need to "prime" when enabling the TX interrupts
(in uart_cmsdk_apb_irq_tx_enable()). The need to "prime" can be verified
in the CMSDK UART reference implementation in Verilog mentioned in the
"Arm Cortex-M System Design Kit" [0], on p. 4-8, section 4.3,
in cmsdk_apb_uart.v. In that implementation it's also possible to verify
that the FIFO is only 1 byte long, justifying the semantics that if
buffers are not full (STATE[0] or STATE[1] = 0) they are _completly_
empty, holding no data at all.

[0] https://documentation-service.arm.com/static/5e8f1c777100066a414f770b

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
2021-03-26 08:39:33 -04:00
..
CMakeLists.txt drivers: serial: ns16550: Remove hard-coded max instance count 2021-01-18 15:45:58 -05:00
Kconfig serial: Add support for GRLIB APBUART 2020-11-13 14:53:55 -08:00
Kconfig.altera_jtag
Kconfig.apbuart serial: apbuart interrupt support 2020-11-13 14:53:55 -08:00
Kconfig.cc13xx_cc26xx drivers: cc13xx_cc26xx: use DT_INST_FOREACH to reduce code duplication 2020-04-23 17:29:53 -05:00
Kconfig.cc32xx
Kconfig.cmsdk_apb kconfig: Clean up header comments and make them consistent 2019-11-04 17:31:27 -05:00
Kconfig.esp32
Kconfig.gecko kconfig: Clean up header comments and make them consistent 2019-11-04 17:31:27 -05:00
Kconfig.imx drivers: serial: uart_imx: Convert driver to new DT_INST macros 2020-04-04 09:34:00 -05:00
Kconfig.leuart_gecko kconfig: Clean up header comments and make them consistent 2019-11-04 17:31:27 -05:00
Kconfig.litex kconfig: Clean up header comments and make them consistent 2019-11-04 17:31:27 -05:00
Kconfig.lpc11u6x drivers: serial: Add support for LPC11U6X UART controllers 2020-07-29 20:12:24 +02:00
Kconfig.mcux drivers: serial: uart_mcux: Convert to DT_INST 2020-04-14 17:52:31 -05:00
Kconfig.mcux_flexcomm drivers: uart: mcux_flexcomm: Convert to DT_INST 2020-04-28 16:54:30 -05:00
Kconfig.mcux_iuart drivers: serial: Add NXP IUART driver 2020-08-14 14:51:50 -05:00
Kconfig.mcux_lpsci drivers: uart: mcux_lpsci: Convert to DT_INST 2020-04-28 16:54:30 -05:00
Kconfig.mcux_lpuart drivers: uart: mcux_lpuart: Convert to DT_INST 2020-04-20 15:50:45 -05:00
Kconfig.miv drivers: uart: miv: convert to DT_INST defines 2020-03-11 16:37:22 -06:00
Kconfig.msp432p4xx
Kconfig.native_posix drivers: serial: native_posix: Convert 2nd UART to be devicetree based 2021-02-18 09:06:21 +01:00
Kconfig.npcx driver: npcx7: fixed typo in Kconfig.npcx files. 2020-12-07 12:11:17 -05:00
Kconfig.nrfx drivers: serial: nrfx_uarte: Add low power mode 2021-03-08 12:51:50 +01:00
Kconfig.ns16550 drivers: serial: ns16550: Remove hard-coded max instance count 2021-01-18 15:45:58 -05:00
Kconfig.nuvoton drivers: serial: add support for Nuvoton series UART 2020-07-01 21:09:25 +02:00
Kconfig.pl011 drivers: pl011: add SBSA mode 2021-01-24 13:59:55 -05:00
Kconfig.psoc6 kconfig: Clean up header comments and make them consistent 2019-11-04 17:31:27 -05:00
Kconfig.rtt drivers: serial: uart_rtt converted to devicetree 2020-09-03 21:51:28 +02:00
Kconfig.rv32m1_lpuart kconfig: Clean up header comments and make them consistent 2019-11-04 17:31:27 -05:00
Kconfig.sam0 kconfig: Clean up header comments and make them consistent 2019-11-04 17:31:27 -05:00
Kconfig.sifive drivers: serial: sifive: use interrupt-cell to set IRQ priority 2021-01-16 17:22:08 -05:00
Kconfig.stellaris arm: Removed support for CC2650 2020-01-18 09:27:55 -06:00
Kconfig.stm32 drivers: serial: implement stm32 uart async api 2021-01-18 19:07:29 +01:00
Kconfig.uart_sam drivers: serial: uart_sam: rework device tree support 2020-04-18 17:04:08 -05:00
Kconfig.usart_sam drivers: serial: usart_sam: rework device tree support 2020-04-18 17:04:08 -05:00
Kconfig.xlnx drivers: serial: add driver for the Xilinx UART Lite IP 2020-08-14 13:35:39 -05:00
Kconfig.xmc4xxx drivers: serial: add XMC seris UART support 2020-05-09 14:21:44 +02:00
leuart_gecko.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_altera_jtag_hal.c drivers: serial: Convert DEVICE_AND_API_INIT to DEVICE_DEFINE 2020-12-19 19:59:21 -05:00
uart_apbuart.c drivers/apbuart: add TX FIFO interrupt support 2021-01-21 15:53:03 -05:00
uart_cc13xx_cc26xx.c power: Rename constraint API 2021-02-15 08:08:36 -05:00
uart_cc32xx.c drivers: uart_cc32xx: use device tree iteration 2021-02-15 08:08:21 -05:00
uart_cmsdk_apb.c drivers: uart: uart_cmsdk_apb: Fix uart_irq_is_pending 2021-03-26 08:39:33 -04:00
uart_esp32.c device: esp32: Convert clock control to use DEVICE_DT_GET 2021-02-18 12:42:53 -06:00
uart_gecko.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_handlers.c device: Const-ify all device driver instance pointers 2020-09-02 13:48:13 +02:00
uart_imx.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_liteuart.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_lpc11u6x.c drivers: serial: uart_lpc11u6x: Convert drivers to new DT device macros 2020-12-19 19:58:33 -05:00
uart_lpc11u6x.h device: Const-ify all device driver instance pointers 2020-09-02 13:48:13 +02:00
uart_mcux_flexcomm.c drivers: serial: NXP: Convert clock control to use DEVICE_DT_GET 2021-02-18 10:39:07 -06:00
uart_mcux_iuart.c drivers: serial: NXP: Convert clock control to use DEVICE_DT_GET 2021-02-18 10:39:07 -06:00
uart_mcux_lpsci.c drivers: serial: NXP: Convert clock control to use DEVICE_DT_GET 2021-02-18 10:39:07 -06:00
uart_mcux_lpuart.c drivers: serial: NXP: Convert clock control to use DEVICE_DT_GET 2021-02-18 10:39:07 -06:00
uart_mcux.c drivers: serial: NXP: Convert clock control to use DEVICE_DT_GET 2021-02-18 10:39:07 -06:00
uart_miv.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_msp432p4xx.c device: Remove DEVICE_DT_DECLARE / DEVICE_DT_INST_DECLARE 2021-01-15 07:16:21 -06:00
uart_native_posix.c drivers: serial: native_posix: Convert 2nd UART to be devicetree based 2021-02-18 09:06:21 +01:00
uart_npcx.c uart-npcx: forward poll requests to fifo when running interrupt mode 2021-03-02 20:33:25 -06:00
uart_nrfx_uart.c device: Remove DEVICE_DT_DECLARE / DEVICE_DT_INST_DECLARE 2021-01-15 07:16:21 -06:00
uart_nrfx_uarte.c drivers: serial: nrfx_uarte: Add low power mode 2021-03-08 12:51:50 +01:00
uart_ns16550_port_x.h drivers: serial: ns16550: Remove hard-coded max instance count 2021-01-18 15:45:58 -05:00
uart_ns16550.c drivers: serial: ns16550: Remove hard-coded max instance count 2021-01-18 15:45:58 -05:00
uart_ns16550.h
uart_nuvoton.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_pl011.c drivers: pl011: add SBSA mode 2021-01-24 13:59:55 -05:00
uart_psoc6.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_rtt.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_rv32m1_lpuart.c device: rv32m1: Convert clock control to use DEVICE_DT_GET 2021-02-18 09:26:39 -06:00
uart_sam0.c drivers: uart: sam0: Convert dma to use DEVICE_DT_GET 2021-03-08 18:22:27 -06:00
uart_sam.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_sifive.c drivers: serial: sifive: use interrupt-cell to set IRQ priority 2021-01-16 17:22:08 -05:00
uart_stellaris.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_stm32.c drivers/serial: stm32: convert dma to new DT_DMA helper macros 2021-03-03 07:24:56 -05:00
uart_stm32.h drivers/serial: stm32: convert dma to new DT_DMA helper macros 2021-03-03 07:24:56 -05:00
uart_xlnx_ps.c device: Remove DEVICE_DT_DECLARE / DEVICE_DT_INST_DECLARE 2021-01-15 07:16:21 -06:00
uart_xlnx_uartlite.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
uart_xmc4xxx.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00
usart_sam.c drivers: uart: Convert drivers to new DT device macros 2020-12-15 15:28:49 -06:00