Problem Configuring DMA for UART transfer.

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

 Hi,

   

 

   

I'm working in a project where I need to adquire 53 bytes of samples which come from a digital IC periodically and then I need to save them in packets of 1431 bytes which is 27 packets of 53 bytes. Then, I need to send the 1431 bytes through the UART and I can't be sending one by one because I need to keep getting the next 53 bytes before I can send the 1431 so I want to use the DMA to transfer the 1431bytes through the UART without CPU intervention.

   

I haven't been able to do this becasuse the DMA is not working at all and I don't know why.

   

I've added the DMA component to my schematic. I use a array to store the 1431 bytes and once the array is full I call CyDmaChSetRequest(UART_DMA_CH, CPU_REQ); to start the DMA transfer.

   

I've tried to download the example here: http://www.psocdeveloper.com/forums/viewtopic.php?t=9435&p=40637 but de file is damaged onece downloaded.

   

The code I'm using to configurate the DMA is the following: 

   

 

   

#define UART_DMA_BYTES_PER_BURST                     4 // Size of the UART Buffer

   

#define UART_DMA_REQUEST_PER_BURST                   0   //Automatically send rest of bursts

   

#define UART_DMA_TRANSFER_SIZE                       1431  // Size of Samples frame

   

#define DMA_BURST_COUNT                               UART_DMA_TRANSFER_SIZE/UART_DMA_BYTES_PER_BURST // 1430/4 = 14

   

 

   

uint8 UART_DMA_CH;

   

uint8 UART_DMA_TD[1];

   

void UART_HANDLER_InitDMA(uint8 DMA_TX_Buffer[])

   

{

   

    UART_DMA_CH = DMA_DmaInitialize( (uint8)DMA_BURST_COUNT, UART_DMA_REQUEST_PER_BURST,   HI16(&DMA_TX_Buffer), HI16 (CYDEV_PERIPH_BASE) );

   

   UART_DMA_TD[0] = CyDmaTdAllocate();

   

   

   

   CyDmaTdSetConfiguration( UART_DMA_TD[0], UART_DMA_TRANSFER_SIZE, UART_DMA_TD[0], TD_INC_SRC_ADR);  //

   

   

   

   /* Configure the lower 16 bit source and destination addresses

   

    * Souce Address = Lower 16 bits of txBuffer array

   

    * Destiantion address = Lower 16 bits of uart tx register 

   

    */

   

   

   

   CyDmaTdSetAddress( UART_DMA_TD[0], LO16((uint32)&DMA_TX_Buffer), LO16((uint32)UART_TXDATA_PTR));

   

   

   

   /* Map TD to the DMA Channel */

   

   CyDmaChSetInitialTd( UART_DMA_CH, UART_DMA_TD[0]);

   

   

   

   /* Enable the DMA channel */

   

   CyDmaChEnable(UART_DMA_CH, 1 ) ;

   

 

   

}

0 Likes
4 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You receive 1 byte at a time from your external IC and store the data (not using DMA) in a buffer. Hopefully the frequency of the incoming bytes is lower than the UART speed.

   

Two errors I can see in your coding, but it is always advisable to post the complete project here, so that we all can have a look at your settings and not only a code snippet.

   

The FIFo buffer might be 4 bytes deep, but you should transfer only 1 byte at a time.

   

Probably your buffer is defined as

   

uint8 DMA_TX_Buffer[1431];

   

then DMA_TX_Buffer is already a pointer to DMA_TX_Buffer[0]

   

There is an error at

   

CyDmaTdSetAddress( UART_DMA_TD[0], LO16((uint32)&DMA_TX_Buffer), LO16((uint32)UART_TXDATA_PTR));

   

CyDmaTdSetAddress( UART_DMA_TD[0], LO16((uint32) DMA_TX_Buffer), LO16((uint32)UART_TXDATA_PTR)); // &

   

and the same here

   

 UART_DMA_CH = DMA_DmaInitialize( (uint8)DMA_BURST_COUNT, UART_DMA_REQUEST_PER_BURST,   HI16(&DMA_TX_Buffer), HI16 (CYDEV_PERIPH_BASE) ); // remove & from DMA_TX_Buffer

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 Hi Bob,

   

Thank you for your response. 

   

If I could post the project I would but I am not allowed. 

   

I've tried what you propose but it doesn't work. I assume DMA_BURST_COUNT and UART_DMA_TRANSFER_SIZE should both be 1431 in this case, right?

   

By the way, is there any way to "comment" a component in the schematic? 

   

For instance, I want to get rid of a PWM component to test other things without it but I want to have it back later with its configuration as it was and everything. Is there a way to do that?

   

 

   

Thank you

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Best will be to create a MyCase and submit the project to Cypress. They will keep it confidential. To do so; On top of this pager "Support & Community ->Technical Support->Create a MyCase"

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Twistx, this is in response to your question about removing a component without actually deleting it so that it keeps its configuration.  I think you can do this by right clicking component->configuration->built in tab and setting CY_REMOVE to true.

   

 

   

I also just wanted to clarify for you why Bob took away the '&' symbol.  Rather than ramble on I figured a link to a site with a great description would be better, which can be found here.  Hope you find it helpful, it is "extremely" important that you understand pointers when dealing with customized DMA, otherwise you are in for quite a headache.  Cheers

0 Likes