Is there a lpuart edma transfer size limit?

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

Is there a lpuart edma transfer size limit?

Jump to solution
2,571 Views
mitterha
Senior Contributor I

Hello,

I am using a combination of the lpuart_edma_rb_transfer and semc_sdram examples for the RT1020 EVK board to evaluate the uart transfer for big data sizes. From the host PC I send a data file via Tera Term to the target and the target simply returns the data received to the host PC. The ring buffer and the send buffer are located in external SDRAM. If I send less than 32kByte everything works fine. As soon as the buffer size is set to 32kByte or above the transfer won't work (it also does not work for a single byte transfer). Maybe there is something wrong with the EXAMPLE_LPUART_IRQHandler in more detail the calculation of the receivedBytes variable because if I only send one byte the calculated Nr. of receivedBytes is set to 32257 and it should be 1. The init functions and IRQ handler are from the example codes. Below the code parts I have changed:

//#define EXAMPLE_RING_BUFFER_SIZE (32*1024U) //does not work
#define EXAMPLE_RING_BUFFER_SIZE (32*1024U - 1) //works


AT_NONCACHEABLE_SECTION_INIT(uint8_t* g_rxBuffer) = {(uint8_t *)(EXAMPLE_SEMC_START_ADDRESS + EXAMPLE_RING_BUFFER_SIZE + 50)};

AT_NONCACHEABLE_SECTION_INIT(uint8_t* g_ringBuffer) = {(uint8_t *)EXAMPLE_SEMC_START_ADDRESS};


/*!
 * @brief Main function
 */
int main(void)
{
    lpuart_transfer_t sendXfer;

    BOARD_ConfigMPU();
    BOARD_InitPins();
    BOARD_BootClockRUN();

    // deactivate caches
    L1CACHE_DisableICache();
    L1CACHE_DisableDCache();
    
    CLOCK_InitSysPfd(kCLOCK_Pfd2, 29);
    /* Set semc clock to 163.86 MHz */
    CLOCK_SetMux(kCLOCK_SemcMux, 1);
    CLOCK_SetDiv(kCLOCK_SemcDiv, 1);

    if (BOARD_InitSEMC() != kStatus_Success)
    {
        while(1);
    }
    
    /* Initialize the LPUART module. */
    EXAMPLE_InitLPUART();

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

    sendXfer.data     = g_rxBuffer;
    sendXfer.dataSize = EXAMPLE_RING_BUFFER_SIZE;
    
    /* Start ring buffer with EDMA used. */
    EXAMPLE_StartRingBufferEDMA();

    while (1)
    {
        isIdleLineDetected = false;
                
        /* Wait for IDLE line detect. */
        while (!isIdleLineDetected)
        {
        }
        EXAMPLE_ReadRingBuffer(g_ringBuffer, g_rxBuffer, receivedBytes);
        sendXfer.dataSize = receivedBytes;
        LPUART_SendEDMA(EXAMPLE_LPUART, &g_lpuartEdmaHandle, &sendXfer);
    }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Kind regards,

Stefan

0 Kudos
1 Solution
2,313 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Stefan Mitterhauser,

After digging deeper, I find that the max transmission and receive bytes is determined by the below function.

        /* Prepare transfer. */
        EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t),
                             (void *)(uint32_t *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t),
                             xfer->dataSize, kEDMA_MemoryToPeripheral);

According to the above codes,  we can get the maximum bytes = BITER *NBYTES (1 byte), BITER can't exceed the 2^15(as below figure shows.), so the maximum bytes is 32 KBytes.

pastedImage_1.png

Hope this is clear.

TIC

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

View solution in original post

10 Replies
2,313 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Stefan,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
It's a weird phenomenon, however, I think I need the more information.
I was wondering if you can upload the complete demo project, as I'd like to replicate the phenomenon by myself, it can help to figure it out.
In further, I'll appreciate if you can introduce the testing flow and which board you used.
Looking forward to your reply.

TIC

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
2,313 Views
mitterha
Senior Contributor I

Hi Jeremy,

thank you for your help! I have attached the project.

The project is for the IMXRT1020 EVK but I had the same problem with the

IMXRT 1050. I am using IAR Workbench and the "Debug" configuration.

For testing I did the following:

1. Open the project in Debug configuration, download it to the board and

let it run. The default buffer size ist 32*1024U -1 bytes. Don't send

more bytes than that or the project won't work because there is no test

for too many characters.

2. Open TeraTerm and change the Serial port setup to the correct COM

port, 115200 baud, 8 bit data, no parity, 1 stop bit and no flow

control. Also set up the transmit delay to 0 msec/char and 0 msec/line.

3. Send some characters as keyboard input to test that everything is

running correct. The received characters just get returned back to host

and after every received data-block (if you use the keyboard after every

character) the user LED toggles.

4. Create a text document with eg. 31000 characters.

5. Send the created document with TeraTerm File->Send file...

6. Wait until the content of the file gets returned -> everything okay

7. Change the buffer size to 32*1024 bytes (comment out line 39 and

remove // at line 40)

8. Save, make, download and run the project again.

9. Try to send some characters again ---> first character just does not

get returned, at the second character EWARM jumps to fsl_assert because

the receivedBytes variable is 0.

Kind regards,

Stefan

Am 19.01.2020 um 04:25 schrieb jeremyzhou:

>

NXP Community

<https://community.freescale.com/resources/statics/1000/35400-NXP-Community-Email-banner-600x75.jpg>

>

Re: Is there a lpuart edma transfer size limit?

reply from jeremyzhou

<https://community.nxp.com/people/jeremyzhou?et=watches.email.thread>

in /i.MX RT/ - View the full discussion

<https://community.nxp.com/message/1257379?commentID=1257379&et=watches.email.thread#comment-1257379>

>

0 Kudos
2,313 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Hi Stefan,

Thanks for your reply
After having a review of the demo project, I think the code is right and the issue is related to the linker file.
According to the MIMXRT1021xxxxx_flexspi_nor.icf, the NCACHE_VAR block resides in the DTCM, so I'd like to suggest the below steps to assign the NCACHE_VAR block to the external SDRAM.
1. Adding the XIP_BOOT_HEADER_DCD_ENABLE=1 in the Defined symbols box to initialized after POR reset.

pastedImage_3.png
2. Replace the MIMXRT1021xxxxx_flexspi_nor.icf by the MIMXRT1021xxxxx_flexspi_nor_sdram.icf.
3. Put evkmimxrt1020_sdram_init.mac file under the project then set up as the below figure shows.

pastedImage_1.png

Please give a try.

TIC

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
2,313 Views
mitterha
Senior Contributor I

Hello!

I have added the XIP_BOOT_HEADER_DCD_ENABLE=1 symbol, replaced MIMXRT1021xxxxx_flexspi_nor.icf by the MIMXRT1021xxxxx_flexspi_nor_sdram.icf and changed the "use macro file" settings.

Unfortunately the result was a HardFault exception before even trying to send something with the terminal. The problem was the function call BOARD_InitSEMC() --> After adding the XIP_BOOT_HEADER_DCD_ENABLE it is not necessary to call BOARD_INIT_SEMC anymore because the Boot ROM already initializes SEMC right?

After removing the call to BOARD_INIT_SEMC the problem is the same as before changing the icf file. After sending one character the variable "receivedBytes" is set to 32257 which should be 1. After the second character it is 0 and the assert function fails.

Do you have any other ideas what the problem could be?

Kind regards,

Stefan

0 Kudos
2,313 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Stefan,

Thanks for your reply.
1) After adding the XIP_BOOT_HEADER_DCD_ENABLE it is not necessary to call BOARD_INIT_SEMC anymore because the Boot ROM already initializes SEMC right?
-- Yes, it's right.
2) It seems a bit weird. So I was wondering if you can upload the new demo project and introduce the testing flow of replicating the issue.

TIC

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
2,313 Views
mitterha
Senior Contributor I

Hello jeremy,

to be sure that I did not make a mistake in my code while combining different demo projects I just tried to reproduce my problems with newly created SDK demo projects for lpuart edma. The problem is the same for the demo projects in the SDK, you can use them in order to verify it.

With MCUXpresso Tools v7 I have cloned the example projects "lpuart_edma_rb_transfer" and "lpuart_edma_transfer" for IAR workbench from SDK_2.6.1_EVK-MIMXRT1020.

Steps to reproduce:

1. Change to configuration sdram_debug to be sure that the buffer arrays are located in SDRAM.

2. Change the buffer sizes #define ECHO_BUFFER_LENGTH (for lpuart_edma_transfer) or #define EXAMPLE_RING_BUFFER_SIZE (for lpuart_edma_rb_transfer) to the size you want to try. Values up to 32*1024-1 are okay and work, if you use values >=32*1024 the project won't work correct anymore.

3. Open TeraTerm with the correct COM port, 115200 baud, 8 bit data, no parity, 1 stop bit, no flow control. 0 msec/char and 0 msec/line transmit delay

4. Compile, download and run the project on target (RT1020-EVK)

5. Create text files containing as many characters as you specified with  ECHO_BUFFER_LENGTH  or EXAMPLE_RING_BUFFER_SIZE (depending on the project you use).

6. Send the file with tera term File>Send file...

The only thing I changed in the demo projects is the define for the buffer size. As long as the specified buffer size is less than 32kByte everything works fine. Above or equal to 32kByte it does not work anymore.

Kind regards,

Stefan

0 Kudos
2,313 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Stefan Mitterhauser,

Thanks for your reply.
I've replicated the phenomenon on the MIMXRT1050 board, as I don't have the MIMXRT1020 board, now I'm working on it now, so please be patient.

TIC

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
2,314 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Stefan Mitterhauser,

After digging deeper, I find that the max transmission and receive bytes is determined by the below function.

        /* Prepare transfer. */
        EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t),
                             (void *)(uint32_t *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t),
                             xfer->dataSize, kEDMA_MemoryToPeripheral);

According to the above codes,  we can get the maximum bytes = BITER *NBYTES (1 byte), BITER can't exceed the 2^15(as below figure shows.), so the maximum bytes is 32 KBytes.

pastedImage_1.png

Hope this is clear.

TIC

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

2,313 Views
mitterha
Senior Contributor I

Hello jeremy,

thank you very much for looking into it and explaining it to me!

I understand that the minor loop count needs to be 1 because the LPUART receives one byte so to receive more bytes before generating an interrupt we can only use the major loop count. If we want to receive e.g. 64kByte without CPU interruption until all bytes are received we would need to repeat the whole major loop a second time and then generate an interrupt request.

I think for that we could use the scatter/gather feature as described in this document What is and how to configure the eDMA scatter/gather feature. For every 32kByte block we link one more TCD to the chain and the last one fires an interrupt.

Do you have another idea how we could trigger two or more 32kByte DMA transfers back2back without CPU intervention and fire an interrupt after all data has been received?

Kind regards,

Stefan

0 Kudos
2,313 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Stefan Mitterhauser,

Thanks for your reply.
1) Do you have another idea how we could trigger two or more 32kByte DMA transfers back2back without CPU intervention and fire an interrupt after all data has been received?
-- In general, I agree with your idea. The scatter/gather feature is able to make it.

TIC

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------