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.

C2000 SPI INIT

Other Parts Discussed in Thread: PGA280, CONTROLSUITE

Hi,

I am using SPI-A on the C2000 launchpad ,To test my chip i have used the spi_lopback_interrupts example code with a little modification (disabling loopback and data check in receive function) ,

which has the following SPI-FIFO init function,

A few questions

1>> How does the interrupt get generated first time automatically since the example code doesnt write anything to SPIBUF

2>> I find that this code continuously transmits data without a delay ,I wish to send 2 bytes , a delay and then 2 bytes .How do i do this

please help!!!

void spi_fifo_init()
{
// Initialize SPI FIFO registers
SpiaRegs.SPICCR.bit.SPISWRESET=0; // Reset SPI

SpiaRegs.SPICCR.all=0x001F; //16-bit character, Loopback mode
SpiaRegs.SPICTL.all=0x0017; //Interrupt enabled, Master/Slave XMIT enabled
SpiaRegs.SPISTS.all=0x0000;
SpiaRegs.SPIBRR=0x0063; // Baud rate
SpiaRegs.SPIFFTX.all=0xC022; // Enable FIFO's, set TX FIFO level to 2
SpiaRegs.SPIFFRX.all=0x0022; // Set RX FIFO level to 2
SpiaRegs.SPIFFCT.all=0x00;
SpiaRegs.SPIPRI.all=0x0010;

SpiaRegs.SPICCR.bit.SPISWRESET=1; // Enable SPI

SpiaRegs.SPIFFTX.bit.TXFIFO=1;
SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;
}

Regards

Abhay

  • 
    
    Hi Abhay,

    The TX interrupt occurs whenever the TX FIFO is empty. As soon as you enable the interrupt and the FIFO, the FIFO is empty so the interrupt occurs right away.

    I have a side project where I am porting some MSP430 OLED drivers to the launchpad. The way I handled it was to do this:

    *When I have added the last byte in my transmission to the TX FIFO, i disable the TX FIFO interrupt. The FIFO is still active, so the rest of the message should flush out and be sent. When I am ready to send again, I re-enable the TX FIFO interrupt.

    The below code is a little rough, but maybe it will give you some starting point.

    interrupt void spiTxFifoIsr(void) { Uint16 tx_fifo_counter; if(0 == first) { //delay before writing first time asm(" RPT#255 || NOP"); asm(" RPT#255 || NOP"); asm(" RPT#255 || NOP"); asm(" RPT#255 || NOP"); asm(" RPT#255 || NOP"); asm(" RPT#255 || NOP"); asm(" RPT#255 || NOP"); asm(" RPT#255 || NOP"); //done delaying for the first time first = 1; } for(tx_fifo_counter = 0; tx_fifo_counter < 2; tx_fifo_counter++) { if(spi_tx_counter < spi_tx_length) { if(1 == OLED_Select) { //start transmitting SpiaRegs.SPICTL.bit.TALK = 1; //set chip select low OLED_Select = 0; //wait asm(" RPT#255 || NOP"); } SPI_write(mySpi, spi_send_data[spi_tx_counter++]); } } if(spi_tx_counter == spi_tx_length) { //if all the words have been transmitted, disable TX FIFO PIE_disableInt(myPie, PIE_GroupNumber_6, PIE_InterruptSource_SPIATX); } // Clear Interrupt flag SPI_clearTxFifoInt(mySpi); // Issue PIE ACK PIE_clearInt(myPie, PIE_GroupNumber_6); return; }
    void spi_send(Uint16 length)
    {
    	spi_tx_length = length;
    	spi_tx_counter = 0;
    	spi_rx_counter = 0;
    	spi_ready = 0;
    
        PIE_enableInt(myPie, PIE_GroupNumber_6, PIE_InterruptSource_SPIARX);
        PIE_enableInt(myPie, PIE_GroupNumber_6, PIE_InterruptSource_SPIATX);
    
        while(!spi_ready);
    }

  • Hi Devin ,

    Thanks for the reply ,

    I understand what you are saying , but i am coding using the register approach since the final target is F28069 which doesn't support the API style of coding . I am using the launchpad for getting familiar

    how ever I will try and disable the TX FIFO interrupt  , but  as I am very new to C2000 it will be great if you can show me in steps how to do it , Please see attached the code file which I am using for testing , do let me know where is the best place to disable the interrupt and how I should do it

    // TI File $Revision: /main/4 $
    // Checkin $Date: October 6, 2010   14:43:18 $
    //###########################################################################
    //
    // FILE:   Example_2802xSpi_FFDLB_int.c
    //
    // TITLE:  DSP2802x Device Spi Digital Loop Back with Interrupts Example.
    //
    // ASSUMPTIONS:
    //
    //    This program requires the DSP2802x header files.
    //
    //    This program uses the internal loop back test mode of the peripheral.
    //    Other then boot mode pin configuration, no other hardware configuration
    //    is required.
    //
    //    As supplied, this project is configured for "boot to SARAM"
    //    operation.  The 2802x Boot Mode table is shown below.
    //    For information on configuring the boot mode of an eZdsp,
    //    please refer to the documentation included with the eZdsp,
    //
    //    $Boot_Table
    //    While an emulator is connected to your device, the TRSTn pin = 1,
    //    which sets the device into EMU_BOOT boot mode. In this mode, the
    //    peripheral boot modes are as follows:
    //
    //      Boot Mode:   EMU_KEY        EMU_BMODE
    //                   (0xD00)	     (0xD01)
    //      ---------------------------------------
    //      Wait		 !=0x55AA        X
    //      I/O		     0x55AA	         0x0000
    //      SCI		     0x55AA	         0x0001
    //      Wait 	     0x55AA	         0x0002
    //      Get_Mode	 0x55AA	         0x0003
    //      SPI		     0x55AA	         0x0004
    //      I2C		     0x55AA	         0x0005
    //      OTP		     0x55AA	         0x0006
    //      Wait		 0x55AA	         0x0007
    //      Wait		 0x55AA	         0x0008
    //      SARAM		 0x55AA	         0x000A	  <-- "Boot to SARAM"
    //      Flash		 0x55AA	         0x000B
    //	    Wait		 0x55AA          Other
    //
    //   Write EMU_KEY to 0xD00 and EMU_BMODE to 0xD01 via the debugger
    //   according to the Boot Mode Table above. Build/Load project,
    //   Reset the device, and Run example
    //
    //   $End_Boot_Table
    //
    // DESCRIPTION:
    //
    //    This program is a SPI-A example that uses the internal loopback of
    //    the peripheral.  Both interrupts and the SPI FIFOs are used.
    //
    //    A stream of data is sent and then compared to the recieved stream.
    //
    //    The sent data looks like this:
    //    0000 0001
    //    0001 0002
    //    0002 0003
    //    ....
    //    FFFE FFFF
    //    FFFF 0000
    //     etc..
    //
    //    This pattern is repeated forever.
    //
    //
    // Watch Variables:
    //     sdata[2]    - Data to send
    //     rdata[2]    - Received data
    //     rdata_point - Used to keep track of the last position in
    //                   the receive stream for error checking
    //###########################################################################
    //
    // Original Source by S.D.
    //
    // $TI Release: 2802x C/C++ Header Files and Peripheral Examples V1.29 $
    // $Release Date: January 11, 2011 $
    //###########################################################################
    
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    
    // Prototype statements for functions found within this file.
    // interrupt void ISRTimer2(void);
    interrupt void spiTxFifoIsr(void);
    interrupt void spiRxFifoIsr(void);
    void delay_loop(void);
    void spi_fifo_init(void);
    void error();
    
    
    Uint16 sdata[2];     // Send data buffer
    Uint16 rdata[2];     // Receive data buffer
    Uint16 rdata_point;  // Keep track of where we are
    // in the data stream to check received data
    
    void main(void)
    {
    	Uint16 i;
    
    	// Step 1. Initialize System Control:
    	// PLL, WatchDog, enable Peripheral Clocks
    	// This example function is found in the DSP2802x_SysCtrl.c file.
    	InitSysCtrl();
    
    	// Step 2. Initalize GPIO:
    	// This example function is found in the DSP2802x_Gpio.c file and
    	// illustrates how to set the GPIO to it's default state.
    	// InitGpio();  // Skipped for this example
    	// Setup only the GP I/O only for SPI-A functionality
    	InitSpiaGpio();
    
    	// Step 3. Initialize PIE vector table:
    	// Disable and clear all CPU interrupts
    	DINT;
    	IER = 0x0000;
    	IFR = 0x0000;
    
    	// Initialize PIE control registers to their default state:
    	// This function is found in the DSP2802x_PieCtrl.c file.
    	InitPieCtrl();
    
    	// Initialize the PIE vector table with pointers to the shell Interrupt
    	// Service Routines (ISR).
    	// This will populate the entire table, even if the interrupt
    	// is not used in this example.  This is useful for debug purposes.
    	// The shell ISR routines are found in DSP2802x_DefaultIsr.c.
    	// This function is found in DSP2802x_PieVect.c.
    	InitPieVectTable();
    
    	// Interrupts that are used in this example are re-mapped to
    	// ISR functions found within this file.
    	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
    
    	// Step 4. Initialize all the Device Peripherals:
    	// This function is found in DSP2802x_InitPeripherals.c
    	// InitPeripherals(); // Not required for this example
    	spi_fifo_init();	  // Initialize the SPI only
    
    	// Step 5. User specific code, enable interrupts:
    
    	// Initalize the send data buffer
    
    		sdata[0] = 0x4101;
    		sdata[1] = 0x8300;
    	
    	// 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
    
    	// Step 6. IDLE loop. Just sit and loop forever (optional):
    	for(;;)
    	{
    		    
    	}
    
    }
    
    // Some Useful local functions
    void delay_loop()
    {
    	long      i;
    	for (i = 0; i < 1000000; i++) {}
    }
    
    void error(void)
    {
    	asm("     ESTOP0");	 //Test failed!! Stop!
    	for (;;);
    }
    
    void spi_fifo_init()
    {
    	// Initialize SPI FIFO registers
    	SpiaRegs.SPICCR.bit.SPISWRESET=0; // Reset SPI
    	SpiaRegs.SPICCR.all=0x004F;       //16-bit character, Loopback Disabled
    	SpiaRegs.SPICTL.all=0x0017;       //Interrupt enabled, Master/Slave XMIT enabled
    	SpiaRegs.SPISTS.all=0x0000;
    	SpiaRegs.SPIBRR=0x0063;           // Baud rate
    	SpiaRegs.SPIFFTX.all=0xC022;      // Enable FIFO's, set TX FIFO level to 2
    	SpiaRegs.SPIFFRX.all=0x0022;      // Set RX FIFO level to 2
    	SpiaRegs.SPIFFCT.all=0x00;
    	SpiaRegs.SPIPRI.all=0x0010;
    
    	SpiaRegs.SPICCR.bit.SPISWRESET=1;  // Enable SPI
    
    	SpiaRegs.SPIFFTX.bit.TXFIFO=1;
    	SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;
    }
    
    interrupt void spiTxFifoIsr(void)
    {
    
    		SpiaRegs.SPITXBUF=sdata[0];      
    		SpiaRegs.SPITXBUF=sdata[1];
    
    	    
    	SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1;  // Clear Interrupt flag
    	PieCtrlRegs.PIEACK.all|=0x20;  		// Issue PIE ACK
    }
    
    interrupt void spiRxFifoIsr(void)
    {
    	Uint16 i;
    	for(i=0;i<3;i++)
    	{
    		rdata[i]=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
    }
    
    //===========================================================================
    // No more.
    //===========================================================================
    
    
    I am interfacing this with a PGA280 via SPI and am attempting to do a test read by first resetting the device (0x4101) and reading register 3 (0x8300) , my expected read from the device is 0x19

  • Hello,

    About APIs that Devin used, actually it is simple to be followed and modified to be register approach.

    For example:
    SPI_write(mySpi, spi_send_data[spi_tx_counter++]) is the same as:
    SpiaRegs.SPITXBUF=spi_send_data[spi_tx_counter++];

    You can compare the code structure with the one in C:\ti\controlSUITE\device_support\f2802x\v210\f2802x_common\include and C:\ti\controlSUITE\device_support\f2802x\v210\f2802x_common\source

    For example for SPI, refer to spi.h and spi.c
    For SPI_write like example above, you can find it in spi.h written as:

    inline void SPI_write8(SPI_Handle spiHandle,const uint16_t data)
    {
        SPI_Obj *spi = (SPI_Obj *)spiHandle;


        // set the bits
        spi->SPITXBUF = (data & 0xFF) << 8;

        return;
    } // end of SPI_write() function

    Just take spi->SPITXBUF = (data & 0xFF) << 8; and modify it as SpiaRegs.SPITXBUF = (data & 0xFF) << 8; in your code.

    The same for SPI_clearTxFifoInt(), you can see in spi.c written as:
    void SPI_clearTxFifoInt(SPI_Handle spiHandle)
    {
        SPI_Obj *spi = (SPI_Obj *)spiHandle;


        // set the bits
        spi->SPIFFTX |= SPI_SPIFFTX_INTCLR_BITS;

        return;
    } // end of SPI_clearTxFifoInt() function

    and you can find SPI_SPIFFTX_INTCLR_BITS as ( 1 << 6) in spi.h that correspondent with TXFFINTCLR bit of SPIFFTX.

    so in your line, you can write it as: SpiaRegs.SPIFFTX.bit.TXFFINTCLR = 1;

    Follow the same for PIE module.

    Best regards,

    Maria