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.

TMS320F28377D SPI configuration

Other Parts Discussed in Thread: CONTROLSUITE, TMS320F28377D

Hi,

I have been working with the TMS320F28377D module for the past few weeks and was wondering if anyone could help point me in the correct direction for SPI driver development. Currently, I have managed to configure the registers provided by the spi.h files and executing the SPI protocol internally on the TMS320F28377D. This was done by simply reconfiguring the SPI loopback example provided in the ControlSuite CCS projects.

However, my next step involves transmitting and receiving data over to an external module and attempting to communicate with this external module to run some functions the manufacturer has already provided. 

Do you know of any references, guides, or datasheets that I should be taking a look at in order to help achieve this goal? I have thoroughly read through the TMS320F28377D technical reference SPI chapter, looked over the TMS320F28377D datasheets, external module datasheets and a variety of other examples. Still, I have been unable to locate a proper way to go about this and I fear that my current SPI development may lead to bit-banging out transmission values.

Any advice?

Thank you.

Also, in case anyone is wondering what I have been working with, here is what I have been working with:

/*
* main.c
*/

#include "F28x_Project.h"
//#include "LTC6804-2.h"
//#include "C:\Users\hoanga\Desktop\DC2100A_Software_and_Users_Guide\DC2100A_Source_AppFW_v_1_2_0_GUI_v1_3_1\DC2100A_Source\Firmware\Source\LTC6804-2.h"

#include <stdio.h>
#include <inttypes.h>


//#include "LTC6804-2.h"

void delay_loop(void);
void spi_xmit(Uint16 a);
void spi_fifo_init(void);
void spi_init(void);
void error(void);

//user
void spi_init_test(void);
void spi_fifo_init_test(void);
void spi_receive(Uint16 a);

void main(void) {

Uint16 sdata; // send data
Uint16 rdata; // received data

// Step 1. Initialize System C.ontrol:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
InitSysCtrl();

// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_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
// This function is found in F2837xD_Spi.c
InitSpiaGpio();

// Step 3. Clear all __interrupts and initialize PIE vector table:
// Disable CPU __interrupts
DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE __interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
InitPieCtrl();

// Disable CPU __interrupts and clear all CPU __interrupt flags:
IER = 0x0000;
IFR = 0x0000;

// 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 F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
InitPieVectTable();

// Step 4. Initialize the Device Peripherals:
spi_fifo_init(); // Initialize the Spi FIFO
//FIFO needs to be initialized if DMA were to be utilized
//spi_init(); // init SPI

//spi_fifo_init_test(); //initialize user SPI FIFO
spi_init_test(); //initialize user SPI


// Step 5. User specific code

sdata = 1001;
for(;;)
{
// Transmit data
spi_xmit(sdata);
// Wait until data is received

//while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }

printf("%" PRIu16 "\n", sdata);
// Check against sent data
rdata = SpiaRegs.SPIRXBUF;
//if(rdata != sdata) error();

printf("%" PRIu16 "\n", rdata);
SpiaRegs.SPIRXBUF;
}
}

void spi_xmit(Uint16 a)
{
SpiaRegs.SPITXBUF=a;
}

void spi_receive(Uint16 a)
{
SpiaRegs.SPIRXBUF = a; //receiving value from the buffer?
}

void spi_fifo_init()
{
// Initialize SPI FIFO registers
SpiaRegs.SPIFFTX.all=0xE040;
SpiaRegs.SPIFFRX.all=0x2044;
SpiaRegs.SPIFFCT.all=0x0;
}

void spi_fifo_init_test()
{
//SpiaRegs.SPIFFTX.bit.SPIRST = 0; //TX FIFO SPI Reset
SpiaRegs.SPIFFTX.bit.SPIFFENA = 0; //TX FIFO enhancements (what is that?)
SpiaRegs.SPIFFTX.bit.TXFFIENA = 0; //TX FIFO enable (0 = disable; 1 = enabled)
SpiaRegs.SPIFFTX.bit.TXFFIL = 0; //Transmit FIFO Interrupt Level Bits
SpiaRegs.SPIFFTX.bit.TXFFINT = 0; //TX FIFO Interrupt Bit (Read only)
SpiaRegs.SPIFFTX.bit.TXFFINTCLR = 0; //TX FIFO Interrupt Clear
//SpiaRegs.SPIFFTX.bit.SPIRST = 1; //TX FIFO SPI Reset CLEAR
//SpiaRegs.SPIFFTX.bit.TXFFST //TX FIFO status (tells you how many words there are (4 max) )
//SpiaRegs.SPIFFTX.bit.TXFIFO //TX FIFO reset

SpiaRegs.SPIFFRX.bit.RXFFIENA = 0; //RX FIFO Interrupt Enabler (0 = disable; 1 = enabled)
//SpiaRegs.SPIFFRX.bit.RXFFIL = //RX FIFO Interrupt Level Bits
SpiaRegs.SPIFFRX.bit.RXFFINT = 0; //RX FIFO Interrupt Flag
SpiaRegs.SPIFFRX.bit.RXFFINTCLR = 0; //RX FIFO Interrupt Flag Clear
//SpiaRegs.SPIFFRX.bit.RXFFOVF = //RX FIFO overflow flag
//SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = //RX FIFO overflow flag Clear
//SpiaRegs.SPIFFRX.bit.RXFFST = //RX FIFO Receive status
SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; //RX FIFO Reset

//SPI FIFO Control Register
SpiaRegs.SPIFFCT.bit.TXDLY = 0;


}
void spi_init()
{
SpiaRegs.SPICCR.all =0x000F; // Reset on, rising edge, 16-bit char bits
SpiaRegs.SPICTL.all =0x0006; // Enable master mode, normal phase,
// enable talk, and SPI int disabled.
SpiaRegs.SPIBRR.all =0x007F;
SpiaRegs.SPICCR.all =0x009F; // Relinquish SPI from Reset
SpiaRegs.SPIPRI.bit.FREE = 1; // Set so breakpoints don't disturb xmission
}
void spi_init_test()
{
//Configure the SPI configuration register bits

SpiaRegs.SPICCR.bit.SPISWRESET = 0; //SPI reset initialization

SpiaRegs.SPICCR.bit.CLKPOLARITY = 0; // controls the shift clock polarity refer to page 1990 of the technical documentation for more info

SpiaRegs.SPICCR.bit.HS_MODE = 0; // high speed mode SPI protocol
// need to configure SPI high speed mode with specific MUX values.
//Refer to table 17-4 of the technical reference document for the TMS320F28377D

//4 bits to determine the
//SpiaRegs.SPICCR.bit.SPICHAR = ?? // Character length control bits

//currently set the SPI loopback to 0
SpiaRegs.SPICCR.bit.SPILBK = 0; //SPI Loopback Mode Select

SpiaRegs.SPICCR.bit.SPICHAR = 0x000F; //The number of characters to be shifted in and out as a single character during one shift sequence

SpiaRegs.SPICCR.bit.SPISWRESET = 1; //Relinquish SPI from Reset

//SPI Operation Control Register

SpiaRegs.SPICTL.bit.CLK_PHASE = 0; //help control the CLKPOLARITY sequence
//refer to page 1902 for clarification

//Master mode = 1, Slave mode = 0
SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; //select the SPI A port to be a master or slave control peripheral

SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0; //Overrun Interrupt Enable

SpiaRegs.SPICTL.bit.SPIINTENA = 0; //control whether SPI will run in ISR or not

SpiaRegs.SPICTL.bit.TALK = 1; //Transmit Enable
//enables 4-pin option, ensure to enable the receiver's SPISTEn input pin --> technical documents notes page 1903

//SCLK speed
//baud rate
SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = 0x00007F; //set the SPI baud rate
//7Fh (R/W) = SPI Baud Rate = LSPCLK/128
}
void delay_loop()
{
long i;
for (i = 0; i < 1000000; i++) {}
}

void spare_code()
{

}


void error(void)
{
asm(" ESTOP0"); // Test failed!! Stop!
for (;;);
}

  • Andrew,

    Its good to hear that you have read through as much as you have. You should have a solid understanding of how our SPI module works!

    I think the first thing you would need to do is to define the functions that the external module is capable of. For example, if you are communicating with an external ADC, you may need functions like: SetADCMode, GetADCMode, EnableADC, DisableADC, StartADCConversion, etc. In all of these functions, the external ADC likely has a programming guide associated with it. It of course depends on what you are interfacing with that defines how to accomplish the above functions. i.e.  Send an 8-bit command and then 16-bit data. or send 8-bit command and then receive 16-bit data.

    What external module are you trying to communicate with? I see the LTC6804-2.h header included (but commented out) in your code. I checked on what that is and it looks like there are Arduino drivers already written. It should not be too difficult  to port that over to the F28377D SPI module. It looks like you would just need to replace the spi_write_read command with a custom one for the F28377S SPI module. The commands are already there.

    I hope this helps to get you started. Please do not hesitate to ask any more questions!

    -Mark

  • Hi Mark,

    Thank you for the quick response!

    I have been trying to implement the SPI peripheral to work with TI-RTOS but it looks like TI does not provide support for the TMS320F28377D. Unfortunately, this may put a halt in my current plans and I may have to dedicate a significant portion of my time creating an SPI driver to comply with the TI-RTOS module. Would you have any suggestions as to how to go about creating an SPI driver for TI-RTOS as I have never created an SPI driver before?

    On the other hand, I was able to get the SPI peripheral to somewhat work with the standalone peripheral code example to my LTC6804-2 module. However, the functions that you mention of were not as easy as you suggested (or at least I don't think so!). I am currently trying implement an SPI protocol amongst another module, more specifically DC2100A in case you were wondering. Over the last week, I have been trying to obtain data from the external module via "bit-banging" but I feel like that is not the way to implement SPI protocol between two devices as it seems very inefficient and time consuming.

    Do you have any suggestions as to how I am supposed to implement the external functions provided by the external module? I looked at their software guide and for some reason it seems to be a lot more ambiguous and confusing to implement. Would you recommend anyway to breaking this problem down so that it may be easier to comprehend? (see here: www.linear.com/.../5126 and feel free to look at the "software guide pdf" in the zip file they provided)

    Thank you,
    Andrew H

    Also, in case you were wondering what I have been coding, here it is:

    /*
    * main.c
    */




    //#include "LTC6804-2.h"
    //#include "C:\Users\hoanga\Desktop\DC2100A_Software_and_Users_Guide\DC2100A_Source_AppFW_v_1_2_0_GUI_v1_3_1\DC2100A_Source\Firmware\Source\LTC6804-2.h"

    #include <stdio.h>
    #include <inttypes.h>

    #include <C:\ti\controlSUITE\device_support\F2837xD\v100\F2837xD_common\inc\hw_spi.h>

    #include "F28x_Project.h"

    //#include "LTC6804-2.h"

    void delay_loop(void);
    void error(void);

    //user
    void spi_init_test(void);
    void spi_fifo_init_test(void);
    void spi_receive(Uint16 a);
    void spi_xmit(Uint16 a);
    void spi_fifo_init(void);
    void spi_init(void);

    void wakeup_spi(void);

    void main(void) {

    Uint16 rdata; // received data

    // Step 1. Initialize System C.ontrol:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
    InitSysCtrl();

    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xD_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
    // This function is found in F2837xD_Spi.c
    InitSpiaGpio();

    // Step 3. Clear all __interrupts and initialize PIE vector table:
    // Disable CPU __interrupts
    DINT;

    // Initialize PIE control registers to their default state.
    // The default state is all PIE __interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xD_PieCtrl.c file.
    InitPieCtrl();

    // Disable CPU __interrupts and clear all CPU __interrupt flags:
    IER = 0x0000;
    IFR = 0x0000;

    // 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 F2837xD_DefaultIsr.c.
    // This function is found in F2837xD_PieVect.c.
    InitPieVectTable();

    // Step 4. Initialize the Device Peripherals:
    spi_fifo_init(); // Initialize the Spi FIFO
    //FIFO needs to be initialized if DMA were to be utilized
    //spi_init(); // init SPI

    //spi_fifo_init_test(); //initialize user SPI FIFO
    spi_init_test(); //initialize user SPI
    wakeup_spi();

    // Step 5. User specific code


    for(;;)
    {
    // Wait until data is received
    //while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }

    // Read data

    //FCOM 1111
    //ICOM 0111
    //spi_xmit(0xFFFF); // 1111 1111
    //spi_xmit(0xFFFF); // 1111 1111
    //spi_xmit(0xFFFF); // 1111 1111
    //spi_xmit(0xFFFF); // 1111 1111
    //spi_xmit(0xFFFF); // 1111 1111
    spi_xmit(0x80); //pull CSB low

    spi_xmit(0x00); //RDCVA command
    spi_xmit(0x04); //RDCVA command continued

    spi_xmit(0x07); // respective PEC (packet error code)
    spi_xmit(0xC2); //PEC continued

    spi_xmit(0x00); //pull CSB high
    // Check against sent data
    //while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }
    rdata = SpiaRegs.SPIRXBUF;
    //if(rdata != sdata) error();

    printf("%" PRIu16 "\n", rdata);
    //DELAY_US(1000000);
    }
    }

    void spi_xmit(Uint16 a)
    {
    SpiaRegs.SPITXBUF=a;
    }

    void spi_receive(Uint16 a)
    {
    SpiaRegs.SPIRXBUF = a; //receiving value from the buffer?
    }

    void spi_fifo_init()
    {
    // Initialize SPI FIFO registers
    SpiaRegs.SPIFFTX.all=0xE040;
    SpiaRegs.SPIFFRX.all=0x2044;
    SpiaRegs.SPIFFCT.all=0x0;
    }

    void spi_fifo_init_test()
    {
    //SpiaRegs.SPIFFTX.bit.SPIRST = 0; //TX FIFO SPI Reset
    SpiaRegs.SPIFFTX.bit.SPIFFENA = 0x0; //TX FIFO enhancements (what is that?)
    SpiaRegs.SPIFFTX.bit.TXFFIENA = 0x0; //TX FIFO enable (0 = disable; 1 = enabled)
    SpiaRegs.SPIFFTX.bit.TXFFIL = 0x0; //Transmit FIFO Interrupt Level Bits
    SpiaRegs.SPIFFTX.bit.TXFFINT = 0x0; //TX FIFO Interrupt Bit (Read only)
    SpiaRegs.SPIFFTX.bit.TXFFINTCLR = 0x0; //TX FIFO Interrupt Clear
    //SpiaRegs.SPIFFTX.bit.SPIRST = 1; //TX FIFO SPI Reset CLEAR
    //SpiaRegs.SPIFFTX.bit.TXFFST //TX FIFO status (tells you how many words there are (4 max) )
    //SpiaRegs.SPIFFTX.bit.TXFIFO //TX FIFO reset

    SpiaRegs.SPIFFRX.bit.RXFFIENA = 0x0; //RX FIFO Interrupt Enabler (0 = disable; 1 = enabled)
    //SpiaRegs.SPIFFRX.bit.RXFFIL = //RX FIFO Interrupt Level Bits
    SpiaRegs.SPIFFRX.bit.RXFFINT = 0x0; //RX FIFO Interrupt Flag
    SpiaRegs.SPIFFRX.bit.RXFFINTCLR = 0x0; //RX FIFO Interrupt Flag Clear
    //SpiaRegs.SPIFFRX.bit.RXFFOVF = //RX FIFO overflow flag
    //SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = //RX FIFO overflow flag Clear
    //SpiaRegs.SPIFFRX.bit.RXFFST = //RX FIFO Receive status
    SpiaRegs.SPIFFRX.bit.RXFIFORESET = 0x1; //RX FIFO Reset

    //SPI FIFO Control Register
    SpiaRegs.SPIFFCT.bit.TXDLY = 0x0;


    }
    void spi_init()
    {
    SpiaRegs.SPICCR.all =0x000F; // Reset on, rising edge, 16-bit char bits
    SpiaRegs.SPICTL.all =0x0006; // Enable master mode, normal phase,
    // enable talk, and SPI int disabled.
    SpiaRegs.SPIBRR.all =0x007F;
    SpiaRegs.SPICCR.all =0x009F; // Relinquish SPI from Reset
    SpiaRegs.SPIPRI.bit.FREE = 1; // Set so breakpoints don't disturb xmission
    }
    void spi_init_test()
    {
    //Configure the SPI configuration register bits

    SpiaRegs.SPICCR.bit.SPISWRESET = 0; //SPI reset initialization
    SpiaRegs.SPICCR.bit.CLKPOLARITY = 0; // controls the shift clock polarity refer to page 1990 of the technical documentation for more info
    SpiaRegs.SPICCR.bit.HS_MODE = 0; // high speed mode SPI protocol
    SpiaRegs.SPICCR.bit.SPICHAR = 0x8; // Character length control bits
    SpiaRegs.SPICCR.bit.SPILBK = 0; //SPI Loopback Mode Select
    SpiaRegs.SPICCR.bit.SPISWRESET = 1; //Relinquish SPI from Reset

    //SPI Operation Control Register
    SpiaRegs.SPICTL.bit.CLK_PHASE = 0; //help control the CLKPOLARITY sequence
    SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; //select the SPI A port to be a master or slave; Slave = 0, Master = 1
    SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0; //Overrun Interrupt Enable
    SpiaRegs.SPICTL.bit.SPIINTENA = 0; //control whether SPI will run in ISR or not
    SpiaRegs.SPICTL.bit.TALK = 1; //Transmit Enable

    SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = 0x000013; //set the SPI baud rate
    //7Fh (R/W) = SPI Baud Rate = LSPCLK/128



    //all SPI status registers (flags) default value to 0, this just enforces it
    SpiaRegs.SPISTS.bit.BUFFULL_FLAG = 0;
    SpiaRegs.SPISTS.bit.INT_FLAG = 0;
    SpiaRegs.SPISTS.bit.OVERRUN_FLAG = 0;

    //all SPI priorities default set to 0, this just enforces it
    SpiaRegs.SPIPRI.bit.FREE = 0;
    SpiaRegs.SPIPRI.bit.PRIORITY = 0;
    SpiaRegs.SPIPRI.bit.SOFT = 0;
    SpiaRegs.SPIPRI.bit.STEINV = 0;
    SpiaRegs.SPIPRI.bit.TRIWIRE = 0;
    }
    void delay_loop()
    {
    long i;
    for (i = 0; i < 1000000; i++) {}
    }

    void spare_code()
    {

    }

    void wakeup_spi()
    {
    Uint16 rdata;
    //Wake up serial interface
    spi_xmit(0x00);
    DELAY_US(300); //tWAKE = 100 uS, datasheet recommended 100*3 uS delay time
    spi_xmit(0x00);
    DELAY_US(300); //tWAKE = 100 uS, datasheet recommended 100*3 uS delay time
    spi_xmit(0x00);
    DELAY_US(300); //tWAKE = 100 uS, datasheet recommended 100*3 uS delay time
    printf("Checking wakeup SPI protocol");
    rdata = SpiaRegs.SPIRXBUF;
    printf("%" PRIu16 "\n", rdata);
    printf("-----");
    }

    void error(void)
    {
    asm(" ESTOP0"); // Test failed!! Stop!
    for (;;);
    }
    /*!
    \brief Writes and read a set number of bytes using the SPI port.

    @param[in] uint8_t tx_data[] array of data to be written on the SPI port
    @param[in] uint8_t tx_len length of the tx_data array
    @param[out] uint8_t rx_data array that read data will be written too.
    @param[in] uint8_t rx_len number of bytes to be read from the SPI port.

    */
    /*
    void spi_write_read(Uint16 tx_Data[8],//array of data to be written on SPI port
    Uint16 tx_len, //length of the tx data array
    Uint16 *rx_data,//Input: array that will store the data read by the SPI port
    Uint16 rx_len //Option: number of bytes to be read from the SPI port
    )
    {
    Uint16 i;

    for(i = 0; i < tx_len; i++)
    {
    //spi_write(tx_Data[i]);
    SpiaRegs.SPITXBUF = tx_Data[i];
    }

    for(i = 0; i < rx_len; i++)
    {
    //rx_data[i] = (uint8_t)spi_read(0xFF);
    rx_data[i] = SpiaRegs.SPIRXBUF;
    }
    }
    */