Skip to content

Commit 3a4f868

Browse files
talih0nashif
authored andcommitted
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 <andriy.gelman@gmail.com>
1 parent e9fd49f commit 3a4f868

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

drivers/serial/uart_xmc4xxx.c

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,28 @@ static inline void async_evt_rx_release_buffer(struct uart_xmc4xxx_data *data, i
428428
}
429429
}
430430

431+
static inline void async_evt_rx_stopped(struct uart_xmc4xxx_data *data,
432+
enum uart_rx_stop_reason reason)
433+
{
434+
struct uart_event event = {.type = UART_RX_STOPPED, .data.rx_stop.reason = reason};
435+
struct uart_event_rx *rx = &event.data.rx_stop.data;
436+
struct dma_status stat;
437+
438+
if (data->dma_rx.buffer_len == 0 || data->async_cb == NULL) {
439+
return;
440+
}
441+
442+
rx->buf = data->dma_rx.buffer;
443+
if (dma_get_status(data->dma_rx.dma_dev, data->dma_rx.dma_channel, &stat) == 0) {
444+
data->dma_rx.counter = data->dma_rx.buffer_len - stat.pending_length;
445+
}
446+
447+
rx->len = data->dma_rx.counter - data->dma_rx.offset;
448+
rx->offset = data->dma_rx.counter;
449+
450+
data->async_cb(data->dev, &event, data->async_user_data);
451+
}
452+
431453
static inline void async_evt_rx_disabled(struct uart_xmc4xxx_data *data)
432454
{
433455
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
707729
unsigned int key;
708730
int ret;
709731

710-
if (status != 0) {
711-
return;
712-
}
713-
714732
__ASSERT_NO_MSG(channel == data->dma_rx.dma_channel);
715733
key = irq_lock();
716734
k_work_cancel_delayable(&data->dma_rx.timeout_work);
717735

736+
if (status < 0) {
737+
async_evt_rx_stopped(data, UART_ERROR_OVERRUN);
738+
uart_xmc4xxx_irq_rx_disable(dev_uart);
739+
dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
740+
async_evt_rx_release_buffer(data, CURRENT_BUFFER);
741+
async_evt_rx_release_buffer(data, NEXT_BUFFER);
742+
async_evt_rx_disabled(data);
743+
goto done;
744+
}
745+
718746
if (data->dma_rx.buffer_len == 0) {
719747
goto done;
720748
}
@@ -725,8 +753,8 @@ static void uart_xmc4xxx_dma_rx_cb(const struct device *dma_dev, void *user_data
725753
async_evt_rx_release_buffer(data, CURRENT_BUFFER);
726754

727755
if (!data->rx_next_buffer) {
728-
dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
729756
uart_xmc4xxx_irq_rx_disable(dev_uart);
757+
dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
730758
async_evt_rx_disabled(data);
731759
goto done;
732760
}
@@ -743,8 +771,8 @@ static void uart_xmc4xxx_dma_rx_cb(const struct device *dma_dev, void *user_data
743771
data->dma_rx.buffer_len);
744772

745773
if (ret < 0) {
746-
dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
747774
uart_xmc4xxx_irq_rx_disable(dev_uart);
775+
dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
748776
async_evt_rx_release_buffer(data, CURRENT_BUFFER);
749777
async_evt_rx_disabled(data);
750778
goto done;

0 commit comments

Comments
 (0)