Hi, I am using QDMA to transfer a chunk of 16 16-byte words from internal memory to SDRAM. The problem is that when the source address is odd- numbered, the QDMA copies data from one location prior to the desired source addr. For e.g. if the source memory is like this (Little Endian): Addr Data 0x3 0xAABB 0x5 0xCCDD 0x7 0xEEFF If I want to copy 2 16-byte words starting from source address = 0x5, to the destination address, the dest address should havethe following data after QDMA : 0x0 0xCCDD 0x2 0xEEFF However, the result is like this: 0x0 0xDDAA 0x2 0xFFCC This seems to happen only if teh source addr is an odd number. QDMA details: -------------------- It is a simple QDMA of one chunk of data from one location to another. Both source and destination are 1D. I am doing 16 bit transfers. I've been trying to figure this out for a week without luck. I would be glad to give you further EDMA config details if that will help. Thanks, MG
QDMA in C64xx is offset by 1 byte from the desired location
Started by ●March 18, 2008
Reply by ●March 19, 20082008-03-19
EDMA Guide (spru234c.pdf) in section 1.7 has the following info: "The addresses must be aligned on the element size boundary. Word accesses must be aligned on a word (multiple of 4) boundary and half-word accesses must be aligned on a half-word (multiple of 2) boundary. Unaligned values will result in undefined operation." In your case that means you need to set it up for 8-bit transfers if you want to be able to have a source address that starts on any alignment. Of course, that will degrade your throughput. A better solution would be to just use the CPU to move any "remnants" on the ends and then setup the QDMA transfer with as large an element size as possible. Brad rustic.drive@gmail.com wrote:> Hi, > > I am using QDMA to transfer a chunk of 16 16-byte words from internal > memory to SDRAM. The problem is that when the source address is odd- > numbered, the QDMA copies data from one location prior to the desired > source addr. > > For e.g. if the source memory is like this (Little Endian): > Addr Data > 0x3 0xAABB > 0x5 0xCCDD > 0x7 0xEEFF > > If I want to copy 2 16-byte words starting from source address = 0x5, > to the destination address, the dest address should havethe following > data after QDMA : > 0x0 0xCCDD > 0x2 0xEEFF > > However, the result is like this: > 0x0 0xDDAA > 0x2 0xFFCC > > This seems to happen only if teh source addr is an odd number. > > QDMA details: > -------------------- > It is a simple QDMA of one chunk of data from one location to another. > Both source and destination are 1D. > I am doing 16 bit transfers. > > I've been trying to figure this out for a week without luck. I would > be glad to give you further EDMA config details if that will help. > > Thanks, > MG
Reply by ●March 19, 20082008-03-19
Brad Griffis wrote:> Of course, that will degrade your throughput.Degrade is putting it mildly. The DMA channel is 64-bits wide, so 8-bit transfers are 8 times slower than full width transfers.> A better solution would > be to just use the CPU to move any "remnants" on the ends and then setup > the QDMA transfer with as large an element size as possible.That can lead to awkward cache coherency issues: the DMA transfer bypasses the cache and ends up in SDRAM, the CPU copied bit ends up in cache. Unless there is some overwhelming reason not to, the easiest solution is to always allocate multiples of 8 bytes, aligned on 8 byte boundaries, and do 64-bit DMA transfers. Cheers mark-r --
Reply by ●March 19, 20082008-03-19
Thanks Brad and Mark. I tried doing an 8 bit transfer earlier but saw some weird results. I think I know what I was doing wrong there. I will try 8 bit transfers now and let you know how it goes. Thanks for your help! MG
Reply by ●March 19, 20082008-03-19
On Mar 18, 11:30 pm, Brad Griffis <bradgrif...@hotmail.com> wrote:> EDMA Guide (spru234c.pdf) in section 1.7 has the following info: > > "The addresses must be aligned on the element size boundary. Word accesses > must be aligned on a word (multiple of 4) boundary and half-word accesses > must be aligned on a half-word (multiple of 2) boundary. Unaligned > values will > result in undefined operation." > > In your case that means you need to set it up for 8-bit transfers if you > want to be able to have a source address that starts on any alignment.I tried 8 bit transfers and I'm seeing a different issue, again only when the source addr is odd. Though my src addr is aligned with the element size boundary (8 bit) I'm seeing weird results in the QDMA. Source addr Data 0xccf7f 0xff 0xccf80 0x7f 0xccf81 0xaa 0xccf82 0xbb Dest addr Data 0x60000100 7f7f 0x60000102 bbbb Essentially, the 8 bit value from the next (even) address is copied twice to the destination address. I thought this was because of incorrect incrementing in my QDMA config. I used a DAT_copy to copy the data and saw the exact same problem. So it probably isnt my sum, dum values. Both the QDMA and dat_copy work fine if they have to start copying from 0xccf80 (even address). If it helps, this is the QDMA config: addrexpand_32(_EDMA_QOPT_ADDR) = EDMA_OPT_RMK( EDMA_OPT_PRI_LOW, /* set priority to high; avoid using urgent if possible*/ EDMA_OPT_ESIZE_8BIT, /* 16-bit data */ EDMA_OPT_2DS_NO, /* two dimensional transfer */ EDMA_OPT_SUM_INC, /* increment source address by one element */ EDMA_OPT_2DD_NO, /* one dimensional transfer*/ EDMA_OPT_DUM_INC, /* destination address does not change */ EDMA_OPT_TCINT_YES, /* transfer complete indication neccessary */ EDMA_OPT_TCC_OF(TCC_BIT_USED), /* use CIPR bit 6 as transfer complete indicator */ EDMA_OPT_TCCM_OF(0), EDMA_OPT_ATCINT_NO, //alternate complete code not neccessary EDMA_OPT_ATCC_OF(0), //don't care what alternate code is EDMA_OPT_PDTS_DISABLE, EDMA_OPT_PDTD_DISABLE, EDMA_OPT_LINK_NO, EDMA_OPT_FS_YES /* not applicable for QDMA; always frame or block synchronized */ ); addrexpand_32(_EDMA_QSRC_ADDR) = EDMA_SRC_RMK(lcl_qdma_src); /* set source address */ addrexpand_32(_EDMA_QDST_ADDR) = EDMA_DST_RMK(lcl_qdma_dst); /* set source address */ /*addrexpand_32(_EDMA_QIDX_ADDR) = EDMA_IDX_RMK( EDMA_IDX_FRMIDX_OF(0x0001), // increment adresses by one element EDMA_IDX_ELEIDX_OF(0x0001) ); */ addrexpand_32(_EDMA_QIDX_ADDR) = EDMA_IDX_RMK(1, 1); // kick off edma transfer addrexpand_32(_EDMA_QSCNT_ADDR) = EDMA_CNT_RMK( EDMA_CNT_FRMCNT_OF(1), block_size>>1 ); If there are any red flags you see, pl let me know. I've run out of ideas on this. I could really use some help. Thanks for all your help thus far. MG
Reply by ●March 26, 20082008-03-26
Mark Robinson wrote:> Brad Griffis wrote: > >> Of course, that will degrade your throughput. > > Degrade is putting it mildly. The DMA channel is 64-bits wide, so 8-bit > transfers are 8 times slower than full width transfers. > >> A better solution would be to just use the CPU to move any "remnants" >> on the ends and then setup the QDMA transfer with as large an element >> size as possible. > > That can lead to awkward cache coherency issues: the DMA transfer > bypasses the cache and ends up in SDRAM, the CPU copied bit ends up in > cache. > > Unless there is some overwhelming reason not to, the easiest solution is > to always allocate multiples of 8 bytes, aligned on 8 byte boundaries, > and do 64-bit DMA transfers. > > Cheers > > mark-r >Good point on the cache coherence. I completely agree.