DMA UART K60 Error

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

DMA UART K60 Error

Jump to solution
3,292 Views
mdrasool_yadwad
Contributor II

Hello

I am attaching my code please help me out in this. I want to transfer a char array on to putty using UART by raising DMA request. It is printing only the first element. please help me in this

Labels (1)
0 Kudos
Reply
1 Solution
3,218 Views
mjbcswitzerland
Specialist V

Hi

Multiple triggers when there is one place available in a peripheral is incorrect and will cause failure. A single transfer on each trigger is the correct way to do it.

DMA is very useful since there is no CPU overhead involved but doing it the wrong way (multiple transfers for a single trigger is incorrect and so won't work) won't allow it to be solved.

There are possibly working examples in the SDKs or there is a proven one at the GIT hub link I gave. It may be easier to use something that functions as reference to get you over the present difficulties or re-read the eDMA users manual carefully to gain more understanding.

Regards

Mark

 

View solution in original post

8 Replies
3,286 Views
mjbcswitzerland
Specialist V

Hi

If you can send one byte from a buffer with DMA_TCD_CITER_ELINK set to 1, you should be able to send multiple bytes by just setting DMA_TCD_CITER_ELINK to the number of bytes too be sent. There should be nothing else to do.

However, make sure that you DO NOT TOUCH the DMA in operation until it has completed; either poll its operation or use its end of transfer interrupt to detect its completion.

It is best to use the "Insert Code" method to show code since reading code from screen shots is not very practical (especially if a line is to be copied as a quote, for example).

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]
Contact me by personal message or on the uTasker web site to discuss professional training, solutions to problems or product development requirements

 

0 Kudos
Reply
3,271 Views
mdrasool_yadwad
Contributor II

Below is my code please do check and correct me if there are any corrections 

//source address
DMA_TCD0_SADDR = (uint32_t)a;

/* Source offset disabled */
DMA_TCD0_SOFF = 0x01;

//Source data transfer size and Destination data transfer size
DMA_TCD0_ATTR=DMA_ATTR_SSIZE(0x00)|DMA_ATTR_DSIZE(0x00);

DMA_TCD0_NBYTES_MLNO= 0x04;

//Destination address
DMA_TCD0_DADDR =0x400EB007;

DMA_TCD0_CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(4);
/* No adjustment to destination address */
DMA_TCD0_DLASTSGA = 0x00;

DMA_TCD0_BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(4);

DMA_SERQ |= DMA_SERQ_SERQ_MASK;
DMA_TCD0_CSR = DMA_CSR_START_MASK;

0 Kudos
Reply
3,261 Views
mjbcswitzerland
Specialist V

Hi

 

DMA_TCD0_SOFF = 0x01;
is correct but DMA_TCD0_DOFF = 0;
should be added (and the comment corrected)

 

DMA_TCD0_DLASTSGA = 0x00;
is correct but it is best to add
DMA_TCD0_SLASTSGA = 0x00; too since these registers can be random at reset.
DMA_TCD0_DLASTSGA = -(sizeof(buffer)); is generally used if the output data is prepared in a circular buffer

 

You should set the DREQ flag in the DMA_TCD0_CSR register when working with peripherals otherwise each time there is a trigger 'all' bytes will be sent (overflow). The DREQ flag tells the eDMA to transfer only one byte per DMA trigger and not perform a burst transfer.

 

DMA_TCD0_NBYTES_MLNO= 0x04; is incorrect, it should be 1 since each transfer is a single byte and not 4.

 

DMA_SERQ |= DMA_SERQ_SERQ_MASK; may work but is not correct. It should be DMA_SERQ = 1; since you want to start operation only on this one channel.

 

DMA_TCD0_CSR = DMA_CSR_START_MASK; is also not correct since it is a software method of starting a transfer and not a peripheral driven one.
DMA_TCD0_CSR = DMA_CSR_DREQ; is correct, but it should be "before" the DMA_SERQ write. The first byte will automatically be started if the UART Tx Tx buffer is empty when DMA_SERQ = 1; is performed.

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]
Contact me by personal message or on the uTasker web site to discuss professional training, solutions to problems or product development requirements

 

0 Kudos
Reply
3,248 Views
mdrasool_yadwad
Contributor II

Thank You for your response.

Now if i want to send 109 bytes in a single DMA request . Here I am facing lots for problem. Can you explain me this. How it is done.

0 Kudos
Reply
3,243 Views
mjbcswitzerland
Specialist V

Hi

To perform a multiple transfer on a single trigger the minor loop counter (MLNO) is used.
This is however not of use for a peripheral driver like a UART.

Regards

Mark

 

0 Kudos
Reply
3,238 Views
mdrasool_yadwad
Contributor II

Then how to resolve this. Whether DMA is helpful in UART peripheral.

0 Kudos
Reply
3,219 Views
mjbcswitzerland
Specialist V

Hi

Multiple triggers when there is one place available in a peripheral is incorrect and will cause failure. A single transfer on each trigger is the correct way to do it.

DMA is very useful since there is no CPU overhead involved but doing it the wrong way (multiple transfers for a single trigger is incorrect and so won't work) won't allow it to be solved.

There are possibly working examples in the SDKs or there is a proven one at the GIT hub link I gave. It may be easier to use something that functions as reference to get you over the present difficulties or re-read the eDMA users manual carefully to gain more understanding.

Regards

Mark

 

3,153 Views
mdrasool_yadwad
Contributor II

hello sir,

Now i am facing problems in receive. I want to receive 4 bytes and store in the buffer but the buffer is loaded with same value. below i have written my code please go through it .

 


//Receive Function

{
DMA_SADDR_REG(dmach , ch) =0;

DMA_SADDR_REG(dmach , ch)|= DMA_SADDR_SADDR(0x4006B007); // CONFIGURING SOURCE ADDRESS
DMA_SOFF_REG(dmach,ch) =0;

DMA_ATTR_REG(dmach , ch) = (DMA_ATTR_SSIZE(0) | DMA_ATTR_DSIZE(0)); //CONFIGURING SOURCE ADDRESS SIZE

DMA_NBYTES_MLNO_REG(dmach , ch) = 0;

DMA_NBYTES_MLNO_REG(dmach , ch)|= (DMA_NBYTES_MLNO_NBYTES(0x04));
DMA_DADDR_REG(dmach , ch) = 0;
DMA_DADDR_REG(dmach , ch) |= DMA_DADDR_DADDR(val); //CONFIGURING DESTINATION ADDRESS ADDRESS


DMA_DOFF_REG(dmach , ch) = DMA_DOFF_DOFF(0x01);


DMA_BITER_ELINKNO_REG(dmach , ch) =0;
DMA_BITER_ELINKNO_REG(dmach , ch) = DMA_BITER_ELINKNO_BITER(0x4); //STARTING MAJOR ITERATION COUNT
DMA_CITER_ELINKNO_REG(dmach , ch) =0;
DMA_CITER_ELINKNO_REG(dmach , ch) = DMA_CITER_ELINKNO_CITER(0x4); // CURRENT MAJOR ITERATION COUNT


DMA_SERQ |= DMA_SERQ_SERQ_MASK;

DMA_CSR_REG(dmach , ch) = DMA_CSR_START_MASK; // START THE DMA

}

0 Kudos
Reply