AnsweredAssumed Answered

Problem with memory shared between USB, DMA and CPU in an iMX 51.

Question asked by Claus Stovgaard on Dec 16, 2012
Latest reply on Nov 22, 2013 by grantw
Branched to a new discussion

I am having a problem, where the memory controller / TLB and cache system on an iMx 51 seems to play tricks on me.

The problem can be described by the following pice of code.

 

volatile EndpointTransferDescriptorStruct* dTDPtr = dTDHandlerPtr->dTD;
// 4K apart buffer page pointers
U32 currentStartAddress = (U32)(transfer.requestStartAddress + currentOffset);
dTDPtr->BufferPointerPage0 = currentStartAddress;
dTDPtr->BufferPointerPage1 = dTDPtr->BufferPointerPage0 + 4096;
dTDPtr->BufferPointerPage2 = dTDPtr->BufferPointerPage1 + 4096;
dTDPtr->BufferPointerPage3 = dTDPtr->BufferPointerPage2 + 4096;
dTDPtr->BufferPointerPage4 = dTDPtr->BufferPointerPage3 + 4096;

U32 tempPtr = dTDHandlerPtr->dTD->BufferPointerPage0;
if (tempPtr)
{
    if (tempPtr dTD);

        U32 timeout = 100;
        while (timeout)
        {
            U32 tempPtrTwo = dTDHandlerPtr->dTD->BufferPointerPage0;

            TRACEE("Buffer pointer 0 0x%x, @ %dms\n", tempPtrTwo, GetTimeMs());
            if (tempPtrTwo == currentStartAddress)
            {
                break;
            }
            Wait(1);
            timeout--;
        }

        TRACE( "stop\n" );
        TRACE("temp 0x%x, 0x%x, 0x%x", tempPtr, dTDPtr, dTDHandlerPtr->dTD);
        TRACE("temp 2 0x%x\n", currentStartAddress);
        ASSERT(0);
    }
}

 

This piece of code is part of a bigger system, which runs in some time, until the following is printed, and I can break it by my debugger at the "stop" trace.

 

How could this happens startAddr = 0xaf3e0380, tempPtr 0x4000380, dTDPtr 0xaf32c0e0, dTD 0xaf32c0e0??

Buffer pointer 0 0xaf3e0380, @ 95930ms

 

The address in startAddr is correct, where tempPtr is not correct. Looking at the structure with BufferPointerPage1-4 its address is not correct, as it uses the 0x4000380 address as value for BufferPointerPage0. When I read BufferPointerPage0 ones more at line 18 the value is correct. Some how either the write seems "lazy" compared to the read. Or the read fails some times before it is refreshed and is correct later.


For fully understanding this, you will need to know, that dTDPtr pointer is pointing to the top of the LPDDR memory, which is setup to be uncached seen from the CPU. The dTRPtr is also declared volatile all places it is used, as it is handed over to hardware later. All in all is there 12 mb of uncached memory, which contains the QH, a pool of dTDs. Just next to this area (starting inside the same 1 mb section of memory), some buffers used by the DMA and USB is located. So looking at the memory, it must control access from CPU, DMA and USB, and still maintain correct data in the memory.


I will like some input to this problem.

Outcomes