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.