Want to implement UART free running DMA receiver that can be read asynchronously

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

Want to implement UART free running DMA receiver that can be read asynchronously

1,874 Views
swapnilpendhare
Contributor III

I am working on K22 controller, 

My requirement is, 

1. An application layer reads data at regular interval for with 256 bytes to be read. 

2. UART driver should have a respective read API, where it checks for available number of bytes in read DMA buffer, Read those many bytes and return read function, with number of read bytes from DMA as an return value.

We have been using Kinetis SDK and utilizing APIs provided in fsl_dma_manager.c for dma managment & fsl_uart_edma.c API for uart dma handles. 

We checked that UART_ReceiveEDMA() function checks if DMA buffer has requested number of bytes and if available it reads them and returns. If requested number of bytes are not available it returns with no data, as this is non-blocking API. 

Now, 

We tried to use UART_TransferGetReceiveCountEDMA() to identify number of bytes available in DMA read buffer. and tried to call UART_ReceiveEDMA() with request length equal to available bytes count provided by UART_TransferGetReceiveCountEDMA() API. 

But this functionality does not work correctly.? Please provide your suggestions. 

Code sniped : 

uint32_t readCount = 0;

uint8_t g_newRxBuffer[256];

uint8_t g_txBuffer[256];

while (true)

{
   delayms(100);
   LPUART_TransferGetReceiveCountEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &readCount) ;
   if (readCount > 0  )
   {

       receiveXfer.data = g_newRxBuffer;
       receiveXfer.dataSize = readCount;
       LPUART_ReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &receiveXfer);

       memcpy(g_txBuffer, g_newRxBuffer, readCount);
       /* Start to echo. */
       sendXfer.data = g_txBuffer;
       sendXfer.dataSize = readCount;
       LPUART_SendEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &sendXfer);

    }

}

Labels (1)
0 Kudos
4 Replies

1,226 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Swapnil,

Regarding your issue, how about deleting the line    delayms(100).

If you use uart plus DMA, as you can see that there is a callback function, when the uart has received the pre-defined size of bytes by DMA, the callback function is called, in the callback function, you can handle the data defined in the structure: uart_transfer_t receiveXfer; In other words, you do not need to call the  LPUART_TransferGetReceiveCountEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &readCount) ;

Pls refer to the uart example located at:

C:\DriverE\Freescale\SDK2.0_FRDM_K64F\boards\frdmk64f\driver_examples\uart

The interrupt_transfer example has the similar architecture with interrupt mechanism.

BR

Xiangjun Rong

0 Kudos

1,226 Views
carlnormansuret
Contributor V

Hi,

I am also wanting to implement this for a quick fix for a project on my KL28.

I cannot have an interrupt firing every-time a byte arrives as there are 3 serial ports running 115200 and use literally every other peripheral, so its just not practical.

I have played with LPUART_ReceiveEDMA which works, but, there does not seem to be a "free running" configuration that allows you to leave the RX DMA taking data and you just check for bytes and pull out what you want and it continues on while you're doing that so if a constant stream of bytes is flooding in, i just take say 20, 50 , 100 bytes and more data is coming in over the top so the next call ill take another "chunk". I think 1 in 100 implementations of this have a known RX length, and, the timing of when it will arrive are not known, so I cant start / stop as i could get serial data at in uS.

Is there a simple way to use LPUART_ReceiveEDMA so that I can do this? 

- start RX DMA up

- Data is flooding in

- read in the data "at that moment"

- while reading those bytes, more data is arriving via DMA

- do another read of what is there, more data is still arriving

- continue forever

- at no point can the DMA stop taking data into a buffer, the buffer has to be "reset" back to the start, or some way of managing the DMA RX like uTaskers ring buffer.

uTasker has this freerunning DMA option, works great, thanks Mark :smileyhappy: but this is so close I can taste a project completing if i can just get this DMA driver working in a way that is practical.

0 Kudos

1,226 Views
brunoalbrecht
Contributor III

Any follow up on this matter?

I'm also looking for a free running reception of UART over DMA. The drivers provided by NXP are too limited and doesn't seem to follow the reality of every day projects.

For now, I have a callback function that gives a semaphore every time the DMA receives the whole buffer. In my task, I try to take this semaphore, with a timeout; if I get a timeout, I stop the transmission, get whatever has been received and start a new receive transfer.

When using my device in a question-reply mode, it works just fine, but during stream mode, things get ugly. I'm often getting some RX Overflow between the timeout and the restart of the transfer, which is very bad for my application, since that means I'm loosing data that I wasn't supposed to loose.

Regards,

Bruno

0 Kudos

1,226 Views
carlnormansuret
Contributor V

Hi Bruno,

We ended up using uTasker with the free running DMA. There is no solution we could work out using the fsl drivers as they do not use the functionality correctly for what you or I wanted, they just give basic implementation. uTasker has turned out to be a lot more efficient and usable over a variety of devices, and having the support from Mark when we get stuck is great. I ended up scrapping most of the fsl / freertos stuff and using uTasker's drivers as they're do a lot more and work a lot better.

0 Kudos