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.

McASP multiple serializers & EDMA3

Other Parts Discussed in Thread: OMAP-L138

Hi

I have a question about DMA transfers when using McASP with multiple serializers on OMAP-L138. In my situation it looks like that:

- I have 8 serializers programmed as input and 8 programmed as output
- I'm transmitting/receiving 32 8-bit slots on every serializer
- so far the transmitters are looped back to receivers for debugging purposes

I thought I should set up DMA to transfer 32slots*1byte*8serializers ACNT bytes every AXEVT and receive the same amount on AREVT but it doesn't seem to work. When I simply set ACNT to 256 bytes XDMAERR and RDMAERR bits light up. Setting ACNT to 32 doesn't cause DMA errors, but I don't follow why is that. How should writing and reading from McASP DMA port look like in my situation? When I tell EDMA to transmit 256 bytes form address 0x11800000 does it write 32slots*1byte for serializer 1, 32slots*1byte from 0x11800020 for serialzer 2 and so on?

Also, what is the best way of triggering a different DMA transfer, let's say, once 5 AXEVT or AREVT events?

My McASP setting and status registers:

WFIFOCTL: 0
RFIFOCTL: 0
RMASK: ffffffff
RFMT: 30
AFSRCTL: 1003
ACLKRCTL: 20
AHCLKRCTL: 800b
RXTDM: ffffffff
RINTCTL: 0
RCLKCHK: 8ff0008
TXMASK: ffffffff
TXFMT: 30
AFSXCTL: 1002
ACLKXCTL: 60
AHCLKXCTL: 800b
TXTDM: ffffffff
XINTCTL: 0
XCLKCHK: 8ff0008
SRCTL[0]: 2
SRCTL[1]: 1
SRCTL[2]: 2
SRCTL[3]: 1
SRCTL[4]: 2
SRCTL[5]: 1
SRCTL[6]: 2
SRCTL[7]: 1
SRCTL[8]: 2
SRCTL[9]: 1
SRCTL[10]: 2
SRCTL[11]: 1
SRCTL[12]: 2
SRCTL[13]: 1
SRCTL[14]: 2
SRCTL[15]: 1
PFUNC: 0
PDIR: fc00aaaa
DLBCTL: 5
AMUTE: 0
XSTAT: 1d1
RSTAT: 1d0
GLBCTLR: 1f1f
GLBCTLX: 1f1f

Regards
Szymon

  • The Wiki page on OMAP-L1x McASP may be helpful to you. Please take a look at this and then come back with your updated questions.

    Be sure to look at FIFO depth settings to adjust how much data is expect per AXEVT.

  • After some time spent understanding McASP and EDMA I think I know enough to proceed further.

    What I'm planning to do is to place McASP and EDMA configuration code inside a DSP program which is to be loaded using DSPLink. My concern is that writing LLD EDMA code and executing it on the DSP while Linux is already running can mess things up...
    The EDMA initialization code needs an address from which our data would be shifted out of the serializers. This address would be avaliable only on the DSP. There probably would be a quick way of exchanging this address between ARM and DSP but it seems overcomplicated and unnatural. I'm also planning to use interrupts on the DSP side on data transfer completion. Again, using the EDMA LLD would make more sense...

    What do you think of my approach?

    I have also stumbled upon a problem with linking in EDMA LLD:

    When i define my transfer like this (a trivial example really):

            unsigned int chIdTX0 = EDMA3_DRV_HW_CHANNEL_EVENT_1;

            paramSetTX0.srcAddr    = (unsigned int)(0x11800000);
            paramSetTX0.destAddr   = (unsigned int)(0x01D02000);
            paramSetTX0.srcBIdx    = 0;
            paramSetTX0.destBIdx   = 0;
            paramSetTX0.srcCIdx    = 0;
            paramSetTX0.destCIdx   = 0;
            paramSetTX0.aCnt       = 32;
            paramSetTX0.bCnt       = 1;
            paramSetTX0.cCnt       = 1;
            paramSetTX0.bCntReload = 0;
            paramSetTX0.linkAddr   = 0xFFFFu;
            paramSetTX0.opt = 0x0010000C; //NOTE: STATIC transfer
            result = EDMA3_DRV_setPaRAM(hEdma, chIdTX0, &paramSetTX0);
            if (result != EDMA3_DRV_SOK) {
               return result;
            }

    I get a random output on the serializers, as I expeced, depending on what's written in 0x11800000 and above.
    But when I try linking two PaRAM Sets like this:

           unsigned int chIdTX0 = EDMA3_DRV_HW_CHANNEL_EVENT_1;
           unsigned int chIdTXLink0= EDMA3_DRV_LINK_CHANNEL;

           paramSetTX0.srcAddr    = (unsigned int)(0x11800000);
           paramSetTX0.destAddr   = (unsigned int)(0x01D02000);
           paramSetTX0.srcBIdx    = 0;
           paramSetTX0.destBIdx   = 0;
           paramSetTX0.srcCIdx    = 0;
           paramSetTX0.destCIdx   = 0;
           paramSetTX0.aCnt       = 32;
           paramSetTX0.bCnt       = 1;
           paramSetTX0.cCnt       = 1;
           paramSetTX0.bCntReload = 0;
           paramSetTX0.linkAddr   = 0xFFFFu;
           paramSetTX0.opt = 0x00100000;

           result = EDMA3_DRV_setPaRAM(hEdma, chIdTX0, &paramSetTX0);
           if (result != EDMA3_DRV_SOK) {

               return result;

           }
           result = EDMA3_DRV_setPaRAM(hEdma, chIdTXLink0, &paramSetTX0);
           if (result != EDMA3_DRV_SOK) {
              return result;
           }
           result = EDMA3_DRV_linkChannel(hEdma, chIdTX0, chIdTXLink0);
           if (result != EDMA3_DRV_SOK) {
              return result;
           }

    ...I get transmitter underrun status on McASP as if something was wrong. Why is that?

    I would appreciate any feedback on that :). I can provide a full source code if you like.

    Regards
    Szymon

  • I looked into the registers and noticed that when I call EDMA3_DRV_linkChannel(hEdma, chIdTX0, chIdTXLink0); the PaRAM of chIdTX0 doesn't get reloaded but instead a NULL PaRAM set gets written.

    When I explicitly write the LinkReload address to the correct register McASP starts up just fine. There is one thing I don't fully understand about that though. chIdTXLink0 has a value of 64 in my case, so linking should be performed to PaRAM set 64. LinkReload should be: 0x4000 + 0x20*64 = 0x4800 (offset + PaRAMSize*channelNumber). While I was looking into the registers I noticed that EDMA3_DRV_setPaRAM(hEdma, chIdTXLink0, &paramSetTX0); wrote the values to 0x4400. Knowing that I changed the LinkReload to 0x4400 and it finnaly started working. Could anyone explain what's going on?

    The EDMA initialization code was taken from the example provided by TI in OMAP_L138_arm_1_00_00_06.

  • Szymon,

    Szymon Kuklinski said:

    I looked into the registers and noticed that when I call EDMA3_DRV_linkChannel(hEdma, chIdTX0, chIdTXLink0); the PaRAM of chIdTX0 doesn't get reloaded but instead a NULL PaRAM set gets written.

    When I explicitly write the LinkReload address to the correct register McASP starts up just fine. There is one thing I don't fully understand about that though. chIdTXLink0 has a value of 64 in my case, so linking should be performed to PaRAM set 64. LinkReload should be: 0x4000 + 0x20*64 = 0x4800 (offset + PaRAMSize*channelNumber). While I was looking into the registers I noticed that EDMA3_DRV_setPaRAM(hEdma, chIdTXLink0, &paramSetTX0); wrote the values to 0x4400. Knowing that I changed the LinkReload to 0x4400 and it finnaly started working. Could anyone explain what's going on?

    The EDMA initialization code was taken from the example provided by TI in OMAP_L138_arm_1_00_00_06.

    This is happening because the EDMA3_DRV_linkChannel() API  only links the chIDTX0 with chIdTXLink0 (i.e. it writes the address of the paRAM of the chIdTXLink0 in the link.Addr field of chIdTX0).

    And

    Szymon Kuklinski said:

    When i define my transfer like this (a trivial example really):

            unsigned int chIdTX0 = EDMA3_DRV_HW_CHANNEL_EVENT_1;

            paramSetTX0.srcAddr    = (unsigned int)(0x11800000);
            paramSetTX0.destAddr   = (unsigned int)(0x01D02000);
            paramSetTX0.srcBIdx    = 0;
            paramSetTX0.destBIdx   = 0;
            paramSetTX0.srcCIdx    = 0;
            paramSetTX0.destCIdx   = 0;
            paramSetTX0.aCnt       = 32;
            paramSetTX0.bCnt       = 1;
            paramSetTX0.cCnt       = 1;
            paramSetTX0.bCntReload = 0;
            paramSetTX0.linkAddr   = 0xFFFFu;
            paramSetTX0.opt = 0x0010000C; //NOTE: STATIC transfer
            result = EDMA3_DRV_setPaRAM(hEdma, chIdTX0, &paramSetTX0);
            if (result != EDMA3_DRV_SOK) {
               return result;
            }

    I get a random output on the serializers, as I expeced, depending on what's written in 0x11800000 and above.
    But when I try linking two PaRAM Sets like this:

           unsigned int chIdTX0 = EDMA3_DRV_HW_CHANNEL_EVENT_1;
           unsigned int chIdTXLink0= EDMA3_DRV_LINK_CHANNEL;

           paramSetTX0.srcAddr    = (unsigned int)(0x11800000);
           paramSetTX0.destAddr   = (unsigned int)(0x01D02000);
           paramSetTX0.srcBIdx    = 0;
           paramSetTX0.destBIdx   = 0;
           paramSetTX0.srcCIdx    = 0;
           paramSetTX0.destCIdx   = 0;
           paramSetTX0.aCnt       = 32;
           paramSetTX0.bCnt       = 1;
           paramSetTX0.cCnt       = 1;
           paramSetTX0.bCntReload = 0;
           paramSetTX0.linkAddr   = 0xFFFFu;
           paramSetTX0.opt = 0x00100000;

           result = EDMA3_DRV_setPaRAM(hEdma, chIdTX0, &paramSetTX0);
           if (result != EDMA3_DRV_SOK) {

               return result;

           }
           result = EDMA3_DRV_setPaRAM(hEdma, chIdTXLink0, &paramSetTX0);
           if (result != EDMA3_DRV_SOK) {
              return result;
           }

           result = EDMA3_DRV_linkChannel(hEdma, chIdTXLink0, chIdTXLink0);
           if (result != EDMA3_DRV_SOK) {
              return result;
           }


           result = EDMA3_DRV_linkChannel(hEdma, chIdTX0, chIdTXLink0);
           if (result != EDMA3_DRV_SOK) {
              return result;

           }

    ...I get transmitter underrun status on McASP as if something was wrong. Why is that?

    I would appreciate any feedback on that :). I can provide a full source code if you like.

    Remember that you have loaded paRAMs of both chIdTX0 and chIdTXLink0 with the same value first and then called the EDMA3_DRV_linkChannel() API which has modified only the linkAddr field of chIdTX0. Now this will make sure once the transfer in the chIdTX0 is complete, its paRAM gets reloaded with the paRAM of chIdTXLink0 which has the linkAddr field = 0xFFFFu. Now when this transfer is complete the paRAM is loaded with NULL as expected. This is a typical example of a single linking.

    But you want to achieve "continuous linking", and to do it logically, you should also link the chIdTX0Link0 to itself so that the linkAddr field of chIdTXLink0 is also pointing to chIdTXLink0.  

    So with the addition of the lines in green, your code should work properly.

     

    Regards,

    Sundaram