DMA UART K60 Error

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

DMA UART K60 Error

跳至解决方案
3,296 次查看
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

标签 (1)
0 项奖励
回复
1 解答
3,222 次查看
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

 

在原帖中查看解决方案

8 回复数
3,290 次查看
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 项奖励
回复
3,275 次查看
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 项奖励
回复
3,265 次查看
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 项奖励
回复
3,252 次查看
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 项奖励
回复
3,247 次查看
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 项奖励
回复
3,242 次查看
mdrasool_yadwad
Contributor II

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

0 项奖励
回复
3,223 次查看
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,157 次查看
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 项奖励
回复