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.

L138 EDMA implementetion in sys/bios

Other Parts Discussed in Thread: SYSBIOS, OMAPL138

 Dear colleges

I'm try to implement SPI EDMA data receiving ftom external ADC. 

So, I need to start the transfers by GPIO event.

I found SPI EDMA example of psp. But it is example for read/write data to/from spi flash.I trying to rewrite this example for my needs, but is is not so easy as I thought before. 

Starterwere example looks more easy and understandable. Can I use StarterWare function for initialize and start SPI EDMA transactions in sys/bios ? Will it works correct?

  • Hi,

    Thanks for your post.

    Your understanding seems to be fine. That's a good idea to use starterware routines to be used for EDMA & SPI initialization and other EDMA transactions to be integrated in SYS/BIOS environment, but i would suggest you to ensure handling the EDMA & SPI interrupt setup code from starterware to SYSBIOS which would be more complex to handle. But, in my opinion SPI & EDMA initialization as well system configuration approach moving  from starterware code to SYSBIOS implementation would be fine to integrate.

    Thanks & regards,
    Sivaraj K

    -------------------------------------------------------------------------------------------------------

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

    -------------------------------------------------------------------------------------------------------

  •  Thank you Sivaraj!

    I create four PaRAM init function (one for transmit dummy byte, one for receive valid bytes from ADC and two linked PaRAM for Ping and Pong ParamSets)

    void edmaTxReload(void)
    {
    	unsigned int shadowRegionId = 1;	// Shadow region used for interrupts
    	unsigned int edmaTxChNum = 22;		// Ch22 is the GPIO Bank2 Event
    	unsigned int edmaTxEvtQNum = 0;		// Event Queue used
    	unsigned short edmaTxACnt = 1;		// 16 1-byte transmissions
    	unsigned short edmaBCnt = 16;		// 1 time transmission
    	unsigned short edmaCCnt = 128;		// 1 time transmission
    	unsigned short edmaTxSrcBIdx = 0;	// Don't want to change the src count offset
    	unsigned short edmaTxDesBIdx = 0;	// Don't want to change the destination count offset
    	unsigned short edmaTxSrcCIdx = 0;	// Don't want to change the src count offset
    	unsigned short edmaTxDesCIdx = 0;	// Don't want to change the destination count offset
    	unsigned short edmaBCntReload = 4;	// Don't want to reload B count
    	unsigned int dummyVal = 0xFF;
        volatile unsigned int *ds;
        unsigned int *sr;
        unsigned int i = 0;
    
    	// Set up DMA Tx channel ////////////////////////////////////////////////////////////
        // Associate DMA Channel to Event Queue
        HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_DMAQNUM((edmaTxChNum) >> 3u)) &=
                             EDMA3CC_DMAQNUM_CLR(edmaTxChNum);
    
        HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_DMAQNUM((edmaTxChNum) >> 3u)) |=
                      EDMA3CC_DMAQNUM_SET((edmaTxChNum), edmaTxEvtQNum);
    
    //    // Enable the Event Interrupt
    //    HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_IESR(shadowRegionId)) |= (0x01u <<  edmaTxChNum);
    
        HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_OPT(edmaTxChNum)) &= EDMA3CC_OPT_TCC_CLR;
        HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_OPT(edmaTxChNum)) |= EDMA3CC_OPT_TCC_SET(edmaTxChNum);
    
        /* Fill the PaRAM Set with transfer specific information */
        txParamSet.srcAddr    = (unsigned int)&dummyVal;
        txParamSet.destAddr   = (unsigned int)&HWREG(SOC_SPI_1_REGS + SPI_SPIDAT1);
    
        txParamSet.aCnt = edmaTxACnt;
        txParamSet.bCnt = edmaBCnt;
        txParamSet.cCnt = edmaCCnt;
    
        // Setting up the SRC/DES Index
        txParamSet.srcBIdx = edmaTxSrcBIdx;
        txParamSet.destBIdx = edmaTxDesBIdx;
            /* A Sync Transfer Mode */
        txParamSet.srcCIdx = edmaTxSrcCIdx;
        txParamSet.destCIdx = edmaTxDesCIdx;
    
    
        // 0x4000 is starting add.  8 32 bit register values per channel.  Using ch32.  So 8*4*32+0x4000 = 0x4400
        txParamSet.linkAddr = (unsigned short)0xFFFF;//0x4400;
        txParamSet.bCntReload = edmaBCntReload;
    
        // Initialize the options register
        txParamSet.opt = 0u;
    
        // Program the TCC
        txParamSet.opt |= ((edmaTxChNum << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);
    
    //    /* Enable Intermediate & Final transfer completion interrupt */
    //    paramSet.opt |= (1 << EDMA3CC_OPT_ITCINTEN_SHIFT);
    //    paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);
    
    	// Set for A-B synchronized transfer
    //    txParamSet.opt |= (1 << EDMA3CC_OPT_SYNCDIM_SHIFT);
        // End Set up DMA Tx channel ////////////////////////////////////////////////////////
    
        // Write the parameter set for origional Tx set
        sr = (unsigned int *)&txParamSet;
        ds = (unsigned int *)(SOC_EDMA30CC_0_REGS + EDMA3CC_OPT(edmaTxChNum));
    
        for(i=0; i < EDMA3CC_PARAM_ENTRY_FIELDS; i++)
        {
            *ds = *sr;
            ds++;
            sr++;
        }
    
        // clear SECR to clean any previous NULL request
        HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_SECR(shadowRegionId)) = (0x01u << edmaTxChNum);
    
        // clear EMCR to clean any previous NULL request
        HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_EMCR) |= (0x01u <<  edmaTxChNum);
    
        // (EESR) - set corresponding bit to enable DMA event
    	HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_EESR(shadowRegionId)) |= (0x01u <<  edmaTxChNum);
    }
    
    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;
    
    
        // Set up DMA Recv channel //////////////////////////////////////////////////////////
    
        
    
        // 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;
    
    
    	    // Set up DMA Recv channel //////////////////////////////////////////////////////////
    
    	  
    
    	    /* 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 PingSetParamNum = 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 //////////////////////////////////////////////////////////
    
    		   
    
    		    /* 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 , &PingParamSet);
    
    		       /* Enable the transfet */
    		       EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, PingSetParamNum , EDMA3_TRIG_MODE_EVENT);
    }

    So, now I just not sure, should I use

     // 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);

    just once for edmaRecvChNum = 18 , as implemented now in edmaRecvReload(), or I should call it for Ping and Pong PaRAM sets too?

    Can I be sure that after switching to new PaRAM set (to Ping or Pong PaRAM set ) EDMA will wake up by same event (SPI - event 18). I'm not sure now because in PaRAM sets of Ping and Pong transactions uses another channel numbers (64 linked to 65).

     or I something mixed?

  • Hi,

    Thanks for your update.

    Please check section 18.3.4.4 in omapl138 TRM from which, you could find example for ping pong buffering for McBSP ping and pong PaRAM sets. Kindly check Figure 18-28, 18-29, 18-30 & 18-31 in the TRM doc. below:

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

    Thanks & regards,

    Sivaraj K

  •  Sivaraj, I investigated TRM, thank you!

    I noticed that Ping and Pong ParamSets has different from McAsp ParamSet by  TCC number in OPT register. So, If I understood right, I can set any TCC number for my ParamSets of Ping/Pong, and pool suitable IPR[TCC] bit in application for cach event completion of filling the Ping or Pong buffer?

    So, channel number is matches the ParamSet, but TCC number not necessarily equal to Channel number. Is it correct?