From 0f50df41f1b5bce2cb8155c2bd19e8d8a2dda727 Mon Sep 17 00:00:00 2001 From: Nick Kraus Date: Sun, 15 Oct 2023 15:14:24 -0400 Subject: [PATCH] drivers: uart_emul: Add Emulated Errors Allows test code to set UART errors, for driver code wanting to test proper error handling. Signed-off-by: Nick Kraus --- drivers/serial/uart_emul.c | 18 +++++++++++++++++- include/zephyr/drivers/serial/uart_emul.h | 8 ++++++++ tests/drivers/uart/uart_emul/src/main.c | 23 +++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/serial/uart_emul.c b/drivers/serial/uart_emul.c index 7b3c7ca1c39..f1d90d9efb1 100644 --- a/drivers/serial/uart_emul.c +++ b/drivers/serial/uart_emul.c @@ -29,6 +29,7 @@ struct uart_emul_work { /* Device run time data */ struct uart_emul_data { struct uart_config cfg; + int errors; struct ring_buf *rx_rb; struct k_spinlock rx_lock; @@ -93,7 +94,11 @@ static void uart_emul_poll_out(const struct device *dev, unsigned char out_char) static int uart_emul_err_check(const struct device *dev) { - return 0; + struct uart_emul_data *drv_data = dev->data; + int errors = drv_data->errors; + + drv_data->errors = 0; + return errors; } #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE @@ -350,6 +355,10 @@ uint32_t uart_emul_put_rx_data(const struct device *dev, uint8_t *data, size_t s IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, (irq_en = drv_data->rx_irq_en;)); } + if (count < size) { + uart_emul_set_errors(dev, UART_ERROR_OVERRUN); + } + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, ( if (count > 0 && irq_en && !empty) { (void)k_work_submit(&drv_data->irq_work.work); @@ -397,6 +406,13 @@ uint32_t uart_emul_flush_tx_data(const struct device *dev) return count; } +void uart_emul_set_errors(const struct device *dev, int errors) +{ + struct uart_emul_data *drv_data = dev->data; + + drv_data->errors |= errors; +} + #define UART_EMUL_RX_FIFO_SIZE(inst) (DT_INST_PROP(inst, rx_fifo_size)) #define UART_EMUL_TX_FIFO_SIZE(inst) (DT_INST_PROP(inst, tx_fifo_size)) diff --git a/include/zephyr/drivers/serial/uart_emul.h b/include/zephyr/drivers/serial/uart_emul.h index 68a289841df..08e6be05b1a 100644 --- a/include/zephyr/drivers/serial/uart_emul.h +++ b/include/zephyr/drivers/serial/uart_emul.h @@ -83,6 +83,14 @@ uint32_t uart_emul_flush_rx_data(const struct device *dev); */ uint32_t uart_emul_flush_tx_data(const struct device *dev); +/** + * @brief Sets one or more driver errors + * + * @param dev The emulated UART device instance + * @param errors The @ref uart_rx_stop_reason errors to set + */ +void uart_emul_set_errors(const struct device *dev, int errors); + #ifdef __cplusplus } #endif diff --git a/tests/drivers/uart/uart_emul/src/main.c b/tests/drivers/uart/uart_emul/src/main.c index af04058171f..2de2cdfbd08 100644 --- a/tests/drivers/uart/uart_emul/src/main.c +++ b/tests/drivers/uart/uart_emul/src/main.c @@ -40,6 +40,8 @@ static void uart_emul_before(void *f) uart_emul_flush_rx_data(fixture->dev); uart_emul_flush_tx_data(fixture->dev); + + uart_err_check(fixture->dev); } ZTEST_F(uart_emul, test_polling_out) @@ -78,6 +80,27 @@ ZTEST_F(uart_emul, test_polling_in) zassert_equal(rc, -1, "RX buffer should be empty"); } +ZTEST_F(uart_emul, test_errors) +{ + int errors; + + uart_emul_set_errors(fixture->dev, (UART_ERROR_PARITY | UART_ERROR_FRAMING)); + errors = uart_err_check(fixture->dev); + zassert_equal(errors, (UART_ERROR_PARITY | UART_ERROR_FRAMING), "UART errors do not match"); + + /* uart_err_check should also clear existing errors */ + errors = uart_err_check(fixture->dev); + zassert_equal(errors, 0, "Should be no errors"); + + /* overflowing rx buffer should produce an overrun error */ + uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE); + errors = uart_err_check(fixture->dev); + zassert_equal(errors, 0, "Should be no errors"); + uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE); + errors = uart_err_check(fixture->dev); + zassert_equal(errors, UART_ERROR_OVERRUN, "UART errors do not match"); +} + static void uart_emul_isr(const struct device *dev, void *user_data) { /* always of size SAMPLE_DATA_SIZE */