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.

C6747 EDMA Link to Self transfer from SPI

Other Parts Discussed in Thread: SYSBIOS

Hello,

I am having difficulties using the EDMA on the 6747 core of an OMAPL137. I am trying use the EDMA to service a receive event from the SPI peripheral. A fixed amount of data arrives on the SPI at regular intervals so I have set the EDMA to do a ‘Link-to-Self Transfer’ as described in the user guide SPRUFL1c, page 30. The first reception works OK and the PaRAM set gets linked correctly, but subsequent receptions, though appear to handled correctly (the correct IPR bit gets set), no new data is transferred. As anyone had this problem before, is there anything one has to do to reset the channel controller after the first transfer has completed?

Cheers,

John

 

 

  • John

    Please share your PaRAM values for your "link to self" transfer. Without additional information , my first guess would be that the SPI never generated the subsequent events, any way for you to confirm that this is not the case?

    Regards

    Mukul

  • Mukul,

    Thank you for your reply. I am pretty sure that the SPI is generating events because I can step through the program and watch the PaRAM set updating (the BCNT field decrements on every word received). Then, after the full message has been received, the PaRAM set updates and the IPR bit that I have specified (bit 0) get set. So it all appears to be working fine, except that no new data has appeared in my buffer, apart from the first time around.

    I use PaRAM set 14 (for the SPI RX event), and link to PaRAM set 32 as this is the first that is not assigned to a channel. PaRAM set 32 is set up identically to PaRAM set 14:

    /* Parameter set 14 (for event and channel 14 - SPI0 RX) */

    edmaRegs->PARAMSET[14].OPT          = 0x00100000;

    edmaRegs->PARAMSET[14].SRC          = (Uint32)&(spiRegs->SPIBUF);

    edmaRegs->PARAMSET[14].A_B_CNT      = 0x00020002;

    edmaRegs->PARAMSET[14].DST          = (Uint32)RXDataBuffer;

    edmaRegs->PARAMSET[14].SRC_DST_BIDX = 0x00020000;

    edmaRegs->PARAMSET[14].LINK_BCNTRLD = 0x00004400;

    edmaRegs->PARAMSET[14].SRC_DST_CIDX = 0x00000000;

    edmaRegs->PARAMSET[14].CCNT         = 0x00000001;

    /* Parameter set 32 reload */

    edmaRegs->PARAMSET[32].OPT          = 0x00100000;

    edmaRegs->PARAMSET[32].SRC          = (Uint32)&(spiRegs->SPIBUF);

    edmaRegs->PARAMSET[32].A_B_CNT      = 0x00020002;

    edmaRegs->PARAMSET[32].DST          = (Uint32)RXDataBuffer;

    edmaRegs->PARAMSET[32].SRC_DST_BIDX = 0x00020000;

    edmaRegs->PARAMSET[32].LINK_BCNTRLD = 0x00004400;

    edmaRegs->PARAMSET[32].SRC_DST_CIDX = 0x00000000;

    edmaRegs->PARAMSET[32].CCNT         = 0x00000001;

      The other EDMA set up I do is:

     /* Clear missed event, error and event registers */

    edmaRegs->EMCR     = 0xFFFFFFFF;

    edmaRegs->QEMCR    = 0x000000FF;

    edmaRegs->CCERRCLR = 0x00010003;

    edmaRegs->ECR      = 0xFFFFFFFF;

    edmaRegs->SECR     = 0xFFFFFFFF;

     Then in my main code, the reception is handled like this:

     /* Enable DMA request so that slave transmissions can be received */

    spiRegs->SPIINT0 = 0x10000;

    /* Wait for transfer complete */

    data = (Uint16)spiRegs->SPIBUF;

    edmaRegs->ICR = 0xFFFFFFFF;

    while (edmaRegs->IPR == 0x0) ;  

    /* Disable DMA request */

    spiRegs->SPIINT0 = 0x0;

    I realise that blocking on the IPR is inefficient and defeats the object of using the EDMA in the first place - but this is just an example to show the problem, in the real application I will enable the interrupt on the IPR bit.

    Any light that you can shed on this problem would be appreciated.

    Cheers,

    John.

  • John

    Thanks for sharing the details. Do you know for sure that the second time around you see the PARAM32 get copied over to PARAM14 location? It is not clear from what you said

    John Wilkes said:
    Then, after the full message has been received, the PaRAM set updates and the IPR bit that I have specified (bit 0) get set.

    Assuming it is getting copied over, how do you go about reenabling the DMA request (spiRegs->SPIINT0 = 0x10000;) once the first param expires and sets the IPR and you clear the IPR and disable the DMA request (is this being done in a loop?)

    Regards

    Mukul

  • Hi Mukul,

    Thanks again for your help. I know that PaRAM 14 gets updated from PaRAM32 because I can control the incoming SPI data (actually from a Piccolo microcontroller) so that one word is sent at a time, I can view PaRAM set 14 as each word is received and I see it updated: after the first word arrives, the BCNT reduces to 1 and the DST increases by 2. After the second word arrives, the PaRAM set is restored to its original settings - indicating that the update from PaRAM 32 has occurred - and the IPR bit gets set. After stepping through this the first time, the data transmitted by the Piccolo is in the RXDataBuffer array. The second time stepping through this is identical, except no new data appears in the array.

    I have also tried using the second SPI module (event and PaRAM set 18), but this behaves in exactly the same way.

    The code is in a loop. Actually it is in the idle task of SYS/BIOS so it loops forever. Earlier in the loop the 6747 signals to the Piccolo to send its data, and later in the loop the data is processed. This structure is for development purposes: I plan to use a clock thread to signal for the data and a swi thread triggered from the DMA interrupt to process the data when it has arrived. But I need to get it working first.

    Cheers,

    John.

     

     

  • Hi John

    Thanks for the additional details. I still think the second time around the SPI Rx event was not generated or not captured by the EDMA.

    Please clarify additionally that the second time (once PARAM32 contents are copied over PARAM14), do you see them decrement again? Do you see the IPR bit get set again (after you cleared it first time via write to ICR)? Is the code stuck polling for IPR completion?

    Some debug suggestions

    1) Try not disabling the DMAREQEN bit (just leave it enabled)?

    2) Try a BCNT of greater then 2 , say 4 or higher just to make sure that if you just had a single PARAM14 that has the entire transfer context, you are able to transfer all the bytes (just trying to make sure that the "break" in functionality is only once linking happens)

    3) Since RXDATABuffer is a circular buffer ( PARAM32 dst location is the same as PARAM14) I am hoping that the data that you transmit 1st time vs 2nd time is different data patterns, so that you can clearly tell that the new data (2nd iteration) never came through (not just getting overwritten by the same data pattern etc).

    Regards

    Mukul

     

  • My colleague pointed out that if you were getting the IPR bit set the second iteration, but just that the CPU is not seeing the data. It could also be a cache coherency issue? Which memory are you using for rx data buffer? There are bios apis (BCACHE) to do cache invalidation.

  • Hi Mukul,

    Hmmm, the cache thing sounds likely - the DMA writes the value to memory but the CPUs cache does not get updated. Maybe you could advise me here as I do not have a lot of experience with cache: How do I know (or force) which part of memory my variable is in? The buffer is defined as global array and I used a standard SYSBIOS config and didn't set up anything special with the  memory - maybe I should have? The memory address of the array, according to the watch window, is 0xC300AEE0 - does this help locate which memory it is in?

    As far as the other things:

    The reason that I disable the DMAREQEN bit is because other things happen on the SPI port in other parts of the loop, but I don't want the DMA to respond to these. I tried disabling the EER bit instead and leaving DMAREQEN permanently set - I got exactly the same results as before.

    I haven't had a chnace to try BCNT = 4, but I'm not sure what this will show, the "break" is only happening after the link because I can see the first two words arrive seperately and correctly if I step through on the Piccolo.

    The data that arrives each time may be different or the same - but I fill my array with zeros prior to reception so that is clear to see that new data isn't being written to the buffer (unless of course it is zeros arriving - but it isn't).

    Thanks again for your help.

    Cheers,

    John.

     

     

  • John

    I am not a SYSBIOS expert, but looking at the user guide

    http://processors.wiki.ti.com/images/f/f6/Spruex3e.pdf

    You have a couple of options to test out the cache-coherency theory

    1) Your data buffer is currently in external memory (SDRAM), you can try to map all your code/data to L2 (IRAM) memory (0x118000000)  instead to avoid cache coherency issues between EDMA and CPU. How to re-map put code,data , stack in different memory segments is shown on Page 5-8, 5.2.2.3 (FYI some of the snapshots in the guide are for DA830 , which belongs to the same design family as c6747, so the illustrations will apply as-is to c6747)

    2) As a test, you can temporarily disable SDRAM caching , this is controlled via MAR bits for different memories (like Shared RAM and SDRAM). I believe by default BIOS might be enabling caching to external memories, so you can disable to by writing to appropriate MAR register bits (shown in section 5.5.2) , the MAR bits are defined in the datasheet Table 3-2 (MAR192 onwards is for 0xc000 0000 memory segments)

    3) Probably the long term solution would be to make use of the Cache_inv APIs to avoid read coherency issues ( the usage is described in the user guide section 6.4.1)

    Hope this helps.

    All of this still assumes that your IPR bit did  get set the second time (the transfer done with PARAM32 copied over to PARAM14) and you think just the CPU is reading incorrect,stale values etc.

    Regards

    Mukul

     

  • Hi Mukul,

    Yes this was the problem. Following your first suggestion I created a new RTSC platform with code, data and stack sections defaulting to IRAM. After recompiling the project with this custom platform, the buffer is now updated every time an SPI reception occurs. The problem is solved. Thank you very much for your help.

    Cheers,

    John.