IMXRT1024 LPUART EDMA RingBuffer Transfer Wrong Received Byte Count

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

IMXRT1024 LPUART EDMA RingBuffer Transfer Wrong Received Byte Count

1,970 Views
Lukas_Frank
Senior Contributor I

Hi,

 

I am getting wrong received byte in sequential send and receive operation on my board. I am using LPUART2 and LPUART3, and sending datas in a manner stated like below:

 

uint32_t getReceivedByte[10] = {0};
uint32_t transferCycleIter;
for(transferCycleIter=0;transferCycleIter<10;transferCycleIter++)
{
send_DATA();//from_UART2_to_UART3

receive_DATA();//for_UART3

getReceivedByte[transferCycleIter] = receivedBytes_UART3;

}

 

I am sending bytes count like below order:I am reading calculated received bytes count like below order:
77
2323
55
124294967292
214294967264
114294967285
264294967264
154294967284
244294967273
94294967269

What is going on?

Could you help me about healthiest way to calculate receivedByte ?

Thank you.

0 Kudos
12 Replies

1,966 Views
danielchen
NXP TechSupport
NXP TechSupport

Hi Lukas:

 

Do you use the latest SDK 2.10?  

 

Regards

Daniel

1,958 Views
Lukas_Frank
Senior Contributor I

Hi Dear @danielchen ,

I am using 2.9.0 one. Is it depends on the version. 

Thanks and Regards.

0 Kudos

1,950 Views
Lukas_Frank
Senior Contributor I

By the way, I have a theory about the issue. I think it is related to baud rate. When I set my baud rate above the 2810000. It is returning wrong receivedBytes. Is there any direct update in new version for this issue?

Thank you. 

0 Kudos

1,948 Views
danielchen
NXP TechSupport
NXP TechSupport

not sure.  I will try to reproduce your issue on my side with SDK210

 

Regards

Daniel

0 Kudos

1,935 Views
Lukas_Frank
Senior Contributor I

Dear @danielchen  thank you for your help. I will be waiting for you. 

Thanks and Regards.

Tags (1)
0 Kudos

1,933 Views
danielchen
NXP TechSupport
NXP TechSupport

Do you have a simple project to reproduce this issue?

0 Kudos

1,906 Views
danielchen
NXP TechSupport
NXP TechSupport

Hi  @Lukas_Frank :

 

I tested the lpuart_edma_rb_tranfer  demo and got the same result.  This seems an issue.  What you can do in your side.

1. measure the real baud rate when you config it to 1280000.

2. try to lower the baud rate , to see whether if can work.

 

I will update you when I have new findings.

 

Regards

Daniel

1,756 Views
Lukas_Frank
Senior Contributor I

Hi Dear @danielchen,

 

Did you find any new update about the issue? Could you please enlighten me? Will we be able to use 4125000 Baudrate?

 

Thank you.

0 Kudos

1,737 Views
danielchen
NXP TechSupport
NXP TechSupport

The baud rate rates up to 20Mbps. However, the signal integrity on the serial line, correct data receive, is not guaranteed and should be experimentally.    But your question is the received Bytes not right when you configure the baudrate to 4000000?  can the data be sent successfully? I can not reproduce this issue with your code.

0 Kudos

1,579 Views
Lukas_Frank
Senior Contributor I

After a long time,

 

Hi Dear @danielchen ,

 

I am still trying to solve issue. I think problem causes from uncontrollable increasion of "ringBufferFlag" counter in CallBack. I am using two 1024-EVK now as Sender and Receiver. It is occuring even at 115200 baudrate. Is not there a more efficient way to calculate incoming bytes in eDMA Ring Buffer usage? I will run some parts of my code when the exact match is occured for specific byte count received.

 

I will share my codes in short time. 

 

Thanks and Regards.

0 Kudos

1,574 Views
danielchen
NXP TechSupport
NXP TechSupport

Hi @Lukas_Frank 

 

I would suggest you open a new thread for this. thank you.

 

Regards

Daniel

 

1,892 Views
Lukas_Frank
Senior Contributor I

Hi Dear @danielchen ,

 

Sorry for my delayed reply. Here are my codes :

 

/*
 * Copyright 2019 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_lpuart_edma.h"
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
#include "fsl_dmamux.h"
#endif
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define EXAMPLE_LPUART                 LPUART1
#define EXAMPLE_LPUART_CLK_FREQ        BOARD_DebugConsoleSrcFreq()
#define LPUART_TX_DMA_CHANNEL          0U
#define LPUART_RX_DMA_CHANNEL          1U
#define LPUART_TX_DMA_REQUEST          kDmaRequestMuxLPUART1Tx
#define LPUART_RX_DMA_REQUEST          kDmaRequestMuxLPUART1Rx
#define EXAMPLE_LPUART_DMAMUX_BASEADDR DMAMUX
#define EXAMPLE_LPUART_DMA_BASEADDR    DMA0
#define EXAMPLE_LPUART_IRQHandler      LPUART1_IRQHandler
#define EXAMPLE_LPUART_IRQn            LPUART1_IRQn
/* Ring buffer size definition, please make sure to set this value large enough.
 * Otherwise, once overflow occurred, data in ring buffer will be overwritten.
 */
#define EXAMPLE_RING_BUFFER_SIZE (32U)

/*******************************************************************************
 * Prototypes
 ******************************************************************************/
/* Initialzie the USART module. */
static void EXAMPLE_InitEDMA(void);

/* Initalize the DMA configuration for USART  TX and RX used.  */
static void EXAMPLE_InitLPUART(void);

/* Start ring buffer. */
static void EXAMPLE_StartRingBufferEDMA(void);

/* Reading data from the ring buffer. */
static void EXAMPLE_ReadRingBuffer(uint8_t *ringBuffer, uint8_t *receiveBuffer, uint32_t length);

/* LPUART RX EDMA call back. */
void EXAMPLE_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);

/* LPUART user callback */
void EXAMPLE_TxEDMACallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData);

/*******************************************************************************
 * Variables
 ******************************************************************************/
lpuart_edma_handle_t g_lpuartEdmaHandle;
edma_handle_t g_lpuartTxEdmaHandle;
edma_handle_t g_lpuartRxEdmaHandle;
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_tipString[]) =
    "LPUART EDMA ring buffer example.\r\nBoard will send back received characters:\r\n";
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_rxBuffer[EXAMPLE_RING_BUFFER_SIZE]) = {0};
volatile bool txOnGoing                                                    = false;
volatile bool isIdleLineDetected                                           = false;
volatile uint32_t ringBufferFlag                                           = 0U;
volatile uint32_t receivedBytes                                            = 0U;
volatile uint32_t ringBufferIndex                                          = 0U;

/* allocate ring buffer section. */
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_ringBuffer[EXAMPLE_RING_BUFFER_SIZE]) = {0};
/* Allocate TCD memory poll with ring buffer used. */
AT_NONCACHEABLE_SECTION_ALIGN(static edma_tcd_t tcdMemoryPoolPtr[1], sizeof(edma_tcd_t));

/*******************************************************************************
 * Code
 ******************************************************************************/

/* Initialzie the USART module. */
static void EXAMPLE_InitLPUART(void)
{
    lpuart_config_t lpuartConfig;

    LPUART_GetDefaultConfig(&lpuartConfig);
    lpuartConfig.rxIdleType   = kLPUART_IdleTypeStopBit;
    lpuartConfig.rxIdleConfig = kLPUART_IdleCharacter2;
    lpuartConfig.baudRate_Bps = 4000000;//BOARD_DEBUG_UART_BAUDRATE;
    lpuartConfig.enableTx     = true;
    lpuartConfig.enableRx     = true;

    LPUART_Init(EXAMPLE_LPUART, &lpuartConfig, EXAMPLE_LPUART_CLK_FREQ);
}

/* Initalize the DMA configuration for USART  TX and RX used. */
static void EXAMPLE_InitEDMA(void)
{
    edma_config_t config;

#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
    /* Init DMAMUX */
    DMAMUX_Init(EXAMPLE_LPUART_DMAMUX_BASEADDR);
    /* Set channel for LPUART */
    DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL, LPUART_TX_DMA_REQUEST);
    DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL, LPUART_RX_DMA_REQUEST);
    DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL);
    DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL);
#endif

    /* Init the EDMA module */
    EDMA_GetDefaultConfig(&config);
    EDMA_Init(EXAMPLE_LPUART_DMA_BASEADDR, &config);
    EDMA_CreateHandle(&g_lpuartTxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_TX_DMA_CHANNEL);
    EDMA_CreateHandle(&g_lpuartRxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL);

    /* Create LPUART DMA handle for sending data. */
    LPUART_TransferCreateHandleEDMA(EXAMPLE_LPUART, &g_lpuartEdmaHandle, EXAMPLE_TxEDMACallback, NULL,
                                    &g_lpuartTxEdmaHandle, &g_lpuartRxEdmaHandle);
}

/* Start ring buffer. */
static void EXAMPLE_StartRingBufferEDMA(void)
{
    edma_transfer_config_t xferConfig;

    /* Install TCD memory for using only one TCD queue. */
    EDMA_InstallTCDMemory(&g_lpuartRxEdmaHandle, (edma_tcd_t *)&tcdMemoryPoolPtr[0], 1U);

    /* Prepare transfer to receive data to ring buffer. */
    EDMA_PrepareTransfer(&xferConfig, (void *)(uint32_t *)LPUART_GetDataRegisterAddress(EXAMPLE_LPUART),
                         sizeof(uint8_t), g_ringBuffer, sizeof(uint8_t), sizeof(uint8_t), EXAMPLE_RING_BUFFER_SIZE,
                         kEDMA_PeripheralToMemory);

    /* Submit transfer. */
    g_lpuartRxEdmaHandle.tcdUsed = 1U;
    g_lpuartRxEdmaHandle.tail    = 0U;
    EDMA_TcdReset(&g_lpuartRxEdmaHandle.tcdPool[0U]);
    EDMA_TcdSetTransferConfig(&g_lpuartRxEdmaHandle.tcdPool[0U], &xferConfig, tcdMemoryPoolPtr);

    /* Enable major interrupt for counting received bytes. */
    g_lpuartRxEdmaHandle.tcdPool[0U].CSR |= DMA_CSR_INTMAJOR_MASK;

    /* There is no live chain, TCD block need to be installed in TCD registers. */
    EDMA_InstallTCD(g_lpuartRxEdmaHandle.base, g_lpuartRxEdmaHandle.channel, &g_lpuartRxEdmaHandle.tcdPool[0U]);

    /* Setup call back function. */
    EDMA_SetCallback(&g_lpuartRxEdmaHandle, EXAMPLE_RxEDMACallback, NULL);

    /* Start EDMA transfer. */
    EDMA_StartTransfer(&g_lpuartRxEdmaHandle);

    /* Enable LPUART RX EDMA. */
    LPUART_EnableRxDMA(EXAMPLE_LPUART, true);

    /* Enable RX interrupt for detecting the IDLE line interrupt. */
    LPUART_EnableInterrupts(EXAMPLE_LPUART, kLPUART_IdleLineInterruptEnable);
    EnableIRQ(EXAMPLE_LPUART_IRQn);
}

/* Reading out the data from ring buffer. */
static void EXAMPLE_ReadRingBuffer(uint8_t *ringBuffer, uint8_t *receiveBuffer, uint32_t length)
{
    assert(ringBuffer);
    assert(receiveBuffer);
    assert(length);

    uint32_t index = length;

    /* If length if larger than ring buffer size, it means overflow occurred, need to reset the ringBufferIndex. */
    if (length > EXAMPLE_RING_BUFFER_SIZE)
    {
        ringBufferIndex = ((ringBufferIndex + length) % EXAMPLE_RING_BUFFER_SIZE);
        index           = EXAMPLE_RING_BUFFER_SIZE;
    }

    while (index)
    {
        *(receiveBuffer++) = ringBuffer[ringBufferIndex++];
        if (ringBufferIndex == EXAMPLE_RING_BUFFER_SIZE)
        {
            ringBufferIndex = 0U;
            ringBufferFlag--;
        }
        index--;
    }
}

void EXAMPLE_LPUART_IRQHandler(void)
{
    uint32_t status            = LPUART_GetStatusFlags(EXAMPLE_LPUART);
    uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(EXAMPLE_LPUART);

    /* If new data arrived. */
    if ((0U != ((uint32_t)kLPUART_IdleLineFlag & status)) &&
        (0U != ((uint32_t)kLPUART_IdleLineInterruptEnable & enabledInterrupts)))
    {
        (void)LPUART_ClearStatusFlags(EXAMPLE_LPUART, kLPUART_IdleLineFlag);
        isIdleLineDetected = true;
        receivedBytes      = EXAMPLE_RING_BUFFER_SIZE -
                        EDMA_GetRemainingMajorLoopCount(EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL);
        receivedBytes += (EXAMPLE_RING_BUFFER_SIZE * ringBufferFlag) - ringBufferIndex;

        if (receivedBytes > 32U)
        {
            __NOP();
        }
    }
    LPUART_TransferEdmaHandleIRQ(EXAMPLE_LPUART, &g_lpuartEdmaHandle);
    SDK_ISR_EXIT_BARRIER;
}

/* LPUART RX EDMA call back. */
void EXAMPLE_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
    if (true == transferDone)
    {
        ringBufferFlag++;
    }
}

/* LPUART EDMA TX user callback */
void EXAMPLE_TxEDMACallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData)
{
    userData = userData;

    if (kStatus_LPUART_TxIdle == status)
    {
        txOnGoing = false;
    }
}

/*!
 * @brief Main function
 */

uint16_t itr;
uint16_t count = 0;
uint8_t temp1[11];
uint8_t temp2[20];
uint8_t temp3[28];
uint8_t temp4[10];
uint8_t temp5[21];
uint8_t temp6[11];
uint8_t temp7[19];
uint8_t temp8[30];

void initArrays()
{
    for(itr=0 itr<sizeof(temp1); itr++)
    {
		temp1[itr]= count;
		count++;
    }
	for(itr=0 itr<sizeof(temp2); itr++)
    {
		temp2[itr]= count;
		count++;
    }
    for(itr=0 itr<sizeof(temp3); itr++)
    {
		temp3[itr]= count;
		count++;
    }
    for(itr=0 itr<sizeof(temp4); itr++)
    {
		temp4[itr]= count;
		count++;
    }
    for(itr=0 itr<sizeof(temp5); itr++)
    {
		temp5[itr]= count;
		count++;
    }
    for(itr=0 itr<sizeof(temp6); itr++)
    {
		temp6[itr]= count;
		count++;
    }
    for(itr=0 itr<sizeof(temp7); itr++)
    {
		temp7[itr]= count;
		count++;
    }
    for(itr=0 itr<sizeof(temp8); itr++)
    {
		temp8[itr]= count;
		count++;
    }
}

int main(void)
{
    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_InitBootClocks();

    /* Initialize the LPUART module. */
    EXAMPLE_InitLPUART();

    /* Intialzie the EDMA configuration. */
    EXAMPLE_InitEDMA();

    /* Start ring buffer with EDMA used. */
    EXAMPLE_StartRingBufferEDMA();
	
    uint16_t innerIterForAssignment = 0;
    uint32_t innerByteCountHolder[20] = {0};

    while (1)
    {
      lpuart_transfer_t sendXfer;
	  if(innerIterForAssignment<8) //8 is temp array count just for simulating of the consecutive transfer operation
	  {
		switch(innerIterForAssignment)
		{
			case 0:
			{
				sendXfer.data = temp1;
				sendXfer.dataSize = sizeof(temp1)
			}break;
			case 1:
			{
				sendXfer.data = temp2;
				sendXfer.dataSize = sizeof(temp2)
			}break;
			case 2:
			{
				sendXfer.data = temp3;
				sendXfer.dataSize = sizeof(temp3)
			}break;
			case 3:
			{
				sendXfer.data = temp4;
				sendXfer.dataSize = sizeof(temp4)
			}break;
			case 4:
			{
				sendXfer.data = temp5;
				sendXfer.dataSize = sizeof(temp5)
			}break;
			case 5:
			{
				sendXfer.data = temp6;
				sendXfer.dataSize = sizeof(temp6)
			}break;
			case 6:
			{
				sendXfer.data = temp7;
				sendXfer.dataSize = sizeof(temp7)
			}break;
			case 7:
			{
				sendXfer.data = temp8;
				sendXfer.dataSize = sizeof(temp8)
			}break;
			default:
			{

			}break;
		} 

		LPUART_SendEDMA(EXAMPLE_LPUART, &g_lpuartEdmaHandle, &sendXfer);
		
		isIdleLineDetected = false;
        /* Wait for IDLE line detect. */
        while (!isIdleLineDetected)
        {
        }

        EXAMPLE_ReadRingBuffer(g_ringBuffer, g_rxBuffer, receivedBytes);
		innerIterForAssignment++;
		innerByteCountHolder[innerIterForAssignment] = receivedBytes;
		
	  }
	  else
	  {
		  innerIterForAssignment=11;//just for the fill inner of else
	  }
    }
	
}

 

I can get baudrate between 2500000 and 2800000 with this code as I remember. But I need really deep help for setting my baudrate 4000000. I read in Reference Manual UART has "Programmable baud rates up to 20 Mbps.".

Lukas_Frank_0-1637139914899.png

 

Could you help me please?

 

Thanks and Regards.

0 Kudos