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).
main.c
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(;;) {}
}
Debugger Results
I have seen the following behaviour in my debugging environment:
- SADDR and DADDR for both TCDs are incremented/decremented correctly for the first major loop
- data is correctly transferred during the first major loop
- data is correctly transferred during the first minor loop of the second major loop
- data is incorrectly transferred during the second minor loop of the second major loop
- TCD1 correctly transfers data from src[0]->dst[2]
- TCD2 is not triggered so the transfer of src[1]->dst[3] does not occur
- Before this transfer takes place, EDMA.TCD[1].CSR.B.MAJORELINK is cleared somehow
- Before this transfer takes place, EDMA.TCD[1].CITER.ELINKYES.B.ELINK = 1 and EDMA.TCD[1].CITER.ELINKYES.B.LINKCH = 2, which makes me think that TCD2 should be triggered, but it is not
- After this transfer takes place, EDMA.TCD[2].DADDR.B.DADDR is not changed which confirms that TCD1 did not trigger TCD2
- on the first minor loop of the third major loop, TCD1 correctly transfers src[0]->dst[0], and TCD2 is triggered which transfers src[1]->dst[3] which is incorrect but I guess makes sense if it was not triggered during the second minor loop of the second major loop
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