From 3a4f868084e7248180b77c0ea0f71e15c9689de0 Mon Sep 17 00:00:00 2001 From: Andriy Gelman Date: Thu, 29 Aug 2024 22:33:50 -0400 Subject: [PATCH] drivers: uart_xmc4xxx: Forward DMA overrun errors to user Currently DMA overrun errors are ignored. Forward the error to the user using the UART_RX_STOPPED with UART_ERROR_OVERRUN reason. Signed-off-by: Andriy Gelman --- drivers/serial/uart_xmc4xxx.c | 40 +++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/serial/uart_xmc4xxx.c b/drivers/serial/uart_xmc4xxx.c index 7bde7fafde1..51ec19cf427 100644 --- a/drivers/serial/uart_xmc4xxx.c +++ b/drivers/serial/uart_xmc4xxx.c @@ -428,6 +428,28 @@ static inline void async_evt_rx_release_buffer(struct uart_xmc4xxx_data *data, i } } +static inline void async_evt_rx_stopped(struct uart_xmc4xxx_data *data, + enum uart_rx_stop_reason reason) +{ + struct uart_event event = {.type = UART_RX_STOPPED, .data.rx_stop.reason = reason}; + struct uart_event_rx *rx = &event.data.rx_stop.data; + struct dma_status stat; + + if (data->dma_rx.buffer_len == 0 || data->async_cb == NULL) { + return; + } + + rx->buf = data->dma_rx.buffer; + if (dma_get_status(data->dma_rx.dma_dev, data->dma_rx.dma_channel, &stat) == 0) { + data->dma_rx.counter = data->dma_rx.buffer_len - stat.pending_length; + } + + rx->len = data->dma_rx.counter - data->dma_rx.offset; + rx->offset = data->dma_rx.counter; + + data->async_cb(data->dev, &event, data->async_user_data); +} + static inline void async_evt_rx_disabled(struct uart_xmc4xxx_data *data) { struct uart_event event = {.type = UART_RX_DISABLED}; @@ -707,14 +729,20 @@ static void uart_xmc4xxx_dma_rx_cb(const struct device *dma_dev, void *user_data unsigned int key; int ret; - if (status != 0) { - return; - } - __ASSERT_NO_MSG(channel == data->dma_rx.dma_channel); key = irq_lock(); k_work_cancel_delayable(&data->dma_rx.timeout_work); + if (status < 0) { + async_evt_rx_stopped(data, UART_ERROR_OVERRUN); + uart_xmc4xxx_irq_rx_disable(dev_uart); + dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel); + async_evt_rx_release_buffer(data, CURRENT_BUFFER); + async_evt_rx_release_buffer(data, NEXT_BUFFER); + async_evt_rx_disabled(data); + goto done; + } + if (data->dma_rx.buffer_len == 0) { goto done; } @@ -725,8 +753,8 @@ static void uart_xmc4xxx_dma_rx_cb(const struct device *dma_dev, void *user_data async_evt_rx_release_buffer(data, CURRENT_BUFFER); if (!data->rx_next_buffer) { - dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel); uart_xmc4xxx_irq_rx_disable(dev_uart); + dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel); async_evt_rx_disabled(data); goto done; } @@ -743,8 +771,8 @@ static void uart_xmc4xxx_dma_rx_cb(const struct device *dma_dev, void *user_data data->dma_rx.buffer_len); if (ret < 0) { - dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel); uart_xmc4xxx_irq_rx_disable(dev_uart); + dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel); async_evt_rx_release_buffer(data, CURRENT_BUFFER); async_evt_rx_disabled(data); goto done;