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.

C6424 4ch McASP EDMA problems??

We are trying to implement 4 single channel DMA events to each of the corresponding McASP buffer (0-3). It seems the McASP DMA only contains either 1 DMA Channel AVETO or an 2 (even/odd) DMA channels. Is there a way to DMA one frame of data to one Transmit buffer independently. In our application we need to send 4 different audio frame sized data to different McASP channels, therefore each channel would trigger a corresponding DMA event at seperate times. Any ideas??

 

Kyle

  • Hello,

    There is no easy solution to this. The only two approach that I think MIGHT work are:

     

    1. Use QDMA. You can use interrupt to trigger QDMA. You then need to think about how to setup interrupt.

    2. Link transfers, but this way you are servicing the 4 channels one after another. Please see the EDMA user guide for more info.

  • Kyle,

    The fact and limitation of the McASP, as you noted, is that there is one event AXEVT0 to indicate that all active channels/serializers must be serviced.

    Paul's 2nd option is the one you need to use, but he meant to say to Chain transfers and not Link transfers.

    If I understand your goal, it is that there will be four (4) serializers used. These 4 serializers must all be transmitting or receiving simultaneously and must be synchronized to the AXEVT0 or AREVT0 event. But you want the four channels to be sending different frame sizes of data, even though the data will be sent at the same sample rate. For example, you might want channel 1 to be of length 64 from buffer1, channel 2 of length 256 from buffer2, and channels 3 & 4 of length 1024 from buffer3 & buffer4.

    Your solution is to have four DMA channels, each with its active/assigned PARAM set and also one or more Link PARAM sets. Channel A for serializer 1 will have to be channel AXEVT0 so that it will be triggered by the McASP peripheral.

    Channel A will transfer 1 word, with ACNT=4 BCNT=64 CCNT=1 SYNCDIM=ASYNC, and it will chain to Channel B, so TCC=B and ITCCHEN=1 and TCCHEN=1.

    Channel B will then immediately transfer 1 word, with ACNT=4 BCNT=256 CCNT=1 SYNCDIM=ASYNC, and it will chain to Channel C, so TCC=C and ITCCHEN=1 and TCCHEN=1.

    And so on for Channels C and D.

    When each DMA channel completes its frame, independently, you will want to have a Link PARAM set for that channel to load new transfer parameters. You can also have each DMA channel generate an interrupt when it completes a frame. These interrupts will be activated when that DMA channel's frame has been completed, and at the same time the new parameters will be copied from the Link PARAM set.

  • It seems that when I enable all McASP Serializers for transmit it will only generate an AXEVT0 event when they have all been written to using a single DMA. Is this correct or am I setting something up wrong?  I believe that the chaining is setup correctly and that all 4 DMAs are occuring (only when 1 serializer is enabled), but when I enable all serializers the first DMA never gets linked therefore it doesn't lets the chained DMAs occur. Another question I have is do I set the TCC equal to channel B or channel B's TCC?

    For better understanding I have 4 ping and 4 pong buffers. Each channel 0-3 have a ping and pong buffer.

    ping0 is set to CSL_EDMA3_CHA_AXEVT0.  

    ping0 is linked to pong0 and both have the same destination to McASP channel 0 and same size.

    ping0 should trigger ping1.

    ping1 is linked to pong1 and both have the same dest. McASP channel 1 and same size, however different size than ping0/pong0 and others.

    ping1 should trigger ping2.............

    If all four serializers are enabled the AXEVT0 event does not happen therefore the program sticks. If just channel 0 serializer is enabled the AXEVT0 works great and I can decode all four channels and fill all 4 channel's ping and pong buffers, however audio is only coming out of ch0 due to the fact that the rest are disabled.

    Help??

    Kyle

     

  •  Heres my edma init code:


     // Request the McASP0 TX EDMA channel (output DMA channel)
     edmaAudioOutCh0Ping   = EDMA3_DRV_HW_CHANNEL_MCASP0_TX;
     edmaAudioOutCh1Ping   = EDMA3_DRV_DMA_CHANNEL_ANY;
     edmaAudioOutCh2Ping   = EDMA3_DRV_DMA_CHANNEL_ANY;
     edmaAudioOutCh3Ping   = EDMA3_DRV_DMA_CHANNEL_ANY;
     
     
     // Also a link channel - get a link PaRAM set
     edmaAudioOutCh0Pong   = EDMA3_DRV_LINK_CHANNEL; // Any link ch
     edmaAudioOutCh1Pong   = EDMA3_DRV_LINK_CHANNEL; // Any link ch
     edmaAudioOutCh2Pong   = EDMA3_DRV_LINK_CHANNEL; // Any link ch
     edmaAudioOutCh3Pong   = EDMA3_DRV_LINK_CHANNEL; // Any link ch
     
     edmaAudioOutCh0PingLink  = EDMA3_DRV_LINK_CHANNEL; // Any link ch
     edmaAudioOutCh1PingLink  = EDMA3_DRV_LINK_CHANNEL; // Any link ch
     edmaAudioOutCh2PingLink  = EDMA3_DRV_LINK_CHANNEL; // Any link ch
     edmaAudioOutCh3PingLink  = EDMA3_DRV_LINK_CHANNEL; // Any link ch
      

     
     // Request the PING channel first
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh0Ping,
         &edmaTccPing0, (EDMA3_RM_EventQueue)1, &callbackCh0, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh1Ping,
         &edmaTccPing1, (EDMA3_RM_EventQueue)1, &callbackCh1, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh2Ping,
         &edmaTccPing2, (EDMA3_RM_EventQueue)1, &callbackCh2, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh3Ping,
         &edmaTccPing3, (EDMA3_RM_EventQueue)1, &callbackCh3, NULL );  
     
     // Check for valid return */
     if( edma3Result != EDMA3_DRV_SOK ){
        LOG_printf( &LOG_User, "PING channel request failed: %d",edma3Result );
      goto end;
      }
     
     // Request the PONG link channel
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh0Pong,
         &edmaTccPong0, (EDMA3_RM_EventQueue)0, &callbackCh0, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh1Pong,
         &edmaTccPong1, (EDMA3_RM_EventQueue)0, &callbackCh1, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh2Pong,
         &edmaTccPong2, (EDMA3_RM_EventQueue)0, &callbackCh2, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh3Pong,
         &edmaTccPong3, (EDMA3_RM_EventQueue)0, &callbackCh3, NULL );  
     // Check for valid return */
     if( edma3Result != EDMA3_DRV_SOK ){
        LOG_printf( &LOG_User, "PONG channel request failed failed: %d",
        edma3Result );
      goto end;
      }  
     
     // Request the PING link channel
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh0PingLink,
          &edmaTccPing0Link, (EDMA3_RM_EventQueue)1, &callbackCh0, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh1PingLink,
          &edmaTccPing1Link, (EDMA3_RM_EventQueue)1, &callbackCh1, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh2PingLink,
          &edmaTccPing2Link, (EDMA3_RM_EventQueue)1, &callbackCh2, NULL );
     edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutCh3PingLink,
          &edmaTccPing3Link, (EDMA3_RM_EventQueue)1, &callbackCh3, NULL );  
     // Check for valid return */
     if( edma3Result != EDMA3_DRV_SOK ){
        LOG_printf( &LOG_User, "PING link channel request failed: %d",
        edma3Result );
      goto end;
      } 
     
     // Configure the EDMA3 channels

    // Edit options (OPT) for PING
     edma3PaRAMVals0Ping.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, ENABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCCHEN, ENABLE ) // Enable ping0 chaining
              | CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCINTEN, DISABLE )
              | CSL_FMK(  EDMA3CC_OPT_TCC, edmaAudioOutCh1Ping )
              | CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
              | CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
              | CSL_FMKT( EDMA3CC_OPT_DAM, INCR )
              | CSL_FMKT( EDMA3CC_OPT_SAM, INCR );

     edma3PaRAMVals1Ping.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, ENABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCCHEN, ENABLE ) // Enable ping1 chaining
              | CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCINTEN, DISABLE )
              | CSL_FMK(  EDMA3CC_OPT_TCC, edmaAudioOutCh1Ping )
              | CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
              | CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
              | CSL_FMKT( EDMA3CC_OPT_DAM, INCR )
              | CSL_FMKT( EDMA3CC_OPT_SAM, INCR );

     edma3PaRAMVals2Ping.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, ENABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCCHEN, ENABLE ) // Enable ping2 chaining
              | CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCINTEN, DISABLE )
              | CSL_FMK(  EDMA3CC_OPT_TCC, edmaAudioOutCh3Ping )
              | CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
              | CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
              | CSL_FMKT( EDMA3CC_OPT_DAM, INCR )
              | CSL_FMKT( EDMA3CC_OPT_SAM, INCR );

     edma3PaRAMVals3Ping.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, ENABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCINTEN, DISABLE )
              | CSL_FMK(  EDMA3CC_OPT_TCC, edmaTccPing3 )
              | CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
              | CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
              | CSL_FMKT( EDMA3CC_OPT_DAM, INCR )
              | CSL_FMKT( EDMA3CC_OPT_SAM, INCR );
     
     // Edit options (OPT) for PONG
     edma3PaRAMVals0Pong.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCINTEN, DISABLE )
              | CSL_FMK( EDMA3CC_OPT_TCC, edmaTccPong0 )
              | CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
              | CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
              | CSL_FMKT( EDMA3CC_OPT_DAM, INCR )
              | CSL_FMKT( EDMA3CC_OPT_SAM, INCR );
     edma3PaRAMVals1Pong.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCINTEN, DISABLE )
              | CSL_FMK( EDMA3CC_OPT_TCC, edmaTccPong1 )
              | CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
              | CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
              | CSL_FMKT( EDMA3CC_OPT_DAM, INCR )
              | CSL_FMKT( EDMA3CC_OPT_SAM, INCR );
     edma3PaRAMVals2Pong.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCINTEN, DISABLE )
              | CSL_FMK( EDMA3CC_OPT_TCC, edmaTccPong2 )
              | CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
              | CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
              | CSL_FMKT( EDMA3CC_OPT_DAM, INCR )
              | CSL_FMKT( EDMA3CC_OPT_SAM, INCR );
      edma3PaRAMVals3Pong.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCCHEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
              | CSL_FMKT( EDMA3CC_OPT_TCINTEN, DISABLE )
              | CSL_FMK( EDMA3CC_OPT_TCC, edmaTccPong3 )
              | CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
              | CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
              | CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
              | CSL_FMKT( EDMA3CC_OPT_DAM, INCR )
              | CSL_FMKT( EDMA3CC_OPT_SAM, INCR );  
             
     
     /* Set the starting address for the transfers */
     // Starts with the PING buffer (skip sync bytes) 
     edma3PaRAMVals0Ping.SRC = ( Uint32 )&output0BufferPing;
     edma3PaRAMVals1Ping.SRC = ( Uint32 )&output1BufferPing;
     edma3PaRAMVals2Ping.SRC = ( Uint32 )&output2BufferPing;
     edma3PaRAMVals3Ping.SRC = ( Uint32 )&output3BufferPing; 
     
     // This one starts with the PONG buffer (skip sync bytes)
     edma3PaRAMVals0Pong.SRC = ( Uint32 )&output0BufferPong;
     edma3PaRAMVals1Pong.SRC = ( Uint32 )&output1BufferPong;
     edma3PaRAMVals2Pong.SRC = ( Uint32 )&output2BufferPong;
     edma3PaRAMVals3Pong.SRC = ( Uint32 )&output3BufferPong; 
     
     // Each MCASP EDMA transmit event moves 2 bytes (Uint16) per channel (ACNT)
     // for each of 4 (4 serial audio lines) channels (BCNT)
     edma3PaRAMVals0Ping.A_B_CNT = CSL_FMK( EDMA3CC_A_B_CNT_ACNT, 2 )
              | CSL_FMK( EDMA3CC_A_B_CNT_BCNT, 1 );
                      
     edma3PaRAMVals1Ping.A_B_CNT = CSL_FMK( EDMA3CC_A_B_CNT_ACNT, 2 )
              | CSL_FMK( EDMA3CC_A_B_CNT_BCNT, 1 );

      edma3PaRAMVals2Ping.A_B_CNT = CSL_FMK( EDMA3CC_A_B_CNT_ACNT, 2 )
              | CSL_FMK( EDMA3CC_A_B_CNT_BCNT, 1 );

     edma3PaRAMVals3Ping.A_B_CNT = CSL_FMK( EDMA3CC_A_B_CNT_ACNT, 2 )
              | CSL_FMK( EDMA3CC_A_B_CNT_BCNT, 1 );
     
     
     
     edma3PaRAMVals0Pong.A_B_CNT = edma3PaRAMVals0Ping.A_B_CNT;
     edma3PaRAMVals1Pong.A_B_CNT = edma3PaRAMVals1Ping.A_B_CNT;
     edma3PaRAMVals2Pong.A_B_CNT = edma3PaRAMVals2Ping.A_B_CNT;
     edma3PaRAMVals3Pong.A_B_CNT = edma3PaRAMVals3Ping.A_B_CNT;
     
     // Transfer starts with MCASP0_XBUF0
     edma3PaRAMVals0Ping.DST = CSL_MCASP_TXBUF_ADDR + 2;
     edma3PaRAMVals0Pong.DST = CSL_MCASP_TXBUF_ADDR + 2;
     edma3PaRAMVals1Ping.DST = CSL_MCASP_TXBUF_ADDR + 2 + 4; // Increase address by 32 bits or 4 bytes
     edma3PaRAMVals1Pong.DST = CSL_MCASP_TXBUF_ADDR + 2 + 4;
     edma3PaRAMVals2Ping.DST = CSL_MCASP_TXBUF_ADDR + 2 + 8;
     edma3PaRAMVals2Pong.DST = CSL_MCASP_TXBUF_ADDR + 2 + 8;
     edma3PaRAMVals3Ping.DST = CSL_MCASP_TXBUF_ADDR + 2 + 12;
     edma3PaRAMVals3Pong.DST = CSL_MCASP_TXBUF_ADDR + 2 + 12;
     
     // source and destination B indices
     // These are the distance in bytes between the start of
     // B-dimension transfers (size of output0Buffer
     edma3PaRAMVals0Ping.SRC_DST_BIDX = CSL_FMK( EDMA3CC_SRC_DST_BIDX_DSTBIDX, 0 ) 
                 | CSL_FMK( EDMA3CC_SRC_DST_BIDX_SRCBIDX, 0);
     edma3PaRAMVals0Pong.SRC_DST_BIDX = edma3PaRAMVals0Ping.SRC_DST_BIDX;
     
     edma3PaRAMVals1Ping.SRC_DST_BIDX = CSL_FMK( EDMA3CC_SRC_DST_BIDX_DSTBIDX, 0 ) 
                 | CSL_FMK( EDMA3CC_SRC_DST_BIDX_SRCBIDX, 0);
     edma3PaRAMVals1Pong.SRC_DST_BIDX = edma3PaRAMVals1Ping.SRC_DST_BIDX;
     
     edma3PaRAMVals2Ping.SRC_DST_BIDX = CSL_FMK( EDMA3CC_SRC_DST_BIDX_DSTBIDX, 0 ) 
                 | CSL_FMK( EDMA3CC_SRC_DST_BIDX_SRCBIDX, 0);
     edma3PaRAMVals2Pong.SRC_DST_BIDX = edma3PaRAMVals2Ping.SRC_DST_BIDX;
     
     edma3PaRAMVals3Ping.SRC_DST_BIDX = CSL_FMK( EDMA3CC_SRC_DST_BIDX_DSTBIDX, 0 ) 
                 | CSL_FMK( EDMA3CC_SRC_DST_BIDX_SRCBIDX, 0);
     edma3PaRAMVals3Pong.SRC_DST_BIDX = edma3PaRAMVals3Ping.SRC_DST_BIDX;
     

     // Set the source and destination C indices
     // C index is the distance between the beginning of consecutive frames
     // in the AB synchronized transfer
     edma3PaRAMVals0Ping.SRC_DST_CIDX = CSL_FMK( EDMA3CC_SRC_DST_CIDX_SRCCIDX, 2 )
                | CSL_FMK( EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0 );
               
     edma3PaRAMVals0Pong.SRC_DST_CIDX = edma3PaRAMVals0Ping.SRC_DST_CIDX;  
     
     edma3PaRAMVals1Ping.SRC_DST_CIDX = CSL_FMK( EDMA3CC_SRC_DST_CIDX_SRCCIDX, 2 )
                | CSL_FMK( EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0 );
               
     edma3PaRAMVals1Pong.SRC_DST_CIDX = edma3PaRAMVals1Ping.SRC_DST_CIDX;  

     edma3PaRAMVals2Ping.SRC_DST_CIDX = CSL_FMK( EDMA3CC_SRC_DST_CIDX_SRCCIDX, 2 )
                | CSL_FMK( EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0 );
               
     edma3PaRAMVals2Pong.SRC_DST_CIDX = edma3PaRAMVals2Ping.SRC_DST_CIDX;  

     edma3PaRAMVals3Ping.SRC_DST_CIDX = CSL_FMK( EDMA3CC_SRC_DST_CIDX_SRCCIDX, 2 )
                | CSL_FMK( EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0 );
               
     edma3PaRAMVals3Pong.SRC_DST_CIDX = edma3PaRAMVals3Ping.SRC_DST_CIDX;  

     /* CCNT remove sync data */
     edma3PaRAMVals0Ping.CCNT = 1152*2; // 1152 needs to be changed to channel type MPEG=1152
     edma3PaRAMVals0Pong.CCNT = edma3PaRAMVals0Ping.CCNT;
     
     edma3PaRAMVals1Ping.CCNT = 1152*2; // 1152 needs to be changed to channel type MPEG=1152
     edma3PaRAMVals1Pong.CCNT = edma3PaRAMVals1Ping.CCNT;
     
     edma3PaRAMVals2Ping.CCNT = 1152*2; // 1152 needs to be changed to channel type MPEG=1152
     edma3PaRAMVals2Pong.CCNT = edma3PaRAMVals2Ping.CCNT;
     
     edma3PaRAMVals3Ping.CCNT = 1152*2; // 1152 needs to be changed to channel type MPEG=1152
     edma3PaRAMVals3Pong.CCNT = edma3PaRAMVals3Ping.CCNT;
      
     // Now, configure the actual EDMA PARAM sets
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh0Ping,
       ( const EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals0Ping );  
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh1Ping,
       ( const EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals1Ping );  
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh2Ping,
       ( const EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals2Ping );  
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh3Ping,
       ( const EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals3Ping );  
      
     if( edma3Result != EDMA3_DRV_SOK )
       {
       LOG_printf( &LOG_User, "Configuring PING PARAM failed, %d",
          edma3Result );
      goto end;  
       }
     
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh0Pong,
       ( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals0Pong );
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh1Pong,
       ( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals1Pong );
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh2Pong,
       ( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals2Pong );
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh3Pong,
       ( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals3Pong );  
     
     if( edma3Result != EDMA3_DRV_SOK )
       {
       LOG_printf( &LOG_User, "Configuring PONG PARAM failed, %d",
          edma3Result );
      goto end;  
       }   
     
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh0PingLink,
       ( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals0Ping ); 
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh1PingLink,
       ( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals1Ping ); 
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh2PingLink,
       ( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals2Ping ); 
     edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutCh3PingLink,
       ( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMVals3Ping ); 
     
     
     // Link the  parameter sets to each other
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh0Ping,
           edmaAudioOutCh0Pong ); 
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh1Ping,
           edmaAudioOutCh1Pong ); 
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh2Ping,
           edmaAudioOutCh2Pong ); 
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh3Ping,
           edmaAudioOutCh3Pong ); 
           
     if( edma3Result != EDMA3_DRV_SOK )
       {
       LOG_printf( &LOG_User, "Linking PING to PONG failed, %d",
          edma3Result );
      goto end;  
       }
     
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh0Pong,
           edmaAudioOutCh0PingLink );    
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh1Pong,
           edmaAudioOutCh1PingLink );    
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh2Pong,
           edmaAudioOutCh2PingLink );    
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh3Pong,
           edmaAudioOutCh3PingLink );           
     
     if( edma3Result != EDMA3_DRV_SOK )
       {
       LOG_printf( &LOG_User, "Linking PONG to PING link failed, %d",
          edma3Result );
      goto end;  
       }
     
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh0PingLink,
           edmaAudioOutCh0Pong );
           
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh1PingLink,
           edmaAudioOutCh1Pong );
     
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh2PingLink,
           edmaAudioOutCh2Pong );
     
     edma3Result = EDMA3_DRV_linkChannel( hEdma,
           edmaAudioOutCh3PingLink,
           edmaAudioOutCh3Pong );
     
     if( edma3Result != EDMA3_DRV_SOK ){
       LOG_printf( &LOG_User, "Linking PING link to PONG failed, %d",edma3Result );
      goto end;  
       }
         
     // Chain Ping0 to Ping1 then Ping1 to Ping2 then Ping2 to Ping3
     edmaChainOpts0.tcchEn  = EDMA3_DRV_TCCHEN_EN;  // this will turn ON chaining
     edmaChainOpts0.tcintEn  = EDMA3_DRV_TCINTEN_DIS; // this will turn OFF ints

     edmaChainOpts1.tcchEn  = EDMA3_DRV_TCCHEN_EN;  // this will turn ON chaining
     edmaChainOpts1.tcintEn  = EDMA3_DRV_TCINTEN_DIS; // this will turn OFF ints
     
     edmaChainOpts2.tcchEn  = EDMA3_DRV_TCCHEN_EN;  // this will turn ON chaining
     edmaChainOpts2.tcintEn  = EDMA3_DRV_TCINTEN_DIS; // this will turn OFF ints
     
     edma3Result = EDMA3_DRV_chainChannel(hEdma, edmaAudioOutCh0Ping,
                  edmaAudioOutCh1Ping, &edmaChainOpts0);      
     
     edma3Result = EDMA3_DRV_chainChannel(hEdma, edmaAudioOutCh1Ping,
                  edmaAudioOutCh2Ping, &edmaChainOpts1);
                 
     edma3Result = EDMA3_DRV_chainChannel(hEdma, edmaAudioOutCh2Ping,
                  edmaAudioOutCh3Ping, &edmaChainOpts2);
                 
     if( edma3Result != EDMA3_DRV_SOK ){
        LOG_printf( &LOG_User, "Chaining FAILED, %d", edma3Result );
      goto end;  
       }
                 
                 
     edma3Result = EDMA3_DRV_getPaRAMPhyAddr ( hEdma, edmaAudioOutCh0Ping,
           &edmaPaRAMAddr0 );
     
     edma3Result = EDMA3_DRV_getPaRAMPhyAddr ( hEdma, edmaAudioOutCh1Ping,
           &edmaPaRAMAddr1 );
     
     edma3Result = EDMA3_DRV_getPaRAMPhyAddr ( hEdma, edmaAudioOutCh2Ping,
           &edmaPaRAMAddr2 );
     
     edma3Result = EDMA3_DRV_getPaRAMPhyAddr ( hEdma, edmaAudioOutCh3Ping,
           &edmaPaRAMAddr3 );
          
     edmaChannel0Params =  ( EDMA3_DRV_PaRAMRegs * )edmaPaRAMAddr0;
     edmaChannel1Params =  ( EDMA3_DRV_PaRAMRegs * )edmaPaRAMAddr1;
     edmaChannel2Params =  ( EDMA3_DRV_PaRAMRegs * )edmaPaRAMAddr2;
     edmaChannel3Params =  ( EDMA3_DRV_PaRAMRegs * )edmaPaRAMAddr3;

         
      if( edma3Result != EDMA3_DRV_SOK )
       {
       LOG_printf( &LOG_User, "Getting paRAMPhyAddr failed, %d",
          edma3Result );
      goto end;  
       }      
     
     // Start the EDMA

     EDMA3_DRV_enableTransfer( hEdma, edmaAudioOutCh0Ping, EDMA3_DRV_TRIG_MODE_EVENT );
     EDMA3_DRV_enableTransfer( hEdma, edmaAudioOutCh1Ping, EDMA3_DRV_TRIG_MODE_EVENT );
     EDMA3_DRV_enableTransfer( hEdma, edmaAudioOutCh2Ping, EDMA3_DRV_TRIG_MODE_EVENT );
     EDMA3_DRV_enableTransfer( hEdma, edmaAudioOutCh3Ping, EDMA3_DRV_TRIG_MODE_EVENT );

     // Clear any error flags from XSTAT
     mcasp0Regs->XSTAT = 0xFFFF;
      
     // Take the Serializers out of reset
     CSL_FINST( mcasp0Regs->SRCTL0, MCASP_SRCTL0_SRMOD, XMT );
    // CSL_FINST( mcasp0Regs->SRCTL1, MCASP_SRCTL1_SRMOD, XMT );
    // CSL_FINST( mcasp0Regs->SRCTL2, MCASP_SRCTL2_SRMOD, XMT );
    // CSL_FINST( mcasp0Regs->SRCTL3, MCASP_SRCTL3_SRMOD, XMT );

  • Kyle, 

    Please confirm the XBUSEL register setting.  I think in your set-up you need to access the XRBUF registers directly - see 2.8.1.3 Transfers Through the Configuration Bus (CFG)

     

    XBUSEL Selects whether writes to serializer buffer XRBUF[n] originate from the configuration bus (CFG) or the data (DAT) port.

    0 Writes to XRBUF[n] originate from the data port. Writes to XRBUF[n] from the configuration bus are ignored with no effect to the McASP.

    1 Writes to XRBUF[n] originate from the configuration bus. Writes to XRBUF[n] from the data port are ignored with no effect to the McASP.

     

     

  • Didn't work. Here is the McASP init code I'm using. Please provide reference to this code if there is any items that might need to be changed. I will continue to look for possible solutions in the McASP user guide.

     /* Set up MCASP0 */
     // First, reset the peripheral
     mcasp0Regs->GBLCTL  = 0L; // 0 is reset default, resets everything
     
     // PFUNC should be OK in reset configuration, but make sure
     mcasp0Regs->PFUNC = 0L; // all bits are cleared
     
     // Set the pin directions
     mcasp0Regs->PDIR = CSL_FMKT( MCASP_PDIR_AFSX, INPUT )    //was OUTPUT
                                              | CSL_FMKT( MCASP_PDIR_ACLKX, INPUT )    //was OUTPUT
                                              | CSL_FMKT( MCASP_PDIR_AXR3, OUTPUT )
                                              | CSL_FMKT( MCASP_PDIR_AXR2, OUTPUT )
                                              | CSL_FMKT( MCASP_PDIR_AXR1, OUTPUT )
                                              | CSL_FMKT( MCASP_PDIR_AXR0, OUTPUT )
                                              | CSL_FMKT( MCASP_PDIR_AMUTE, OUTPUT );

     mcasp0Regs->AMUTE = CSL_FMKT( MCASP_AMUTE_MUTEN, ERRLOW ); // MUTE on 
          
     // MPEG2 decoder puts out 16-bit samples     
     mcasp0Regs->XMASK = 0xFFFF; 
     
     // Transmit bit stream format Register (XFMT)
     mcasp0Regs->XFMT = CSL_FMKT( MCASP_XFMT_XDATDLY, 0BIT )
                                              | CSL_FMKT( MCASP_XFMT_XRVRS, MSBFIRST )
                                              | CSL_FMKT( MCASP_XFMT_XSSZ, 32BITS )
                                              | CSL_FMKT( MCASP_XFMT_XBUSEL, VBUS )
                                              | CSL_FMKT( MCASP_XFMT_XROT, 16BITS );
          
     // Transmit Frame Sync Control Register (AFSXCTL)
     mcasp0Regs->AFSXCTL = CSL_FMK( MCASP_AFSXCTL_XMOD, 2 )   // TDM mode
                                                     | CSL_FMKT( MCASP_AFSXCTL_FXWID, WORD ) 
                                                     | CSL_FMKT( MCASP_AFSXCTL_FSXM, EXTERNAL); //was INTERNAL
                 
     //mcasp0Regs->XINTCTL = CSL_FMKT( MCASP_XINTCTL_XDATA, ENABLE );
     
     // Serializer control registers 0-3
     CSL_FINST( mcasp0Regs->SRCTL0, MCASP_SRCTL0_SRMOD, INACTIVE );
     CSL_FINST( mcasp0Regs->SRCTL1, MCASP_SRCTL1_SRMOD, INACTIVE );
     CSL_FINST( mcasp0Regs->SRCTL2, MCASP_SRCTL2_SRMOD, INACTIVE );
     CSL_FINST( mcasp0Regs->SRCTL3, MCASP_SRCTL3_SRMOD, INACTIVE );
     
     // Transmit clock control register (ACLKXCTL)
     mcasp0Regs->ACLKXCTL = CSL_FMKT( MCASP_ACLKXCTL_CLKXP, FALLING)
                                                        | CSL_FMKT( MCASP_ACLKXCTL_ASYNC, ASYNC )
                                                        | CSL_FMKT( MCASP_ACLKXCTL_CLKXM, EXTERNAL ) //was INTERNAL
                                                        | CSL_FMK( MCASP_ACLKXCTL_CLKXDIV, 0 );   //was 9 
                                                       // MCASP bit clock is (SYSCLK3/(AHCLKDIV+1))/(CLKDIV+1) 
                                                       // Configure MCASP bit clock for 3.3 MHz
            
     // Transmit HF Clock Control Register (AHCLKXCTL)
     // AHCLKX (and AHCLKR) must be < 40 MHz
     // AHCLKX = SYSCLK3/(AHCLKXDIV+1)
     mcasp0Regs->AHCLKXCTL = CSL_FMKT( MCASP_AHCLKXCTL_HCLKXM, INTERNAL )
                                                           | CSL_FMKT( MCASP_AHCLKXCTL_HCLKXP, RISING )
                                                           | CSL_FMK( MCASP_AHCLKXCTL_HCLKXDIV, 2 );
                                                            // AHCLK will be 33 MHz for SYSCLK1 = 594 MHz 
            
            
     /* The following is taken from the MCASP User's Guide, (SPRUEN1C): Section 2.10.2*/
     // Enable the high-frequency transmit clock for further configuration
     mcasp0Regs->GBLCTL = CSL_FMKT( MCASP_GBLCTL_XHCLKRST, ACTIVE );
     
     // Make sure the HF clock is out of reset      
     while( !CSL_FEXT( mcasp0Regs->GBLCTL, MCASP_GBLCTL_XHCLKRST ) );
     
     // Now thake the serial clock out of reset
     CSL_FINST( mcasp0Regs->GBLCTL, MCASP_GBLCTL_XCLKRST, ACTIVE );
     
     // Read back to make sure it is latched
     while( !CSL_FEXT( mcasp0Regs->GBLCTL, MCASP_GBLCTL_XCLKRST ) );
     
     /* Configure the transmit clock check register
       We are running with an internal clock, so it seems that
         the clock failure detection shouldn't be needed, but here it is. */
     mcasp0Regs->XCLKCHK = CSL_FMK( MCASP_XCLKCHK_XMAX, 255 )
                                                       | CSL_FMK( MCASP_XCLKCHK_XMIN, 0 )
                                                       | CSL_FMKT( MCASP_XCLKCHK_XCKFAILSW, DISABLE )
                                                       | CSL_FMKT( MCASP_XCLKCHK_XPS, DIVBY2 );

     while( CSL_FEXT(mcasp0Regs->XSTAT, MCASP_XSTAT_XCKFAIL)){
       // Clear XCKFAIL
       CSL_FINST( mcasp0Regs->XSTAT, MCASP_XSTAT_XCKFAIL, YES );
       TSK_sleep( 1 ); // Sleep for 1 clock tick (1 mS)
       }
     
     // Set the TDM time slot register to own slots 0-1
     mcasp0Regs->XTDM = CSL_FMKT( MCASP_XTDM_XTDMS0, ACTIVE )
                                              | CSL_FMKT( MCASP_XTDM_XTDMS1, ACTIVE );

     /* With the MCASP configured, but held in reset, set up EDMA */
     

  • UPDATE:

    Working test: I have one serializer enabled, two decoder filling buffers, with two DMA PSET to source of each set to one of the two decoded buffers. I've got a DMA that services the AXEVTO event to the mcasp port. Audio come out clean!! Another DMA is chained, intermediate, from the first DMA (DMA0). The destination address is some specified register I can monitor. I can see it update continuously a 4byte value (this means my chaining is correct). I tried to mimic what the Mcasp will see. Just one channel of audio is coming out which should happen.

    Now I enable the 2nd channel serializer. Therefore I must write, two 32 bit values into the Mcasp register if accessing through the data port, correct?

    I specify the destination address of the 2nd  DMA to the mcasp register. Therefore, after every 4byte DMA by DMA0 this DMA must send 4bytes (both have the same destination).  In theory the mcasp register should be seeing two 4 byte transfers every AXEVTO. However, for some reason the AXEVTO is not occuring. Remember, I had just verified the chaining was working correctly.

     

    Can the mcasp register only be accessed by the MCASP DMA channel?? Or can any DMA channel access this address?

    Please help.

    Kyle

     

  • Kyle Rottmann said:
    Can the mcasp register only be accessed by the MCASP DMA channel?? Or can any DMA channel access this address?

    Any DMA channel can access the McASP data port address, which is what I assume you mean by "McASP register".

    Here's an "easy" way to figure out if the DMA is working for you.

    1. I assume that you have ACNT=4, BCNT=1, ABSYNC, DST=McASP Data Port address not Config Port address.
    2. Leave the second DMA channel the way you have it for the single channel test.
    3. Change to BCNT=2 and confirm that DSTBIDX=SRCBIDX=0.
    4. Enable both serializers and see if you get the same audio out both channels and consistent AXEVT0's.

    If it does NOT work, look at the McASP status registers and the EDMA status registers to see what they think is going on.

    To debug further, the easiest way to figure out what is happening in the EDMA is to do the following:

    • I assume nothing else is using EDMA resources right now, so we own the whole PARAM; if not, do the best you can.
    • Change the code to assign ALL of the ping and pong and ping-link channels sequentially rather than using CHANNEL_ANY.
    • Confirm what values are allocated for those channels and that they are in order as written in your code.
    • In CCS, open a Memory Window on the PARAM starting with the PARAM assigned to the first channel, 0x01C04180.
    • Change the display format to "TI 32-bit hex" to get rid of the 0x (less space) and widen the window to show 8 words per line.
    • Stretch the height of the window to show all of the PARAMs being used.
    • Stop at a breakpoint just before enabling any of the McASP serializers, and get a screen shot of the memory window.
    • Run it, stop it, and get another screen shot of the memory window.
    • Paste those to a forum reply so we can try to figure out what the EDMA has done.