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.

SPI Interrupt woes on 28335

Other Parts Discussed in Thread: CONTROLSUITE

I'm working on a piece of code that performs hardware-level SPI back and forth with an ADC. After numerous attempts, I set the interrupt-driven code aside and wrote a software-level bit bang and tested that it does work. I'd really like to get the built-in SPI mechanism working though. Once that's done, I'll rewrite it to work in SYS/BIOS.

The problem I'm experiencing is, while I don't even know if the first transfer is getting through, the hardware IRQ keeps triggering, and I'm struggling to understand why.

Here is the main.c file. It's a derivation of the Example_2833xSpi_FFDLB_int from the TI Control Suite. However, I've hacked it to pieces since and rearranged things to an near unrecognizable state.

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
#include "BitBangSPI.h"
#include "HardwareSPI.h"
#include "PSU.h"

Uint16 sdata[7];     // Send data buffer
Uint16 rdata[7][2];     // Receive data buffer
void main(void)
{
   Uint16 i;

   InitSysCtrl();
   SetupPSU();
   DINT;
   IER = 0x0000;
   IFR = 0x0000;
   InitPieCtrl();
   InitPieVectTable();
   spiSetup();

   //Setup data to be sent
   for(i=0;i<7;i++){
	   sdata[i]=
			   (1<<7)|
			   ((i & 0x0007)<<4)|
			   ((0 & 0x0001)<<3)|
			   ((1 & 0x0001)<<2)|
			   ((3 & 0x0003));
   }
   //Clear data reception buffer
   for(i=0;i<7;i++){
	   rdata[i][0]=0;
	   rdata[i][1]=0;
   }


   //Loop and send forever
   i=0;
   for(;;){
		if(i>=7){i=0;}
		spiSendAndReceive(sdata+i,1,rdata[i],2,8);
		i++;
	}

}

Here is my HardwareSPI.c library. There are a few missing functions, but I promise they're just GPIO inits. The two functions called from main.c are spiSetup and spiSendAndReceive.

#include "HardwareSPI.h"
#ifndef USE_SOFTWARE_SPI
#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
static Uint16 spiDataIndex=0;
static Uint16 spiDataSize=0;
static Uint16 *spiTXBuffer;
static Uint16 *spiRXBuffer;
static Uint16 spiSemRXFF;
static Uint16 spiSemTXFF;
static void spiHoldInReset();
static void spiRegisterISR();
static void spiFIFOInit();
static void spiReleaseFromReset();
static void spiEnableInterrupts();

void spiSetup(){
	spiHoldInReset();
	spiInitGPIOPins();
	// Interrupts that are used in this example are re-mapped to
	// ISR functions found within this file.
	spiRegisterISR();
	// Initialize all the Device Peripherals:
	// This function is found in DSP2833x_InitPeripherals.c
	// InitPeripherals(); // Not required for this example
	spiFIFOInit();	  // Initialize the SPI only
	spiReleaseFromReset();
	spiEnableInterrupts();
}

static void spiHoldInReset(){
	EALLOW;
	PieCtrlRegs.PIEIFR6.bit.INTx1=0;	//Disable FIFO Interrupt flags
	PieCtrlRegs.PIEIFR6.bit.INTx2=0;	//Disable FIFO Interrupt flags
	SpiaRegs.SPIFFTX.bit.SPIRST=0;		// Hold both FIFOs in reset
	SpiaRegs.SPIFFTX.bit.TXFIFO=0;		// Hold TX FIFO in reset
	SpiaRegs.SPIFFRX.bit.RXFIFORESET=0;	// Hold RX FIFO in reset
	SpiaRegs.SPICCR.bit.SPISWRESET=0;	// Software Reset SPI
	SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;	//Clear TX FIFO
	SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1;	//Clear RX FIFO
	EDIS;
}

void spiInitGPIOPins(){
	spiCommonInitGPIOPinsStart();
	/* Configure SPI-A pins using GPIO regs*/
	// This specifies which of the possible GPIO pins will be SPI functional pins.
	GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 1; // Configure GPIO54 as SPISIMOA
	GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 1; // Configure GPIO55 as SPISOMIA
	GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 1; // Configure GPIO56 as SPICLKA
	spiCommonInitGPIOPinsEnd();
}

static void spiRegisterISR(){
	EALLOW;	// This is needed to write to EALLOW protected registers
	PieVectTable.SPIRXINTA = &spiRxFifoIsr;
	PieVectTable.SPITXINTA = &spiTxFifoIsr;
	EDIS;   // This is needed to disable write to EALLOW protected registers
}

static void spiFIFOInit()
{
	EALLOW;
	// Initialize SPI FIFO registers
	SpiaRegs.SPIFFCT.bit.TXDLY=0;
	SpiaRegs.SPICCR.bit.CLKPOLARITY=0;
	SpiaRegs.SPICCR.bit.SPILBK=0;
	SpiaRegs.SPICCR.bit.SPICHAR=7;		//Bit width of characters
	SpiaRegs.SPICTL.bit.OVERRUNINTENA=1;//Enable Overrun Interrupt
	SpiaRegs.SPICTL.bit.CLK_PHASE=1;	//Delay by 1/2 cycle
	SpiaRegs.SPICTL.bit.MASTER_SLAVE=1;	//TI is Master
	SpiaRegs.SPICTL.bit.TALK=1;			//Communication is permitted
	SpiaRegs.SPICTL.bit.SPIINTENA=0;	//Disable Interrupt

	SpiaRegs.SPISTS.all=0x0000;

	SpiaRegs.SPIBRR=0x007;				// Baud rate=LSPCLK/(7+1)

	SpiaRegs.SPIFFTX.bit.SPIFFENA=1;	//TX FIFO Enable
	SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;	//Clear TX Int flag
	SpiaRegs.SPIFFTX.bit.TXFFIL=4;		//Set Level to 1 character

	SpiaRegs.SPIFFTX.bit.TXFFST=0;		//Set FIFO Status to 0 characters


	SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1;	//Clear RX FIFO Overflow flag
	SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1;	//Clear RX FIFO Interrupt flag
	SpiaRegs.SPIFFRX.bit.RXFFIENA=0;	//Disable RX FIFO Interrupt
	SpiaRegs.SPIFFRX.bit.RXFFIL=4;		//Set flag after 4 bytes received
	SpiaRegs.SPIFFRX.bit.RXFFST=0;		//Set RX FIFO status to 0

	SpiaRegs.SPIPRI.bit.FREE=1;			//Don't let debug interrupt SPI transfer
	SpiaRegs.SPIPRI.bit.SOFT=0;			//Makes no difference

	EDIS;
}

static void spiReleaseFromReset(){
	EALLOW;
	SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;	//Release from reset
	SpiaRegs.SPIFFTX.bit.TXFIFO=1;		//Release from reset
	SpiaRegs.SPIFFTX.bit.SPIRST=1;		//Release from reset
	SpiaRegs.SPICCR.bit.SPISWRESET=1;	//Release SPI from reset
	EDIS;
}

static void spiEnableInterrupts(){
	EALLOW;
	// Enable interrupts required for this example
	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
	PieCtrlRegs.PIEIER6.bit.INTx1=1;     // Enable PIE Group 6, INT 1
	PieCtrlRegs.PIEIER6.bit.INTx2=1;     // Enable PIE Group 6, INT 2
	IER=0x20;                            // Enable CPU INT6
	EINT;                                // Enable Global Interrupts
	EDIS;
}

void	spiSendAndReceive(Uint16 *outBuffer, Uint16 outBytes, Uint16 *inBuffer, Uint16 inBytes, Uint16  byteSize){
	if(byteSize==0||byteSize>16){return;}	//If bad byte size return
	if(outBuffer==0&&inBuffer==0){return;}	//If both buffers are null return
	if(outBuffer==0&&outBytes!=0){return;}	//If TX buffer is null, but TX buffer size is non zero return
	if(inBuffer==0&&inBytes!=0){return;}	//If RX buffer is null, but RX buffer size is non zero return
	spiSetByteSize(byteSize);
	spiSend(outBuffer, outBytes);
	spiReceive(inBuffer, inBytes);
	EALLOW;
	SpiaRegs.SPIFFTX.bit.TXFFIENA=0;	//TX FIFO Int Enable
	SpiaRegs.SPIFFRX.bit.RXFFIENA=0;	//RX FIFO Int Enable
	EDIS;
}

void spiSetByteSize(Uint16 byteSize){
	SpiaRegs.SPICCR.bit.SPICHAR=(byteSize-1) & (0x000F);
}

void spiSend(Uint16 *outBuffer,Uint16 outBytes){
	spiSemTXFF=1;							//Pseudo Semaphore for TX ISR
	spiTXBuffer=outBuffer;					//Set data buffer
	spiDataSize=outBytes;					//Set data size
	EALLOW;
	SpiaRegs.SPIFFTX.bit.TXFFIL=outBytes;	//Set level to number of characters
	SpiaRegs.SPIFFTX.bit.TXFFST=outBytes;	//Set status reg to number of characters
	SpiaRegs.SPIFFTX.bit.TXFFIENA=1;		// Enable TX FIFO interrupt
	EDIS;
	while(spiSemTXFF==1){}					//Wait until ISR returns
	EALLOW;
	SpiaRegs.SPIFFTX.bit.TXFFIENA=0;		// Disable TX FIFO interrupt
	EDIS;
}

void spiReceive(Uint16 *inBuffer,Uint16 inBytes){
	spiSemRXFF=1;							//Pseudo Semaphore for RX ISR
	spiRXBuffer=inBuffer;					//Set data buffer
	spiDataSize=inBytes;					//Set data size
	EALLOW;
	SpiaRegs.SPIFFRX.bit.RXFFIL=inBytes;	//Set level to number of characters
	SpiaRegs.SPIFFRX.bit.RXFFST=inBytes;	//Set status reg to number of characters
	SpiaRegs.SPIFFRX.bit.RXFFIENA=1;		//Enable RX FIFO interrupt
	EDIS;
	while(spiSemRXFF==1){}					//Wait until ISR returns
	EALLOW;
	SpiaRegs.SPIFFRX.bit.RXFFIENA=0;		//Disable RX FIFO interrupt
	EDIS;
}

interrupt void spiTxFifoIsr(void)
{
	//For every character,
	for(spiDataIndex=0;spiDataIndex<spiDataSize;spiDataIndex++){
		SpiaRegs.SPITXBUF=
				(spiTXBuffer[spiDataIndex]<<(15-SpiaRegs.SPICCR.bit.SPICHAR));// Left align data, then send
	}
	SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;  //Clear Interrupt flag
	//PieCtrlRegs.PIEACK.all|=0x20;  	//Issue PIE ACK
	PieCtrlRegs.PIEACK.bit.ACK6=1;				//Acknowledge interrupt to PIE
	spiSemTXFF=0;						//Reset Semaphore
}

interrupt void spiRxFifoIsr(void)
{

	for(spiDataIndex=0;spiDataIndex<spiDataSize;spiDataIndex++){
		spiRXBuffer[spiDataIndex]=SpiaRegs.SPIRXBUF;		// Read data
	}
	SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1;  // Clear Overflow flag
	SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1; 	// Clear Interrupt flag
	//PieCtrlRegs.PIEACK.all|=0x20;		// Issue PIE ack
	PieCtrlRegs.PIEACK.bit.ACK6=1;		//Acknowledge interrupt to PIE
	spiSemRXFF=0;						//Reset Semaphore
}

#endif

Any help would be greatly appreciated.

  • Hello Dean,

    1. If using original Controlsuite example, is it working well in your hardware?

    2. In your GPIO initialization, did you mention EALLOW and EDIS? (I saw that you put these lines for SPI initialization that I think it is not necessary, but this is not the case anyway).

    3. I read in the datasheet that "Never clear PIEIFR". Maybe you should not initiate them as 0.

    4. I saw that SPI interrupt was not enabled (SpiaRegs.SPICTL.bit.SPIINTENA=0;) but you enabled the PIE for these interrupts and also FIFO interrupts. Maybe you need to enable this bit too?



    I am not sure my comments above will help you but really hoping you can solve your problem soon.



    Best regards,
    Maria

  • I added some modifications. Apparently, the interrupt resets its own flag, and when I cleared it in the code, it turned the flag back on.

    /*
     * HardwareSPI.c
     *  Created on: Mar 11, 2014
     *      Author: dsands
     */
    
    #include "HardwareSPI.h"
    #ifdef USE_HARDWARE_SPI
    #include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
    static Uint16 spiDataIndex=0;
    static Uint16 spiDataSize=0;
    static Uint16 *spiTXBuffer;
    static Uint16 *spiRXBuffer;
    static Uint16 spiSemRXFF;
    static Uint16 spiSemTXFF;
    static void spiHoldInReset();
    static void spiRegisterISR();
    static void spiFIFOInit();
    static void spiReleaseFromReset();
    static void spiEnableInterrupts();
    
    void spiSetup(){
    	spiHoldInReset();
    	spiInitGPIOPins();
    	// Interrupts that are used in this example are re-mapped to
    	// ISR functions found within this file.
    	spiRegisterISR();
    	// Initialize all the Device Peripherals:
    	// This function is found in DSP2833x_InitPeripherals.c
    	// InitPeripherals(); // Not required for this example
    	spiFIFOInit();	  // Initialize the SPI only
    	spiReleaseFromReset();
    	spiEnableInterrupts();
    }
    
    static void spiHoldInReset(){
    	EALLOW;
    	PieCtrlRegs.PIEIFR6.bit.INTx1=0;	//Disable FIFO Interrupt flags
    	PieCtrlRegs.PIEIFR6.bit.INTx2=0;	//Disable FIFO Interrupt flags
    	SpiaRegs.SPIFFTX.bit.SPIRST=0;		// Hold both FIFOs in reset
    	SpiaRegs.SPIFFTX.bit.TXFIFO=0;		// Hold TX FIFO in reset
    	SpiaRegs.SPIFFRX.bit.RXFIFORESET=0;	// Hold RX FIFO in reset
    	SpiaRegs.SPICCR.bit.SPISWRESET=0;	// Software Reset SPI
    	SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;	//Clear TX FIFO Interrupt Flag
    	SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1;	//Clear RX FIFO Interrupt Flag
    	EDIS;
    }
    
    void spiInitGPIOPins(){
    	spiCommonInitGPIOPinsStart();
    	/* Configure SPI-A pins using GPIO regs*/
    	// This specifies which of the possible GPIO pins will be SPI functional pins.
    	GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 1; // Configure GPIO54 as SPISIMOA
    	GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 1; // Configure GPIO55 as SPISOMIA
    	GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 1; // Configure GPIO56 as SPICLKA
    	spiCommonInitGPIOPinsEnd();
    }
    
    static void spiRegisterISR(){
    	EALLOW;	// This is needed to write to EALLOW protected registers
    	PieVectTable.SPIRXINTA = &spiRxFifoIsr;
    	PieVectTable.SPITXINTA = &spiTxFifoIsr;
    	EDIS;   // This is needed to disable write to EALLOW protected registers
    }
    
    static void spiFIFOInit()
    {
    	EALLOW;
    	// Initialize SPI FIFO registers
    	SpiaRegs.SPIFFCT.bit.TXDLY=0;
    	SpiaRegs.SPICCR.bit.CLKPOLARITY=0;
    	SpiaRegs.SPICCR.bit.SPILBK=0;
    	SpiaRegs.SPICCR.bit.SPICHAR=7;		//Bit width of characters
    	SpiaRegs.SPICTL.bit.OVERRUNINTENA=1;//Enable Overrun Interrupt
    	SpiaRegs.SPICTL.bit.CLK_PHASE=1;	//Delay by 1/2 cycle
    	SpiaRegs.SPICTL.bit.MASTER_SLAVE=1;	//TI is Master
    	SpiaRegs.SPICTL.bit.TALK=1;			//Communication is permitted
    	SpiaRegs.SPICTL.bit.SPIINTENA=0;	//Disable Interrupt
    
    	SpiaRegs.SPISTS.all=0x0000;
    
    	SpiaRegs.SPIBRR=0x063;				// Baud rate=LSPCLK/(99+1)
    
    	SpiaRegs.SPIFFTX.bit.SPIFFENA=1;	//TX FIFO Enable
    	SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;	//Clear TX Int flag
    	SpiaRegs.SPIFFTX.bit.TXFFIL=4;		//Set Level to 1 character
    
    	SpiaRegs.SPIFFTX.bit.TXFFST=0;		//Set FIFO Status to 0 characters
    
    
    	SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1;	//Clear RX FIFO Overflow flag
    	SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1;	//Clear RX FIFO Interrupt flag
    	SpiaRegs.SPIFFRX.bit.RXFFIENA=0;	//Disable RX FIFO Interrupt
    	SpiaRegs.SPIFFRX.bit.RXFFIL=4;		//Set flag after 4 bytes received
    	SpiaRegs.SPIFFRX.bit.RXFFST=0;		//Set RX FIFO status to 0
    
    	SpiaRegs.SPIPRI.bit.FREE=1;			//Don't let debug interrupt SPI transfer
    	SpiaRegs.SPIPRI.bit.SOFT=0;			//Makes no difference
    
    	EDIS;
    }
    
    static void spiReleaseFromReset(){
    	EALLOW;
    	SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;	//Release from reset
    	SpiaRegs.SPIFFTX.bit.TXFIFO=1;		//Release from reset
    	SpiaRegs.SPIFFTX.bit.SPIRST=1;		//Release from reset
    	SpiaRegs.SPICCR.bit.SPISWRESET=1;	//Release SPI from reset
    	EDIS;
    }
    
    static void spiEnableInterrupts(){
    	EALLOW;
    	// Enable interrupts required for this example
    	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
    	PieCtrlRegs.PIEIER6.bit.INTx1=1;     // Enable PIE Group 6, INT 1
    	PieCtrlRegs.PIEIER6.bit.INTx2=1;     // Enable PIE Group 6, INT 2
    	IER=0x20;                            // Enable CPU INT6
    	EINT;                                // Enable Global Interrupts
    	EDIS;
    }
    
    void	spiSendAndReceive(Uint16 *outBuffer, Uint16 outBytes, Uint16 *inBuffer, Uint16 inBytes, Uint16  byteSize){
    	if(byteSize==0||byteSize>16){return;}	//If bad byte size return
    	if(outBuffer==0&&inBuffer==0){return;}	//If both buffers are null return
    	if(outBuffer==0&&outBytes!=0){return;}	//If TX buffer is null, but TX buffer size is non zero return
    	if(inBuffer==0&&inBytes!=0){return;}	//If RX buffer is null, but RX buffer size is non zero return
    	spiSetByteSize(byteSize);
    	spiSend(outBuffer, outBytes);
    	spiReceive(inBuffer, inBytes);
    	EALLOW;
    	SpiaRegs.SPIFFTX.bit.TXFFIENA=0;	//TX FIFO Int Enable
    	SpiaRegs.SPIFFRX.bit.RXFFIENA=0;	//RX FIFO Int Enable
    	EDIS;
    }
    
    void spiSetByteSize(Uint16 byteSize){
    	SpiaRegs.SPICCR.bit.SPICHAR=(byteSize-1) & (0x000F);
    }
    
    void spiSend(Uint16 *outBuffer,Uint16 outBytes){
    	spiSemTXFF=1;							//Pseudo Semaphore for TX ISR
    	spiTXBuffer=outBuffer;					//Set data buffer
    	spiDataSize=outBytes;					//Set data size
    	EALLOW;
    	SpiaRegs.SPIFFTX.bit.TXFFIL=outBytes;	//Set level to number of characters
    	SpiaRegs.SPIFFTX.bit.TXFFST=outBytes;	//Set status reg to number of characters
    	SpiaRegs.SPIFFTX.bit.TXFFIENA=1;		// Enable TX FIFO interrupt
    	EDIS;
    	while(SpiaRegs.SPIFFTX.bit.TXFFST>0){}					//Wait until ISR returns
    	EALLOW;
    	SpiaRegs.SPIFFTX.bit.TXFFIENA=0;		// Disable TX FIFO interrupt
    	EDIS;
    }
    
    void spiReceive(Uint16 *inBuffer,Uint16 inBytes){
    	spiSemRXFF=1;							//Pseudo Semaphore for RX ISR
    	spiRXBuffer=inBuffer;					//Set data buffer
    	spiDataSize=inBytes;					//Set data size
    	EALLOW;
    	SpiaRegs.SPIFFRX.bit.RXFFIL=inBytes;	//Set level to number of characters
    	SpiaRegs.SPIFFRX.bit.RXFFST=0;
    	SpiaRegs.SPIFFRX.bit.RXFFIENA=1;		//Enable RX FIFO interrupt
    	EDIS;
    	while(SpiaRegs.SPIFFRX.bit.RXFFST>0){}					//Wait until ISR returns
    	EALLOW;
    	SpiaRegs.SPIFFRX.bit.RXFFIENA=0;		//Disable RX FIFO interrupt
    	EDIS;
    }
    
    interrupt void spiTxFifoIsr(void)
    {
    	//For every character,
    	for(spiDataIndex=0;spiDataIndex<spiDataSize;spiDataIndex++){
    		SpiaRegs.SPITXBUF=
    				(spiTXBuffer[spiDataIndex]<<(15-SpiaRegs.SPICCR.bit.SPICHAR));// Left align data, then send
    	}
    	EALLOW;
    	//SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;  //Clear Interrupt flag (No, it doesn't.)
    	PieCtrlRegs.PIEACK.all|=0x20;  	//Issue PIE ACK
    	//PieCtrlRegs.PIEACK.bit.ACK6=1;				//Acknowledge interrupt to PIE
    	EDIS;
    	spiSemTXFF=0;						//Reset Semaphore
    }
    
    interrupt void spiRxFifoIsr(void)
    {
    
    	for(spiDataIndex=0;spiDataIndex<spiDataSize;spiDataIndex++){
    		spiRXBuffer[spiDataIndex]=SpiaRegs.SPIRXBUF;		// Read data
    	}
    	EALLOW;
    	SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1;  // Clear Overflow flag
    	SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1; 	// Clear Interrupt flag
    	PieCtrlRegs.PIEACK.all|=0x20;		// Issue PIE ack
    	//PieCtrlRegs.PIEACK.bit.ACK6=1;		//Acknowledge interrupt to PIE
    	EDIS;
    	spiSemRXFF=0;						//Reset Semaphore
    }
    
    #endif //USE_HARDWARE_SPI
    

    Things are somewhat better, but I'm not getting good data back from the ADC (a MAX186) whereas I do when I use the bitbang.

  • Hello Dean,

    Did you try the SPI example code from ControlSuite? Did it work well?

    Ad what do you mean by 'somewhat better' for your latest code?

    In your code, please check whether the interrupts enter the ISR  (spiTxFifoIsr and spiRxFifoIsr) or not by placing the counters there.

    Best regards,

    Maria