AnsweredAssumed Answered

request for help with DMA

Question asked by comsosysarch on May 25, 2011
Latest reply on Feb 17, 2012 by Said Syakin

I have a project (IAR) where I am setting up a buffer in memory and at a certain point in a loop I am trying to get the buffer to dump out of a uart using DMA.

I know I have the uart set up correctly because it is the same set up for another test app where it communicates with a PC. And data is coming out the uart and being read by the PC, which is great.

Unfortunately, the data is supposed to be framed and I suspect the DMA is not stopping when it should so I am getting extra superfluous bytes at the end of each frame and the PC is unable to sync on frames (custom frame format).

Seems like it should be a simple solution to someone familiar with DMA on the Kinetis device.

Here is the code I am using to set up the DMA channel:

// TDC for DMA Channel 1DMA_SADDR_REG(eDMA_BASE_PTR,1) = (UInt32)&tlmBuf;DMA_SOFF_REG(eDMA_BASE_PTR,1) = 1;DMA_ATTR_REG(eDMA_BASE_PTR,1) = DMA_ATTR_SMOD(0) | DMA_ATTR_SSIZE(0) | DMA_ATTR_DMOD(0) | DMA_ATTR_DSIZE(0);DMA_NBYTES_MLNO_REG(eDMA_BASE_PTR,1) = sizeof(UART0_D);DMA_SLAST_REG(eDMA_BASE_PTR,1) = -sizeof(tlmBuf);DMA_DADDR_REG(eDMA_BASE_PTR,1) = (UInt32)&UART0_D;DMA_DOFF_REG(eDMA_BASE_PTR,1) = 0;DMA_CITER_ELINKNO_REG(eDMA_BASE_PTR,1) = sizeof(tlmBuf);DMA_DLAST_SGA_REG(eDMA_BASE_PTR,1) = 0;DMA_CSR_REG(eDMA_BASE_PTR,1) = 0;DMA_BITER_ELINKNO_REG(eDMA_BASE_PTR,1) = sizeof(tlmBuf);DMAMUX_CHCFG_REG(DMAMUX_BASE_PTR,1) = DMAMUX_CHCFG_ENBL_MASK | DMAMUX_DMA_REQ_SRC_UART0_TX;

After this I set up the interrupt channel for DMA complete, enable the DMA (SERQ) and finally set the UART TIE mask to enable it to trigger the DMA channel.

Here is the DMA ISR code:

__irq void DMA1_IRQHandler(void){ DMA_CERQ = DMA_CERQ_CERQ(1); DMA_CINT = DMA_CINT_CINT(1);}

The ISR is supposed to turn off the DMA when complete.

I am clocking the K60 at 50 MHz (25 MHz flash) and the UART runs at 921600bps. So I would think I have some latency to be able to get to the ISR and switch off DMA before any extra bytes are transferred, although the way I have done it is not the way I would really prefer.

What I'd like is a way to run a single major loop of the DMA and have it automatically know to shut off at the end of the that one major loop without relying on an ISR that may have latency issues. Since I have a single-byte minor loop in this case maybe there is a way to run N bytes in the minor loop and shut off after one major loop instead. Either way.

I'm still reading through the DMA chapter in the FRM but if someone has experience doing this it would be a huge help.

Thanks.


Outcomes