@@ -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
590591static 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
853866static 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