Hi all,
I am using the MPC5748G's (dev-kit) eDMA to transfer data from one buffer in SRAM to another and have found that my configuration of linking two TCDs does not behave as I expect. I have the following two data buffers:
uint32_t src[2]; // data source
uint32_t dst[4]; // data destination
I would like to continually do the following: transfer src[0]->dst[0] and src[1]->dst[1], then after waiting one second transfer src[0]->dst[2] and src[1]->dst[3]. I have written the following configuration to do this in two minor loops, where src[0] is transferred using TCD1 which then links to src[1] being transfered by TCD2. I have observed that the first major loop behaves correctly but the second minor loop of the second major loop does not (described in detail below).
static uint32_t src[2];
static uint32_t dst[4];
void ISR_1Hz() {
/* Update source buffer for debugging */
static uint8_t data = 0;
src[0] = data;
src[1] = data + 1;
data += 2;
data %= 256;
/* Start DMA transfers */
EDMA.TCD[1].CSR.B.START = 1;
}
void main() {
/* Configure TCD 1 */
EDMA.TCD[1].SADDR.B.SADDR = (uint32_t)&src[0];
EDMA.TCD[1].ATTR.B.SMOD = 0;
EDMA.TCD[1].ATTR.B.SSIZE = 2; // 32-bit source size
EDMA.TCD[1].SOFF.B.SOFF = 0;
EDMA.TCD[1].SLAST.B.SLAST = 0;
EDMA.TCD[1].DADDR.B.DADDR = (uint32_t)&dest[0];
EDMA.TCD[1].ATTR.B.DMOD = 0;
EDMA.TCD[1].ATTR.B.DSIZE = 2; // 32-bit destination size
EDMA.TCD[1].DOFF.B.DOFF = 8; // increment dest 8-bytes each minor loop
EDMA.TCD[1].DLASTSGA.B.DLASTSGA = -16; // decrement dest 16-bytes each major loop
EDMA.TCD[1].NBYTES.MLNO.B.NBYTES = 4; // transfer 4-bytes per minor loop
EDMA.TCD[1].CITER.ELINKYES.B.ELINK = 1; // enable channel-channel linking after minor loops
EDMA.TCD[1].CITER.ELINKYES.B.LINKCH = 2; // enable ch2 for linking
EDMA.TCD[1].CITER.ELINKYES.B.CITER = 2; // 2 minor loops per major loop
EDMA.TCD[1].BITER.ELINKYES.B.BITER = 2; // same as above
EDMA.TCD[1].BITER.ELINKYES.B.ELINK = 1; // same as above
EDMA.TCD[1].BITER.ELINKYES.B.LINKCH = 2; // same as above
EDMA.TCD[1].CSR.B.BWC = 0;
EDMA.TCD[1].CSR.B.INTMAJOR = 0;
EDMA.TCD[1].CSR.B.MAJORELINK = 1; // enable channel-channel linking after major loops
EDMA.TCD[1].CSR.B.MAJORLINKCH = 2; // enable ch2 for linking
/* Configure TCD 2 */
EDMA.TCD[2].SADDR.B.SADDR = (uint32_t)&src[1];
EDMA.TCD[2].ATTR.B.SMOD = 0;
EDMA.TCD[2].ATTR.B.SSIZE = 2;
EDMA.TCD[2].SOFF.B.SOFF = 0;
EDMA.TCD[2].SLAST.B.SLAST = 0;
EDMA.TCD[2].DADDR.B.DADDR = (uint32_t)&dest[1];
EDMA.TCD[2].ATTR.B.DMOD = 0;
EDMA.TCD[2].ATTR.B.DSIZE = 2;
EDMA.TCD[2].DOFF.B.DOFF = 8;
EDMA.TCD[2].DLASTSGA.B.DLASTSGA = -16;
EDMA.TCD[2].NBYTES.MLNO.B.NBYTES = 4;
EDMA.TCD[2].CITER.ELINKNO.B.ELINK = 0; // same config as TCD1 but no linking
EDMA.TCD[2].CITER.ELINKNO.B.CITER = 2;
EDMA.TCD[2].BITER.ELINKNO.B.BITER = 2;
EDMA.TCD[2].BITER.ELINKNO.B.ELINK = 0;
EDMA.TCD[2].CSR.B.BWC = 0;
EDMA.TCD[2].CSR.B.INTMAJOR = 0;
/* Do nothing else */
for(;;) {}
}
I have seen the following behaviour in my debugging environment:
Please advise what I can change to my TCD configuration to solve this issue. Alternatively, if there is a better suited approach to this problem or if I should clarify any part of my question, please let me know.
Cheers,
Anthony B
Solved! Go to Solution.
I don't like using of .B instance especially with status or control/status registers as it is a source of potential issues. Pay attention to following bulletin:
http://www.nxp.com/files/32bit/doc/eng_bulletin/EB758.pdf
I would recommend to use .R instance.
I don't like using of .B instance especially with status or control/status registers as it is a source of potential issues. Pay attention to following bulletin:
http://www.nxp.com/files/32bit/doc/eng_bulletin/EB758.pdf
I would recommend to use .R instance.
Changed all to use .R and it works as intended. Thanks a lot, David!
Hi, are you starting it by TCD0, when you are only using TCD1 and 2? Or there is further info missing?
My mistake, I copied it to this forum incorrectly. Yes, I've been using TCD[1] to trigger the DMA transfer. I updated the original post.