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.

EDMA3 Transfer Complete Interrupt not Triggering

Other Parts Discussed in Thread: OMAPL138

I am using EDMA3 to make transfers on the SPI0 peripheral (in loopback mode) on OMAP L138. I'm working with CSLR. The transfer works fine and I see the correct data being received.

Next I configured the INTC to interrupt the DSP based on the example at "\pspdrivers_02_10_01\packages\ti\psp\cslr\evmOMAPL138\examples\intc". The EDMA3 transfers are configured to raise an interrupt on completion.

The interrupt being triggered is the one corresponding to "CSL_INTC_EVENTID_EDMA3_0_CC0_ERRINT" (# 56) and not "CSL_INTC_EVENTID_EDMA3_0_CC0_INT1" (# 8) in the "soc_OMAPL138.h". This is strange because when I check CCERR at EDMA3, it's 0 and IPR is 0x0000C000. I can see my interrupt routine being triggered when I use event 56 instead of 8.

The state of some registers before and after triggering the EDMA3 transfer:

BEFORE:
dmaRegs->IPR = 0x00000000
dmaRegs->IER = 0x0000C000
dmaRegs->EER = 0x0000C000
dmaRegs->EMR = 0
dmaRegs->CCERR = 0
intcRegs->EVTFLAG[0] = 0x0000001D
intcRegs->EVTFLAG[1] = 0x00000000
intcRegs->EVTFLAG[2] = 0x00000021
intcRegs->EVTFLAG[3] = 0x00000001
intcRegs->INTMUX2 = 0x0B0A0908
intcRegs->EVTMASK[0] = 0x0000000F
intcRegs->EVTMASK[1] = 0x00000000
intcRegs->EVTMASK[2] = 0x00000000
intcRegs->EVTMASK[3] = 0x00000000

AFTER:
dmaRegs->IPR = 0x0000C000
dmaRegs->IER = 0x0000C000
dmaRegs->EER = 0x0000C000
dmaRegs->EMR = 0
dmaRegs->CCERR = 0
intcRegs->EVTFLAG[0] = 0x0000001F
intcRegs->EVTFLAG[1] = 0x01000000
intcRegs->EVTFLAG[2] = 0x00000021
intcRegs->EVTFLAG[3] = 0x00000001
intcRegs->INTMUX2 = 0x0B0A0908
intcRegs->EVTMASK[0] = 0x0000000F
intcRegs->EVTMASK[1] = 0x00000000
intcRegs->EVTMASK[2] = 0x00000000
intcRegs->EVTMASK[3] = 0x00000000

And the source code:

#include <stdio.h> #include <c6x.h> #include <ti/psp/cslr/soc_OMAPL138.h> #include <ti/psp/cslr/cslr_spi.h> #include <ti/psp/cslr/cslr_edma3cc.h> #include <ti/psp/cslr/cslr_psc_OMAPL138.h> #include <ti/psp/cslr/cslr_dspintc.h> #define NO_DMA 0 #define SPI_BITS_PER_TX 8 #define SPI_BITS_PER_RX 8 #define SPI_BYTES_PER_TX (SPI_BITS_PER_TX>>3) #define SPI_BYTES_PER_RX (SPI_BITS_PER_RX>>3) #define SPI0_TX_PARAM CSL_EDMA3_CHA_SPI0_TX #define SPI0_RX_PARAM CSL_EDMA3_CHA_SPI0_RX #define BCNT_SHIFT CSL_EDMA3CC_A_B_CNT_BCNT_SHIFT #define BCNTRLD_SHIFT CSL_EDMA3CC_LINK_BCNTRLD_BCNTRLD_SHIFT #define DSTBIDX_SHIFT CSL_EDMA3CC_SRC_DST_BIDX_DSTBIDX_SHIFT #define TCINTEN_SHIFT CSL_EDMA3CC_OPT_TCINTEN_SHIFT #define TCC_SHIFT CSL_EDMA3CC_OPT_TCC_SHIFT #define EDMA3_INTC_EVENT_NR CSL_INTC_EVENTID_EDMA3_0_CC0_INT1 CSL_SpiRegsOvly spiRegs = (CSL_SpiRegsOvly)CSL_SPI_0_REGS; CSL_Edma3ccRegsOvly dmaRegs = (CSL_Edma3ccRegsOvly)CSL_EDMA30CC_0_REGS; CSL_DspintcRegsOvly intcRegs = (CSL_DspintcRegsOvly)CSL_INTC_0_REGS; static void setUpDMA(); static void setUpIterrupts(); extern void intcVectorTable(void); void startSPI(); void testSPI(); void ISR_EDMA(); interrupt void ISR_EDMA() { printf("\n ____INTERRUPT TRIGGERED____\n"); } void main(void) { printf("\nSPI loopback test started.\n"); startSPI(); testSPI(); } /*  * @brief Starts up the SPI peripheral for use with DMA.  */ void startSPI(void) { CSL_PscRegsOvly psc0Regs = (CSL_PscRegsOvly)CSL_PSC_0_REGS; // Deassert SPI0 local PSC reset and set NEXT state to ENABLE psc0Regs->MDCTL[CSL_PSC_SPI0] = CSL_FMKT( PSC_MDCTL_NEXT, ENABLE ) | CSL_FMKT( PSC_MDCTL_LRST, DEASSERT ); // Move SPI0 PSC to Next state psc0Regs->PTCMD = CSL_FMKT(PSC_PTCMD_GO0, SET); // Wait for transition while( CSL_FEXT(psc0Regs->MDSTAT[CSL_PSC_SPI0], PSC_MDSTAT_STATE) != CSL_PSC_MDSTAT_STATE_ENABLE); // First reset the SPI chip spiRegs->SPIGCR0 = CSL_FMK(SPI_SPIGCR0_RESET, CSL_SPI_SPIGCR0_RESET_IN_RESET); // Now bring the chip out of reset state spiRegs->SPIGCR0 = CSL_FMK(SPI_SPIGCR0_RESET, CSL_SPI_SPIGCR0_RESET_OUT_OF_RESET); // Enable the CLKMOD and MASTER bits in the SPI global control reg spiRegs->SPIGCR1 |= CSL_FMK(SPI_SPIGCR1_MASTER,0x01) | CSL_FMK(SPI_SPIGCR1_CLKMOD,0x01); // Enable the pins so that they are used for the SPI interface(Multiplex) spiRegs->SPIPC0 = CSL_FMK(SPI_SPIPC0_CLKFUN ,0x01) | CSL_FMK(SPI_SPIPC0_SOMIFUN ,0x01) | CSL_FMK(SPI_SPIPC0_SIMOFUN ,0x01); // configure the data format in SPIFMT spiRegs->SPIFMT[0] = CSL_FMK(SPI_SPIFMT_CHARLEN,SPI_BITS_PER_TX) | CSL_FMK(SPI_SPIFMT_PRESCALE,0x02); // set the preconfigure data format as 0 which is already set above spiRegs->SPIDAT1 = CSL_FMKT(SPI_SPIDAT1_DFSEL,FORMAT0); // Enable interrupt on DMA which EDMA3 sees as 'events' spiRegs->SPIINT0 = 0; spiRegs->SPIINT0 = CSL_FMKT(SPI_SPIINT0_DMAREQEN,ENABLE); // Loopback needs to be enabled AFTER configuring the SPI peripheral as master spiRegs->SPIGCR1 |= CSL_FMK(SPI_SPIGCR1_ENABLE,0x01) | CSL_FMK(SPI_SPIGCR1_LOOPBACK,0x01); setUpDMA(); } static void setUpDMA() { // Enable Receive and Transmit events that cause the next SPI_BYTES_PER_TX/RX // bytes to be transferred. dmaRegs->EESR = 1<<SPI0_RX_PARAM | 1<<SPI0_TX_PARAM; // Enable the Receive and Transmit interrupts at EDMA3 dmaRegs->IESR = 1<<SPI0_RX_PARAM | 1<<SPI0_TX_PARAM; setUpIterrupts(); } static void setUpIterrupts() { // Clear event 8 intcRegs->EVTCLR[0] = EDMA3_INTC_EVENT_NR; // Configure the interrupt controller to forward EDMA3 interrupts to DSP on event 8 CSL_FINS(intcRegs->INTMUX2, DSPINTC_INTMUX2_INTSEL8, EDMA3_INTC_EVENT_NR); // !!!THIS WORKS WITH 56 instead of 8!!! // Set up Interrupt Service Table Pointer to the vector table. ISTP = (unsigned int)intcVectorTable; ICR = 0xFFF0; // Chear all interrrupts (4-15) IER |= 1<<8 | 1<<1; // Enable interrupt bits 8 and 2(Non-Maskable Interrupt) _enable_interrupts(); // Enable interrupts, set GIE bit } /*  * @brief Tests the SPI loopback with DMA by transferring the contents of one buffer to another.  */ void testSPI(void) { int arraySize = 8; char *send = "QRSTUVWXYZ123456"; char *receive = "ABCDEFGHIJKLMNOP"; char test; #if NO_DMA while(*send) { // write the data to the transmit buffer CSL_FINS(spiRegs->SPIDAT1,SPI_SPIDAT1_TXDATA,*send); // check if data is recieved while ((CSL_FEXT(spiRegs->SPIBUF,SPI_SPIBUF_RXEMPTY)) == 1); test = (CSL_FEXT(spiRegs->SPIBUF,SPI_SPIBUF_RXDATA)); if (test == *send) { printf("sent %c recv %c\n",*send,test); } else { printf("ERROR : sent %c recv %c\n",*send,test); printf("\nSPI Loopback test Failed.\n"); return; } send++; } printf("SPI Loopback test success.\n"); #else // Set up Tx DMA :- A-Synchronous mode (NOT asynchronous), SPI peripheral // creates an event when a byte is transferred, causes SPI_BYTES_PER_TX // bytes to be copied to SPIDAT0. The first event/trigger is done manually. // Interrupt on transfer completion with code SPI0_TX_PARAM dmaRegs->PARAMSET[SPI0_TX_PARAM].OPT = 1<<TCINTEN_SHIFT | SPI0_TX_PARAM<<TCC_SHIFT; dmaRegs->PARAMSET[SPI0_TX_PARAM].SRC = (Uint32)send; dmaRegs->PARAMSET[SPI0_TX_PARAM].A_B_CNT = ((Uint32)arraySize<<BCNT_SHIFT) | SPI_BYTES_PER_TX; dmaRegs->PARAMSET[SPI0_TX_PARAM].DST = (Uint32)(&spiRegs->SPIDAT0); // A-size transfers are SPI_BYTES_PER_TX bytes apart at SOURCE. dmaRegs->PARAMSET[SPI0_TX_PARAM].SRC_DST_BIDX = SPI_BYTES_PER_TX; dmaRegs->PARAMSET[SPI0_TX_PARAM].LINK_BCNTRLD = 0x0000FFFF; // No linking dmaRegs->PARAMSET[SPI0_TX_PARAM].SRC_DST_CIDX = 0; // No 3D transfer dmaRegs->PARAMSET[SPI0_TX_PARAM].CCNT = 1; // No 3D transfer // Set up Rx DMA :- A-Synchronous mode (NOT asynchronous), SPI peripheral // creates an event when new data is available, causes SPI_BYTES_PER_RX // to be copied from SPIBUF. // Interrupt on transfer completion with code SPI0_RX_PARAM dmaRegs->PARAMSET[SPI0_RX_PARAM].OPT = 1<<TCINTEN_SHIFT | SPI0_RX_PARAM<<TCC_SHIFT; dmaRegs->PARAMSET[SPI0_RX_PARAM].SRC = (Uint32)(&spiRegs->SPIBUF); dmaRegs->PARAMSET[SPI0_RX_PARAM].A_B_CNT = ((Uint32)arraySize/2<<BCNT_SHIFT) | SPI_BYTES_PER_RX; dmaRegs->PARAMSET[SPI0_RX_PARAM].DST = (Uint32)receive; // A-size transfers are SPI_BYTES_PER_RX bytes apart at DESTINATION. dmaRegs->PARAMSET[SPI0_RX_PARAM].SRC_DST_BIDX = SPI_BYTES_PER_RX<<DSTBIDX_SHIFT; dmaRegs->PARAMSET[SPI0_RX_PARAM].LINK_BCNTRLD = 0x0000FFFF; // No linking dmaRegs->PARAMSET[SPI0_RX_PARAM].SRC_DST_CIDX = 0; // No 3D transfer dmaRegs->PARAMSET[SPI0_RX_PARAM].CCNT = 1; // No 3D transfer // Trigger the Tx dmaRegs->ESR = 1<<SPI0_TX_PARAM; printf("Received: %s\n", receive); //ISR = (1<<8); while(1); #endif }

I'll appreciate any pointers on what I could be doing wrong.

Cheers,
Akhil