Forums

QDMA in C64xx is offset by 1 byte from the desired location

Started by Unknown March 18, 2008
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
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
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 --
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
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
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.