Skip to content

Commit fb1ffff

Browse files
hakehuangnashif
authored andcommitted
driver: uart: uart_mcux_lpuart fix issues in async api
1. optimized the logic for buffer usage in async api 2. skip timeout flush when the remaining counts is 0, as this will trigger dma_callback to process. 3. remove scatter mode, as we are not using this mode 4. trigger after dma_reload. Signed-off-by: Hake Huang <[email protected]>
1 parent bfe3c43 commit fb1ffff

File tree

1 file changed

+40
-22
lines changed

1 file changed

+40
-22
lines changed

drivers/serial/uart_mcux_lpuart.c

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -515,10 +515,11 @@ static void mcux_lpuart_async_rx_flush(const struct device *dev)
515515
const size_t rx_rcv_len = data->async.rx_dma_params.buf_len -
516516
status.pending_length;
517517

518-
if (rx_rcv_len > data->async.rx_dma_params.counter) {
518+
if (rx_rcv_len > data->async.rx_dma_params.counter && status.pending_length) {
519519
data->async.rx_dma_params.counter = rx_rcv_len;
520520
async_evt_rx_rdy(dev);
521521
}
522+
LPUART_ClearStatusFlags(config->base, kLPUART_RxOverrunFlag);
522523
} else {
523524
LOG_ERR("Error getting DMA status");
524525
}
@@ -584,7 +585,7 @@ static void prepare_rx_dma_block_config(const struct device *dev)
584585
head_block_config->dest_address = (uint32_t)rx_dma_params->buf;
585586
head_block_config->source_address = LPUART_GetDataRegisterAddress(lpuart);
586587
head_block_config->block_size = rx_dma_params->buf_len;
587-
head_block_config->dest_scatter_en = true;
588+
head_block_config->dest_scatter_en = false;
588589
}
589590

590591
static int configure_and_start_rx_dma(
@@ -615,20 +616,38 @@ static int uart_mcux_lpuart_dma_replace_rx_buffer(const struct device *dev)
615616
struct mcux_lpuart_data *data = (struct mcux_lpuart_data *)dev->data;
616617
const struct mcux_lpuart_config *config = dev->config;
617618
LPUART_Type *lpuart = config->base;
619+
struct mcux_lpuart_rx_dma_params *rx_dma_params = &data->async.rx_dma_params;
618620

619621
LOG_DBG("Replacing RX buffer, new length: %d", data->async.next_rx_buffer_len);
622+
620623
/* There must be a buffer to replace this one with */
621624
assert(data->async.next_rx_buffer != NULL);
622625
assert(data->async.next_rx_buffer_len != 0U);
623-
const int success = dma_reload(config->rx_dma_config.dma_dev,
624-
config->rx_dma_config.dma_channel,
625-
LPUART_GetDataRegisterAddress(lpuart),
626-
(uint32_t)data->async.next_rx_buffer,
627-
data->async.next_rx_buffer_len);
626+
rx_dma_params->buf = data->async.next_rx_buffer;
627+
rx_dma_params->buf_len = data->async.next_rx_buffer_len;
628+
rx_dma_params->offset = 0;
629+
rx_dma_params->counter = 0;
630+
data->async.next_rx_buffer = NULL;
631+
data->async.next_rx_buffer_len = 0U;
632+
633+
const int success =
634+
dma_reload(config->rx_dma_config.dma_dev, config->rx_dma_config.dma_channel,
635+
LPUART_GetDataRegisterAddress(lpuart), (uint32_t)rx_dma_params->buf,
636+
rx_dma_params->buf_len);
628637

629638
if (success != 0) {
630639
LOG_ERR("Error %d reloading DMA with next RX buffer", success);
631640
}
641+
/* Request next buffer */
642+
async_evt_rx_buf_request(dev);
643+
644+
int ret = dma_start(config->rx_dma_config.dma_dev, config->rx_dma_config.dma_channel);
645+
646+
if (ret < 0) {
647+
LOG_ERR("Failed to start DMA(Rx) Ch %d(%d)", config->rx_dma_config.dma_channel,
648+
ret);
649+
}
650+
632651
return success;
633652
}
634653

@@ -673,16 +692,9 @@ static void dma_callback(const struct device *dma_dev, void *callback_arg, uint3
673692
async_evt_rx_rdy(dev);
674693
async_evt_rx_buf_release(dev);
675694

676-
rx_dma_params->buf = data->async.next_rx_buffer;
677-
rx_dma_params->buf_len = data->async.next_rx_buffer_len;
678-
data->async.next_rx_buffer = NULL;
679-
data->async.next_rx_buffer_len = 0U;
680-
681-
/* A new buffer was available (and already loaded into the DMA engine) */
682-
if (rx_dma_params->buf != NULL &&
683-
rx_dma_params->buf_len > 0) {
695+
if (data->async.next_rx_buffer != NULL && data->async.next_rx_buffer_len > 0) {
684696
/* Request the next buffer */
685-
async_evt_rx_buf_request(dev);
697+
uart_mcux_lpuart_dma_replace_rx_buffer(dev);
686698
} else {
687699
/* Buffer full without valid next buffer, disable RX DMA */
688700
LOG_INF("Disabled RX DMA, no valid next buffer ");
@@ -832,6 +844,8 @@ static int mcux_lpuart_rx_enable(const struct device *dev, uint8_t *buf, const s
832844
rx_dma_params->timeout_us = timeout_us;
833845
rx_dma_params->buf = buf;
834846
rx_dma_params->buf_len = len;
847+
data->async.next_rx_buffer = NULL;
848+
data->async.next_rx_buffer_len = 0U;
835849

836850
LPUART_EnableInterrupts(config->base, kLPUART_IdleLineInterruptEnable);
837851
prepare_rx_dma_block_config(dev);
@@ -841,10 +855,9 @@ static int mcux_lpuart_rx_enable(const struct device *dev, uint8_t *buf, const s
841855
async_evt_rx_buf_request(dev);
842856

843857
/* Clear these status flags as they can prevent the UART device from receiving data */
844-
LPUART_ClearStatusFlags(config->base, kLPUART_RxOverrunFlag |
845-
kLPUART_ParityErrorFlag |
846-
kLPUART_FramingErrorFlag |
847-
kLPUART_NoiseErrorFlag);
858+
LPUART_ClearStatusFlags(config->base, kLPUART_RxOverrunFlag | kLPUART_ParityErrorFlag |
859+
kLPUART_FramingErrorFlag |
860+
kLPUART_NoiseErrorFlag);
848861
LPUART_EnableRx(lpuart, true);
849862
irq_unlock(key);
850863
return ret;
@@ -853,13 +866,14 @@ static int mcux_lpuart_rx_enable(const struct device *dev, uint8_t *buf, const s
853866
static int mcux_lpuart_rx_buf_rsp(const struct device *dev, uint8_t *buf, size_t len)
854867
{
855868
struct mcux_lpuart_data *data = dev->data;
869+
unsigned int key;
856870

871+
key = irq_lock();
857872
assert(data->async.next_rx_buffer == NULL);
858873
assert(data->async.next_rx_buffer_len == 0);
859874
data->async.next_rx_buffer = buf;
860875
data->async.next_rx_buffer_len = len;
861-
uart_mcux_lpuart_dma_replace_rx_buffer(dev);
862-
876+
irq_unlock(key);
863877
return 0;
864878
}
865879

@@ -921,6 +935,10 @@ static inline void mcux_lpuart_async_isr(struct mcux_lpuart_data *data,
921935
data->async.rx_dma_params.timeout_us);
922936
LPUART_ClearStatusFlags(config->base, kLPUART_IdleLineFlag);
923937
}
938+
939+
if (status & kLPUART_RxOverrunFlag) {
940+
LPUART_ClearStatusFlags(config->base, kLPUART_RxOverrunFlag);
941+
}
924942
}
925943
#endif
926944

0 commit comments

Comments
 (0)