This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SPI / EDMA and memcpy during transfer

Other Parts Discussed in Thread: AM3359

Hello,

i am using on theICE Board AM3359 and the SPI with EDMA.

Sometimes the spi/edma send one byte to much on SPI channel. It happens when i manipulate data to be send (in actual dataframe) with memcpy. When the memcpy is called, the data which i manipulate, is not touched by the EDMA at the same time. The mutuality between EDMA and memcpy is the start adress of the txBuffer, where the data to be send is stored.

____||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||________ SPI data (txBuffer)

_____memcpy()_|Byte_A|________||||||||________ parallel memcpy() and manipulate last bytes.

It seems that the BCNT, does not decrement, that the EDMA passes Byte_A two times to SPI.

When the Error occurs, i can see that the EdmaComplInterrupt appear 4 SPICLK cycles later.

How often occurs the SPI EDMA Even? Every byte? (SPI wordlength is 8)

Thanks.

  • I am not entirely sure if this explains anything, but, if the the data buffer involved in the EDMA transfer has been touched by the CPU (via memcpy), which seems to be the case here then, if:

    (a)  the data buffer is in external memory, and

    (b) cache is enabled for the data range where the buffer is,

    then you would need to ensure Cache coherence since EDMA is not cache aware. For example if EDMA is used to transfer the data buffer which was just written to via memcpy() then you have to issue a cache-writeback *before* you start the EDMA transfer.

    Additionally you must ensure that the data buffer lies within cache-line size aligned buffer. (128-byte aligned addresses for start and end of buffer.

    Are you taking care of these?

    Murat

  • Hello Murat,

    yes, Cache is enabled and the buffer are in external memory (DDR).
     The buffers are aligfned to 64bit (#pragma DATA_ALIGN(txPingBuffer,64)).
    Regarding cache coherency i use this function before memcpy CacheDataInvalidateBuff();

    I already checked if the data is correct, between cache and memory.

    Only if i change the last bytes of the buffer (which is currently transmitted) then the error occurs. It was about 70times in one hour.

    When the error occurs i can see that the EDMACompletion Interrupt apperas about 12µs later than usual.

  • Can you sketch the relevant code portion related to the buffer access and EDMA transfers.

    Doing an cache-invalidate of the buffer before memcpy() is correct for accessing the buffer that was just EDMA'ed in. (I am assuming that is the case.) However, you mention modifying the buffer currently trasnmistted, which is unclear to me.

    If you modify a buffer (say via CPU write) then you need to Cache-Writeback before submitting the EDMA transfer the data out of that buffer, and I don't see that mentioned in your note.

    Best regards,

    Murat

  • During a transfer of one frame i got two times into the EDMA Completion Handler. First time after e.g. 10 Bytes the second time after 30 Byte.

    If the first EDMA Interrupt occurs, the following is done:

    EDMA3ClrIntr()
    CacheDataInvalidateBuff(&rxBuffer, 10);
    memcpy(&myStructure,&rxBuffer,10);
    First RX Data (10bytes) needed to calculate data for the last Bytes in this actual frame. 
    memcpy((&txBuffer)+20,(&myStructure)+20,10);  //  Last Bytes with new values



    Regarding the coherency, i´ve seen in Debug mode that CPU and Memory View are the identical.

    The error does not occurs every time. Only if sometime the first interrupt has a delay of about 12µs at 8Mhz SPI-Clk

  • Hi Daniel,

    This is still not very clear to me.

    (1) You should cache-invalidate the rxBuffer before submitting the EDMA transfer, this is to avoid a race condition where if there is dirty data in rxBuffer, and due to system activity if it rxBuffer gets evicted from cache while EDMA is in progress the stale dirty contents of the rxBuffer may overwrite the newly transfered rxBuffer. (I am not saying this is what happened, but there is a possibility, so issue the

    CacheDataInvalidateBuff

    before EDMA transfer into rxBuffer starts.

    (2) after you prepare the txBuffer, do you EDMA out the txBuffer to somewhere else? if so, you must do a Cache Writeback after the memcpy()

    (3) how large are your rxBuffer and txBuffer?

    (4) please indicate the 'error', what do you observe. it is not clear from the description above.


    Best regards,

    Murat

  • Hi Murat,

    i am with the AM3359 SPI-SLAVE. I cannot initiate the transfer.

    If the am3359 has input data via SPI/EDMA, then after 10bytes the EDMA Interrupt triggers the EDMA ISR, in which i save the 10bytes input-data to rxBuffer, calculate, and modify the last 5 bytes in txBuffer (of total 30bytes) with e.g. a checksum.

    CacheDataInvalidateBuff will be called at the beginning of the ISR before memcpy() the rxBuffer to a structure (to ensure memcpy() reads data from ext. memory)

    The last bytes which will be written to ext. memory with memcpy() [txBuffer] don´t need a CacheDataInvalidateBuff because the data will be read from cache and written to memory (EDMA reads the txBuffer from memory)


    The buffers are 64byte large.

    #pragma DATA_ALIGN(txPingBuffer,64);   volatile unsigned char txPingBuffer[64]; 

    For EDMA i use ping/pong paramsets and buffers, because i need two EDMA Interrupts (after 10bytes and the last completion interrupt)

    In the picture you can see the first interrupt duration (start/end) in green. When the first Interrupt of one transfer (this one after 10bytes) is finish, the last instruction is memcpy(), copy the checksum at the last bytes of txBuffer. When the green line is low, the ISR is completed and there you can see (blue line) that 0x44 is sent two times.

    That is the ERROR which i mean. The checksum at receiver will not be correct !!!

    When the first EDMA ISR is finish, there are about 20 more bytes to be received/transmitted in one dataframe.

    i assume that the SPI send two times the same data, if the interrupt occurs abput 12µs later and has a 15µs longer duration then usual. Everytime i got this error, the interrupt is a little bit later, so if i copy to the txBuffer that maybe the EDMA in this time has access to the same byte of the dataframe?

  • Are you still having this issue?

    I still think you are missing a CacheWriteBackInvalidate of the txBuffer *after* the memcpy().

    I am not sure about how to interpret the back-to-back 0x44 you circled. Is this the contents of the data bus?


    Best regards,

    Murat

  • Yes i have still this problem. The blue signal is the data bus.

    I´ve tried these functions  CacheDataCleanBuff, CacheDataInvalidateBuff, CacheDataCleanInvalidateBuff but hat was not the solution.

    I can not determine what causes this error.

    But every time when a byte is wrongly sended two times (results in an offset, no data is lost or corrupted),

    the EDMA Interrupt finishs (GPIO toggle green signal)

  • I am not entirely sure what is happening here either. If the issue still persists, to further isolate the issue, can you try disabling the cache and see if the issue of unexpected DMA transfer still takes place?

    Murat

  • I´ve solved this problem.


    The solution is, to change the memory for the EDMA variables. First the DDR memory (0x8000000) was used for the EDMA variables.

    The variables are now stored on the on-chip-memory (0x40300000) which is connected over L3 fast interconnect. The change of the memory reduces this error to zero.

  • Thanks Daniel,

    Glad your issue is resolved.

    Murat

  • Maybe someone has some informations for me about the L3 FastInterconnect and how the DDR is connected.

    And with which busrates work these memories..

    Thanks