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.

EDMA Linking mode for ping-pong buffering

Other Parts Discussed in Thread: OMAPL138

 Hi All!

I learned how to use EDMA in Linking mode.

I want to receive 2048 bytes by SPI continuously into the ping-pong buffer by EDMA Linking mode. I investigated Technical Reference manual for L138 and now I have just one question. 

In use four ParamSet: one for dummy SPI transmission, one for SPI receive and two linked Paramset for ping and pong buffers filling. For each ParamSet initialization I created function which is called once in the EDMA initialization routine.

My ParamSet init functions:

void edmaRecvReload(void)
{
	unsigned int shadowRegionId = 1;	// Shadow region used for interrupts
	unsigned int edmaRecvChNum = 18;	// Ch18 is SPI1 Receive Event
	unsigned int edmaTxEvtQNum = 0;		// Event Queue used
	unsigned short edmaRecvACnt = 1;		// 2048 1-byte transmissions
	unsigned short edmaBCnt = 2048;		// 1 time transmission
	unsigned short edmaCCnt = 1;		// 1 time transmission
	unsigned short edmaRecvSrcBIdx = 0;	// Don't want to change the src count offset
	unsigned short edmaRecvDesBIdx = 1;	// Increment on destination count offset by one byte
	unsigned short edmaRecvSrcCIdx = 0;	// Don't want to change the src count offset
	unsigned short edmaRecvDesCIdx = 0;	// Don't want to change the destination count offset
	unsigned short edmaBCntReload = 0;	// Don't want to reload B count
    unsigned int writeAddr;
    volatile unsigned int *ds;
    unsigned int *sr;
    unsigned int i = 0;

    // Set up DMA Recv channel //////////////////////////////////////////////////////////

    //getWriteBufferAddr(&writeAddr);

    // Associate DMA Channel to Event Queue
    HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_DMAQNUM((edmaRecvChNum) >> 3u)) &=
                         EDMA3CC_DMAQNUM_CLR(edmaRecvChNum);

    HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_DMAQNUM((edmaRecvChNum) >> 3u)) |=
                  EDMA3CC_DMAQNUM_SET((edmaRecvChNum), edmaTxEvtQNum);

    // Enable the Event Interrupt
    HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_IESR(shadowRegionId)) |= (0x01u <<  edmaRecvChNum);

    HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_OPT(edmaRecvChNum)) &= EDMA3CC_OPT_TCC_CLR;
    HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_OPT(edmaRecvChNum)) |= EDMA3CC_OPT_TCC_SET(edmaRecvChNum);

    /* Fill the PaRAM Set with transfer specific information */
    recvParamSet.srcAddr    = (unsigned int)&HWREG(SOC_SPI_1_REGS + SPI_SPIBUF);
    recvParamSet.destAddr   = (unsigned int)&PingBuf;

    recvParamSet.aCnt = edmaRecvACnt;
    recvParamSet.bCnt = edmaBCnt;
    recvParamSet.cCnt = edmaCCnt;

    // Setting up the SRC/DES Index
    recvParamSet.srcBIdx = edmaRecvSrcBIdx;
    recvParamSet.destBIdx = edmaRecvDesBIdx;
        /* A Sync Transfer Mode */
    recvParamSet.srcCIdx = edmaRecvSrcCIdx;
    recvParamSet.destCIdx = edmaRecvDesCIdx;


    // 0x4000 is starting add.  8 32 bit register values per channel.  Using ch32.  So 8*4*32+0x4000 = 0x4400
    recvParamSet.linkAddr = (unsigned short)0x4800;
    recvParamSet.bCntReload = edmaBCntReload;

    // Initialize the options register
    recvParamSet.opt = 0u;
    /* Enable Final transfer completion interrupt */
     recvParamSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);
    // Program the TCC
    recvParamSet.opt |= ((edmaRecvChNum << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);

//    /* Enable Intermediate & Final transfer completion interrupt */
//    paramSet.opt |= (1 << EDMA3CC_OPT_ITCINTEN_SHIFT);
//	recvParamSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);

	// Set for A-B synchronized transfer
//    txParamSet.opt |= (1 << EDMA3CC_OPT_SYNCDIM_SHIFT);
    // End Set up DMA Recv channel //////////////////////////////////////////////////////
    /* configure PaRAM Set */

    	    EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, edmaRecvChNum , &PongParamSet);

    	    /* Enable the transfer */
    	    EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, edmaRecvChNum , EDMA3_TRIG_MODE_EVENT);


}


void Pong_ParamSet_init(void)
{
	unsigned int shadowRegionId = 1;	// Shadow region used for interrupts
		unsigned int PongSetParamNum = 64;	// Set 64 linked to Set 65
		unsigned int edmaTxEvtQNum = 0;		// Event Queue used
		unsigned short edmaRecvACnt = 1;		// 2048 1-byte transmissions
		unsigned short edmaBCnt = 2048;		// 1 time transmission
		unsigned short edmaCCnt = 1;		// 1 time transmission
		unsigned short edmaRecvSrcBIdx = 0;	// Don't want to change the src count offset
		unsigned short edmaRecvDesBIdx = 1;	// Increment on destination count offset by one byte
		unsigned short edmaRecvSrcCIdx = 0;	// Don't want to change the src count offset
		unsigned short edmaRecvDesCIdx = 0;	// Don't want to change the destination count offset
		unsigned short edmaBCntReload = 0;	// Don't want to reload B count
	    unsigned int writeAddr;
	    volatile unsigned int *ds;
	    unsigned int *sr;
	    unsigned int i = 0;

	    // Set up DMA Recv channel //////////////////////////////////////////////////////////

	   // getWriteBufferAddr(&writeAddr);

	    /* Fill the PaRAM Set with transfer specific information */
	    PongParamSet.srcAddr    = (unsigned int)&HWREG(SOC_SPI_1_REGS + SPI_SPIBUF);
	    PongParamSet.destAddr   = (unsigned int)&PongBuf;

	    PongParamSet.aCnt = edmaRecvACnt;
	    PongParamSet.bCnt = edmaBCnt;
	    PongParamSet.cCnt = edmaCCnt;

	    // Setting up the SRC/DES Index
	    PongParamSet.srcBIdx = edmaRecvSrcBIdx;
	    PongParamSet.destBIdx = edmaRecvDesBIdx;
	        /* A Sync Transfer Mode */
	    PongParamSet.srcCIdx = edmaRecvSrcCIdx;
	    PongParamSet.destCIdx = edmaRecvDesCIdx;


	    // 0x4000 is starting add.  8 32 bit register values per channel.  Using ch32.  So 8*4*32+0x4000 = 0x4400
	    PongParamSet.linkAddr = (unsigned short)0x4820;
	    PongParamSet.bCntReload = edmaBCntReload;

	    // Initialize the options register
	    PongParamSet.opt = 0u;
	    /* Enable Final transfer completion interrupt */
	   //
	   PongParamSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);   //Im NOT SURE!!!
	    // Program the TCC
	    PongParamSet.opt |= ((18 << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);  //interrupt from chan18 after completion Im NOT SURE!!!

	    /* configure PaRAM Set */
	    EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, PongSetParamNum , &PongParamSet);

	    /* Enable the transfet */
	    EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, PongSetParamNum , EDMA3_TRIG_MODE_EVENT);
}

void Ping_ParamSet_init(void)

{

	unsigned int shadowRegionId = 1;	// Shadow region used for interrupts
			unsigned int PongSetParamNum = 65;	// Set 65 linked to Set 64
			unsigned int edmaTxEvtQNum = 0;		// Event Queue used
			unsigned short edmaRecvACnt = 1;		// 2048 1-byte transmissions
			unsigned short edmaBCnt = 2048;		// 1 time transmission
			unsigned short edmaCCnt = 1;		// 1 time transmission
			unsigned short edmaRecvSrcBIdx = 0;	// Don't want to change the src count offset
			unsigned short edmaRecvDesBIdx = 1;	// Increment on destination count offset by one byte
			unsigned short edmaRecvSrcCIdx = 0;	// Don't want to change the src count offset
			unsigned short edmaRecvDesCIdx = 0;	// Don't want to change the destination count offset
			unsigned short edmaBCntReload = 0;	// Don't want to reload B count
		    unsigned int writeAddr;
		    volatile unsigned int *ds;
		    unsigned int *sr;
		    unsigned int i = 0;

		    // Set up DMA Recv channel //////////////////////////////////////////////////////////

		   // getWriteBufferAddr(&writeAddr);

		    /* Fill the PaRAM Set with transfer specific information */
		    PingParamSet.srcAddr    = (unsigned int)&HWREG(SOC_SPI_1_REGS + SPI_SPIBUF);
		    PingParamSet.destAddr   = (unsigned int)&PingBuf;

		    PingParamSet.aCnt = edmaRecvACnt;
		    PingParamSet.bCnt = edmaBCnt;
		    PongParamSet.cCnt = edmaCCnt;

		    // Setting up the SRC/DES Index
		    PingParamSet.srcBIdx = edmaRecvSrcBIdx;
		    PingParamSet.destBIdx = edmaRecvDesBIdx;
		        /* A Sync Transfer Mode */
		    PingParamSet.srcCIdx = edmaRecvSrcCIdx;
		    PingParamSet.destCIdx = edmaRecvDesCIdx;


		    // 0x4000 is starting add.  8 32 bit register values per channel.  Using ch32.  So 8*4*32+0x4000 = 0x4400
		    PingParamSet.linkAddr = (unsigned short)0x4800;
		    PingParamSet.bCntReload = edmaBCntReload;

		    // Initialize the options register
		    PingParamSet.opt = 0u;
		    /* Enable Final transfer completion interrupt */
		    //
		     PingParamSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);   // Im NOT SURE!!!

		    // Program the TCC
		    PingParamSet.opt |= ((18 << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);  //interrupt from chan18 after completion Im NOT SURE!!!

		    /* configure PaRAM Set */
		       EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, PingSetParamNum , &PongParamSet);

		       /* Enable the transfet */
		       EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, PingSetParamNum , EDMA3_TRIG_MODE_EVENT);
}

 I market places when Im not sure in the code. So, my questiuon: can I set TCINTEN to 1 and TCC to 18 in the Ping and Pong ParamSets?

 Why Im not sure: Tech. ref. manual has Ping Pong buffering example (18.4.4.4). There use ParamSet64 and ParamSet65 (Pong and Ping) with TCINTEN = 0. Only in ParamSet of channel 3 (McBSP receive) used TCINTEN=1. I want to generate interrupt after each ping/pong filling, therefore I set TCINTEN to 1 and TCC to 18 in each ParamSet for generate same interrupt for each filling of ping and pong.

 Is it correct?

 

  • Hi Dmitry,

    Thanks for your post.

    Yes, you are right and you should set the TCINTEN bit to 1 to generate an interrupt after completion of each ping/pong buffer filling. Generally, in ping pong buffering, the channel OPT, CNT values (A, B, C) and IDX values would all be same between the ping and pong parameters for each channel except the link address & address of the data buffer.

    Please note that the DMA channel will be initially loaded with the ping parameters and the link address for the ping buffer set will be set to the PaRAM offset of the pong parameter set, likewise, the link address for the pong buffer set will be set the the PaRAM offset of the ping parameter set.

    Basically, you can assign the edma channel number you use for Rx. & Tx. in the code to TCC value for each Param Set to generate interrupt after filling of ping/pong buffer.

    Thanks & regards,
    Sivaraj K

    -------------------------------------------------------------------------------------------------------
    Please click the Verify Answer button on this post if it answers your question.
    --------------------------------------------------------------------------------------------------------
  •  Thank you, Sivaraj!

    Please, describe me what do you mean as ParamSet offset. 

    As you can see above I use ParamSet64 for Ping transaction and link 0x4820 as adress to ParamSet65. In ParamSet65 used link adress 0x4800 as adress of ParamSet64.

     So, ParamSets is bouncing from ParamSet64(adress 4800) and ParamSet65(adress 4820). Differ between ParamSet64 and ParamSet65 only in the link adress, other parameters the same.

     What is offset which you mentioned?

  • Hi Dimitry,
    Thanks for your update.

    The offset which i mean is the link address/B count reload parameter (LINK_BCNTRLD) specifies the byte address offset in the PaRAM from which the EDMA3CC loads/reloads the next PaRAM set during linking and the value used to reload the BCNT field in the A count/B count parameter (A_B_CNT) once the last array in the 2nd dimension is transferred.

    Please refer Table 18-14 for EDMA3 CC for parameter RAM (PaRAM) entries to know more on offset for each parameter in the omapl138 TRM as below:

    http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf

    The offset of LINK_BCNTRLD (Link Address/B count reload) is 14h

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------
    Please click the Verify Answer button on this post if it answers your question.
    -------------------------------------------------------------------------------------------------------

     

  •  Thanks! It was helpfull!