Using DMA for transferring data of unknown size ?

cancel
Showing results for 
Search instead for 
Did you mean: 

Using DMA for transferring data of unknown size ?

5,396 Views
Amit_Kumar1
Senior Contributor II

Hi

I am using K60, 100Mhz uc, CW10.6 with PE. I have configured DMA at UART. The data coming in the UART is of variable length and is in hex format. I am able to receive and parse the data of fix length but for variable length i am not able to do anything. I need your suggestion for going further and make this work.

since the data is in hex format, I cant use some function like

while(data[i] != '\n')

{

          new_data[i] = data[i];

          i++;

}

currently the data coming is something like

DATA [ 0 ]  ,  DATA [ 1 ]DATA [ 2 ]DATA [ 3 ]...............DATA [ 3 + n ]
IDLENGTH OF DATA     (n)Varying DATA depending on LENGTH

the length of data can vary from 1 - 255.

What I have done is :

DMA config

dm.jpg

when the packet size is 24(i.e fixed data size) it is working fine.

In final run I have set this transfer count to 255 from 24

In Events.C

void DMAT1_OnComplete(LDD_TUserData *UserDataPtr)

{

      Data_Get();

}


in main.c


void Data_Get()

{

     WAIT1_Waitus(1000);               // I don't know why but without this DMA is flagged multiple times and this function doesn't work

      if((Data[0] == 0x41) && (Data[1] == 0x42)) // ID Check

      {

           uint8_t lt = Data[2];

           for(i=0;i<lt;i++)

           {

                NEW_Data[i] = Data[3+i];

           }

           DMAT1_SetDestinationAddress(dmap, &Data[0]);

      }

      else

      {

           DMAT1_SetDestinationAddress(dmap, &Data[0]);

      }

}


The above function works fine for fixed length packet


for variable length I want to implement the following


void Data_Get()

{

      WAIT1_Waitus(1000);          // Remove this delay and make it work

      if((Data[0] == 0x41) && (Data[1] == 0x42))      // ID Check

      {

           uint8_t lt = Data[2];

           for(i=0;i<lt;i++)

           {

                NEW_Data[i] = Data[3+i];

           }

           DMAT1_SetDestinationAddress(dmap, &Data[0]);

           /* RESET the DMA transfer counter to 0 */

      }

      else

      {

           DMAT1_SetDestinationAddress(dmap, &Data[0]);

            /* RESET the DMA transfer counter to 0 */

      }

}


I tried DMAT1_SetTransferCount(dmap, 0);

but with this the total no. of data to be counted got changed and dma started flagging randomly.

I just want to reset the current value of the counter not the final value to be counted.


I hope I was able to explain my problem.


Kind Regards

Amit Kumar

8 Replies

817 Views
jeremyzhou
NXP TechSupport
NXP TechSupport

Hi Amit,

I'd like to recommend a scenario to receive a variable number of data by DMA.

First, you should configure the transfer byte count=6 and set the DMA_TCDn_CSR[INTHALF],DMA_TCDn_CSR[INTMAJOR] bit to1. Then it will trigger a interrupt after DMA transfer the DATEA[2] to destination.

Second, in the interrupt function, check out the specfic number that the data contain, then adjust the byte counter that will be used for Scatter/Gatter Processing.

Third, if the variable number is less than 6, the interrupt can't happen again, as the major iteration count can't complete. so you can disable the DMA and handle the byte data that had received already.

However if the variable number is more than 6, the DMA will trigger Scatter/Gatter Processing to recieve the last byte data after it  transfered the 6 byte data to destination.

Hope this reply help.
Have a great day,
Ping

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

817 Views
Amit_Kumar1
Senior Contributor II

Hi Jeremyzhou

Thanks for the reply.I Think I tried doing this (if I understood correctly what you tried to suggest). I performed the following steps.

1. Assigned the DMA for 3 Bytes

2. Matched the address and if matched stored the packet size(data 3).

3. Re declared the DMA to transfer the data of packet size.

4. AS the data is received , reset the transfer address and set the transfer to 3 Bytes and repeat the above process.

While matching ID or setting the transfer size the data was coming and so it didn't worked.

Kind Regards

Amit

0 Kudos

817 Views
jeremyzhou
NXP TechSupport
NXP TechSupport

Hi Amit,

Thanks for your reply.

I think you didn't understand my method completely.

I assign the DMA to receive the 6 byte and I also configure the the paratermeters of hte next TCD for Scatter/Gather Processing after the major loop completes its execution.

The DMA will trigger an interrupt when DMA've transfered 3 bytes under set the DMA_TCDn_CSR[INTHALF] bit to one. then anlyze the the 3 received bytes and make some modification of the parameters of the next TCD.

if the variable number is less than 6 which means the major loop completion interrupt can't happen. so you can disable the DMA and handle the byte data that had received already.

However if the variable number is more than 6, the DMA will trigger Scatter/Gatter Processing to recieve the last byte data after it  transfere the 6 byte data to destination.

So you needn't redeclare the DMA to transfer the data and it will be load the new TCD for transfering data automatically by Scatter/Gather Processing.
Have a great day,
Ping

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

817 Views
Amit_Kumar1
Senior Contributor II

Hi Jeremyzhon

Could you please elaborate? I don't have much experience on DMA. Currently I am using DMAT Transfer PE LDD.

Kind Regards

Amit

0 Kudos

817 Views
jeremyzhou
NXP TechSupport
NXP TechSupport

Hi Amit,

Thanks for your reply.

I feel sorry that you hadn't learned my solution.

I'd like to suggest that you'd better not use the PE_LDD component in this project, because it's difficult to use implement the purpose with the PE_LDD component.

And could you please tell me what the particular aspect of the method that you were not very clear?

Have a nice day!

Ping

0 Kudos

817 Views
mjbcswitzerland
Specialist V

Hi Amit

For UART reception in DMA mode where the size of the rx data block is unknown I use a free-running circular buffer. This means that the UART uses DMA (never generates an interrupt) and can do so indefinitely without any SW support.

The SW can then poll the state of the DMA rx pointer (as long as it does so before a complete rx buffer cycle takes place) and see how many bytes of data are in the buffer at any particular point of time, handle a few bytes so that it known the packets size it is waiting for and then complete the packet handling when it knows that the complete data is available.

This technique has been used for multiple UARTs on K60 devices at > 1Mb/s data rates in multiple-UART to Ethernet bridges in networks using near to a thousand such devices and proven over 2 years of operation. Complete code is available in the uTasker project. [UART is opened with the flag UART_RX_DMA but without flags UART_RX_DMA_HALF_BUFFER or UART_RX_DMA_FULL_BUFFER which would be used for fixed length frames to inform of completion. fnMsg(handleUART) returns the number of bytes presently in the circular buffer and fnRead(handleUART, , ) extracts them as if from a FIFO].

Regards

Mark

817 Views
Amit_Kumar1
Senior Contributor II

Hi Mark

Thanks for the help. I have not used circular buffer before but I would like to use it if it makes my task easy. Can I have link of some example code ? It will be easier for me to understand how it works.

Kind Regards

Amit

0 Kudos

817 Views
mjbcswitzerland
Specialist V

Hi

All code is available at http://www.utasker.com/forum/index.php?topic=1721.0

Regards

Mark

0 Kudos