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 with external hardware

Other Parts Discussed in Thread: CONTROLSUITE, TMS320F28377D

Hi,

I recently posted a while back regarding SPI protocol and it's required interface usage with an external module (DC2100A --> LTC6804-2) . As of the last few weeks, I have been dedicating my time attempting to map out bit readings using the external module datasheet and examples. However, I feel like this is not the proper method to go about SPI protocol and may be wasting my time trying to read every byte iteration and reading. The DC2100A model already has SPI functions that were utilized using a PIC controller, but I have been unsuccessful at importing or bringing over the code to CCS. I looked at the LTC6804-2_config.h and LTC-6804.h files but cannot find a way to go about this process.

Would you know of any method to go about importing or utilizing external hardware code (can be found in the DC2100A software guide: http://www.linear.com/solutions/5126)?

Thank you,

Andrew H

In addition, here is the code I have developed thus far:

/*
* 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_config.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 LTC_wakeup(void);
void LTC_read_voltages(void);
void LTC_ADC_conversion(void);
void LTC_ADC_poll(void);
void LTC_clear_cells(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
LTC_wakeup();
LTC_ADC_poll();
LTC_ADC_conversion();
LTC_clear_cells();
LTC_read_voltages();
//LTC6804_Init();
// Step 5. User specific code

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

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


// Check against sent data
//while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }
//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 = 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 = 0x4;//TX FIFO status (tells you how many words there are (4 max) )
SpiaRegs.SPIFFTX.bit.TXFIFO = 1; //release FIFO from reset//TX FIFO reset

SpiaRegs.SPIFFRX.bit.RXFIFORESET = 0; //Initialize RX FIFO Reset
SpiaRegs.SPIFFRX.bit.RXFFIENA = 0; //RX FIFO Interrupt Enabler (0 = disable; 1 = enabled)
SpiaRegs.SPIFFRX.bit.RXFFINT = 0; //RX FIFO Interrupt Flag
SpiaRegs.SPIFFRX.bit.RXFFINTCLR = 0; //RX FIFO Interrupt Flag Clear
SpiaRegs.SPIFFRX.bit.RXFFOVF = 0; //RX FIFO overflow flag
SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = 0;//RX FIFO overflow flag Clear
SpiaRegs.SPIFFRX.bit.RXFFIL = 0x0; //RX FIFO Interrupt Level Bits --> seems a bit important to stop receive garble
//SpiaRegs.SPIFFRX.bit.RXFFST = //RX FIFO Receive status
SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; //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 //current somewhat working setting
SpiaRegs.SPICCR.bit.SPICHAR = 0x0060; // 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
//13h (R/W) = SPI Baud Rate = LSPCLK/20

//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;

//turn of emulation mode
SpiaRegs.SPIRXEMU = 0;
}
void delay_loop()
{
long i;
for (i = 0; i < 1000000; i++) {}
}
void LTC_wakeup()
{

//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 \n");
printf("-----");
}
void LTC_ADC_poll()
{
spi_xmit(0x80);
spi_xmit(0x9F);
spi_xmit(0x14);
spi_xmit(0x1C);
spi_xmit(0x48);
Uint16 rdata;
rdata = SpiaRegs.SPIRXBUF;
printf("%" PRIu16 "\n", rdata);
spi_xmit(0x00);
}
void LTC_ADC_conversion()
{
spi_xmit(0x80);
spi_xmit(0x03);
spi_xmit(0x70);
spi_xmit(0xAF);
spi_xmit(0x42);
Uint16 rdata;
rdata = SpiaRegs.SPIRXBUF;
printf("%" PRIu16 "\n", rdata);
spi_xmit(0x80);
}
void LTC_read_voltages()
{
Uint16 rdata;

// Read data
spi_xmit(0x80); //pull CSB low
rdata = SpiaRegs.SPIRXBUF;
printf("%" PRIu16 "\n", rdata);
spi_xmit(0x00); //RDCVA command
rdata = SpiaRegs.SPIRXBUF;
printf("%" PRIu16 "\n", rdata);
spi_xmit(0x04); //RDCVA command continued
rdata = SpiaRegs.SPIRXBUF;
printf("%" PRIu16 "\n", rdata);
spi_xmit(0x07); // respective PEC (packet error code)
rdata = SpiaRegs.SPIRXBUF;
printf("%" PRIu16 "\n", rdata);
spi_xmit(0xC2); //PEC continued

rdata = SpiaRegs.SPIRXBUF;
printf("%" PRIu16 "\n", rdata);
DELAY_US(1000);

spi_xmit(0x00); //pull CSB high
}
void LTC_clear_cells()
{
spi_xmit(0x80);
spi_xmit(0x07);
spi_xmit(0x11);
spi_xmit(0xC9);
spi_xmit(0xC0);
Uint16 rdata;
rdata = SpiaRegs.SPIRXBUF;
printf("%" PRIu16 "\n", rdata);
spi_xmit(0x80);
}
void error(void)
{
asm(" ESTOP0"); // Test failed!! Stop!
for (;;);
}

  • Andrew. 

    To me it looks like you are on the right track for building your drivers. Judging by the file structure described in the User Guide, your goal is to replace the PIC functions with the c28x functions. the LTC Driver files are intended to be independent of the PIC Microcontroller.  Unfortunately the process of porting code from one architecture to another may not be straightforward. I don't see anything in the drivers you link that would be a showstopper. The F28377D SPI has DMA and also the 16 level FIFO. . I am not aware of any tools to import PIC code to C2000 compatible code. Though this would be a nice tool to have :) 

    What specific issues are you having? Are you just concerned that this process is going to more complex than originally anticipated? Is the C28x SPI not working as you hoped. I think the next step is to sit down and really understand the flow of the existing drivers. Once you truly understand what it is doing, you should be able to pull the functions you require into a custom c28x driver for the same functionality. 

    If you have any specific questions on the behavior of the c28x SPI, I would be glad to help. I can only give you general advice when it comes to porting code, or implementing your system. Maybe others here on the forum could chime in with their experiences?

    -Mark

    Side note:  Please try to limit the number of duplicate posts, I know you have posted a similar thread elsewhere. 

  • Hi Mark,

    Currently I have been just trying to obtain an SPI receive signal from my external hardware. I have tried a few things since my last post. I tried to set the baud rate and LSPCLK accordingly to my external hardware's frequency operation by changing these registers:

    ClkCfgRegs.LOSPCP.bit.LSPCLKDIV = 0x6; //LSPCLK (200 Mhz)/10 (System clock speed CPU initially 200 Mhz)

    SpiaRegs.SPIBRR.all =0x0014; //LSPCLK/20 for a total SPIBRR of 1Mhz

    After that I modified the SPI initialization found in the ControlSuite example codes:

    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 =0x0014;

       SpiaRegs.SPICCR.all =0x008F;         // Relinquish SPI from Reset

       SpiaRegs.SPIPRI.bit.FREE = 1;                // Set so breakpoints don't disturb xmission

    }

    by only removing loopback mode.

    I have been trying to get any sort of data back by observing the SPIDAT and SPIRXBUF registers, but I only seem to be receiving 0xFFFF all the time, but I feel like  I should be able to obtaining different data. I have also tried creating a small delay between transmission times so that perhaps the SPIDAT has time to load data onto the TMS320F28377D device, but still can't seem to pinpoint the exact issue. Also, in loopback mode operation, the SPI functionality of the Delfino controlcard seems to be working just fine.

    Observed in the following figure below is the SPI functionality I have been trying to execute over the past few weeks:

    I tried to mimic this SPI functionality in my following like this:

    // Transmit data
    spi_xmit(0x00);
    spi_xmit(0x80);
    spi_xmit(0x06);
    spi_xmit(0xEA);
    spi_xmit(0x80);

         rdata = SpiaRegs.SPIRXBUF;

    As of right now, I haven't really delved into any of the DMA functions, but perhaps that may be the next best course of action in order to receive some sort of signal from my external hardware via SPI? Would you have any advice on how to get the SPI functionality working and starting?

    Thank you,

    Andrew H

    P.S Sorry about the double post, I posted a reply to our previous conversation, but you never got back to me so I had to create another post.

    Also note, here is my fifo initialization code (copied directly from the ControlSuite Example loopback spi code):

    void spi_fifo_init()
    {
    // Initialize SPI FIFO registers
    SpiaRegs.SPIFFTX.all=0xE040;

    SpiaRegs.SPIFFRX.all=0x2044;
    SpiaRegs.SPIFFCT.all=0x0;
    }

  • I have a basic question, In the original code you do have the SPI GPIO configuration. Has this dropped out of your code somehwhere? are you seeing the proper signals on the pins you require? Do you have any scope plots of the SPI pins?

    If all you do is enable the SPI loopback, you see the receive path working? Can you try this with external loopback? Wire the SPI SIMO to SOMI pin and verify that you are receiving what you are transmitting.

    -Mark
  • Hi Mark,

    Shown above is my oscilloscope measurement of the SPI SOMI (dark blue) and SPICLK (light blue).

    The SPI GPIO has not changed or disappeared since my last post, I just posted what I thought was relevant code in my previous post. I tried an external loopback with the SPI SIMO and SOMI pins and received the correct values for SPITXBUF going into the SPIDAT, but incorrect data going out into the SPIRXBUF. However, the SPIRXEMU register seems to be reading as it should be. I also noticed that the SPITXBUF sends out data in left justified format and SPIRXEMU as right justified format, this was to be expected.

    I think it may be something to do with the SPIDAT information load time onto the SPIRXBUF. I still am receiving the correct values of the SPITXBUF -> SPIRXBUF but the information takes a great deal longer to reach SPIRXBUF when compared to SPIRXEMU.

    In addition, I changed my SPICHAR to 8 bits/character because I made a mistake sending 2 hex bits expecting 4 hex values. That however, still does not solve the incorrect SPIDAT buffering to be expected from my SPI module.

    Let me know what you think and if there is anything I can do to fix my current setup.

    Below I have attached my register readings and code component:

    then next step:

    and my code sample I'm using:

    // Step 5. User specific code

    for(;;)
    {
    DELAY_US(1000000);
    spi_xmit(0xAB);
    rdata = SpiaRegs.SPIRXBUF;
    printf("%" PRIu16 "\n", rdata);

    DELAY_US(1000);
    spi_xmit(0xFF);
    rdata = SpiaRegs.SPIRXBUF;
    printf("%" PRIu16 "\n", rdata);

    DELAY_US(1000000);
    spi_xmit(0x11);
    rdata = SpiaRegs.SPIRXBUF;
    printf("%" PRIu16 "\n", rdata);

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

    //DELAY_US(1000000);
    }
    }

    Thank you,

    Andrew H

    main.c
    #include <stdio.h>
    #include <inttypes.h>
    
    #include "F28x_Project.h"
    
    //#include "LTC6804-2_Registers.h"
    //#include "LTC6804-2_Config.h"
    //#include "LTC6804-2.h"
    //#include "LTC6804-2.c"
    
    void delay_loop(void);
    void error(void);
    
    //user
    void spi_init_test(void);
    void spi_fifo_init_test(void);
    void spi_xmit(Uint16 a);
    void spi_fifo_init(void);
    void spi_init(void);
    
    
    void LTC_wakeup(void);
    void LTC_read_voltages(void);
    void LTC_ADC_start(void);
    void LTC_clear_cells(void);
    void LTC_refon_set(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();
    
    	   EALLOW;
    	   ClkCfgRegs.LOSPCP.bit.LSPCLKDIV = 0x6; //LSPCLK (200 Mhz)/10
    	   EALLOW;
    	// Step 4. Initialize the Device Peripherals:
    	   spi_fifo_init_test(); //initialize user SPI FIFO
    	   spi_init_test(); //initialize user SPI
    	   //spi_fifo_init();
    	   //spi_init();
    
    	   LTC_wakeup();
    	   //LTC_read_voltages();
    	   //LTC_ADC_start();
    	   //LTC_clear_cells();
    	   //LTC_refon_set();
    	   //LTC_ADC_start();
    	   LTC_read_voltages();
    
    	// Step 5. User specific code
    
    	   for(;;)
    	   {
    		   	  DELAY_US(1000000);
    		   	  spi_xmit(0xAB);
    		      rdata = SpiaRegs.SPIRXBUF;
    		      printf("%" PRIu16 "\n", rdata);
    
    		      DELAY_US(1000);
    		      spi_xmit(0xFF);
    		      rdata = SpiaRegs.SPIRXBUF;
    		      printf("%" PRIu16 "\n", rdata);
    
    		      DELAY_US(1000000);
    		      spi_xmit(0x11);
                  rdata = SpiaRegs.SPIRXBUF;
                  printf("%" PRIu16 "\n", rdata);
    
                  DELAY_US(1000000);
                  DELAY_US(1000000);
    		       //printf("%" PRIu16 "\n", rdata);
    
    		    //DELAY_US(1000000);
    		}
    }
    
    void spi_xmit(Uint16 a)
    {
    	SpiaRegs.SPITXBUF = a;
    }
    void spi_fifo_init_test()
    {
    	SpiaRegs.SPIFFTX.bit.SPIRST = 0; //TX FIFO SPI Reset
    	SpiaRegs.SPIFFTX.bit.SPIFFENA = 1; //TX FIFO enhancements --> enables expansion of up to 16 bits
    	SpiaRegs.SPIFFTX.bit.TXFFIENA = 0; //TX FIFO enable interrupt (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 = 0x4;//TX FIFO status (tells you how many words there are (4 max) //read only
    	SpiaRegs.SPIFFTX.bit.TXFIFO = 1; //release FIFO from reset//TX FIFO reset
    
    	SpiaRegs.SPIFFRX.bit.RXFIFORESET = 0; //Initialize RX FIFO Reset
    	SpiaRegs.SPIFFRX.bit.RXFFIENA = 0; //RX FIFO Interrupt Enabler (0 = disable; 1 = enabled)
    	//SpiaRegs.SPIFFRX.bit.RXFFINT = 0; //RX FIFO Interrupt Flag
    	SpiaRegs.SPIFFRX.bit.RXFFINTCLR = 0; //RX FIFO Interrupt Flag Clear
    	//SpiaRegs.SPIFFRX.bit.RXFFOVF = 0; //RX FIFO overflow flag
    	SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = 0;//RX FIFO overflow flag Clear
    	SpiaRegs.SPIFFRX.bit.RXFFIL = 0x1; //RX FIFO Interrupt Level Bits --> seems a bit important to stop receive garble
    	//SpiaRegs.SPIFFRX.bit.RXFFST = //RX FIFO Receive status
    	SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; //RX FIFO Reset
    
    	//SPI FIFO Control Register
    	SpiaRegs.SPIFFCT.bit.TXDLY = 0x0;
    
    
    }
    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 =  0x000F; // Character length control bits
    		   SpiaRegs.SPICCR.bit.SPICHAR = 0x0008; //8 bits --> 2 hex characters
    		   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.OVERRUNINTENA = 0; //Overrun Interrupt Enable
    		   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.TALK = 1; //Transmit Enable
    		   SpiaRegs.SPICTL.bit.SPIINTENA = 0; //control whether SPI will run in ISR or not
    
    		   //LSPCLK = 50MHZ
    		   //SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = 0x0031; //set the SPI baud rate
    		   SpiaRegs.SPIBRR.all = 0x0020;
    		   //SpiaRegs.SPIBRR.all = 0x007F;
    		   //7Fh (R/W) = SPI Baud Rate = LSPCLK/128
    		   //13h (R/W) = SPI Baud Rate = LSPCLK/20
    
    
    
    		   //all SPI status registers (flags) default value to 0, this just enforces it
    		   //SpiaRegs.SPISTS.bit.BUFFULL_FLAG = 1;
    		   //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;
    
    		   //turn off emulation mode
    		   SpiaRegs.SPIRXEMU = 0;
    
    
    }
    void delay_loop()
    {
        long      i;
        for (i = 0; i < 1000000; i++) {}
    }
    void LTC_wakeup()
    {
    
      	 //Wake up serial interface
        spi_xmit(0x00);
        DELAY_US(1);
        //printf("Checking wakeup SPI protocol \n");
    	//printf("----- \n");
    }
    void LTC_ADC_start()
    {
    	//printf("LTC ADC conversion \n");
    	spi_xmit(0x80);
    	spi_xmit(0x02);
    	spi_xmit(0x5B);
    	spi_xmit(0x1E);
        //printf("---------- \n");
    }
    
    void LTC_clear_cells()
    {
    	spi_xmit(0x87);
    	spi_xmit(0x11);
    	spi_xmit(0xB9);
    	spi_xmit(0xD4);
    	Uint16 rdata;
        rdata = SpiaRegs.SPIRXBUF;
        //printf("%" PRIu16 "\n", rdata);
    	spi_xmit(0x80);
    }
    void LTC_refon_set()
    {
    	spi_xmit(0x80);
    	spi_xmit(0x02);
    
    	spi_xmit(0x5B);
    	spi_xmit(0x1E);
    }
    void LTC_read_voltages()
    {
    	Uint16 rdata;
    		 spi_xmit(0x80);
    		 DELAY_US(224);
    		 //while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }
    		 //rdata = SpiaRegs.SPIRXBUF;
    
    		 spi_xmit(0x06);
    		 DELAY_US(224);
    		 //while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }
    		 //rdata = SpiaRegs.SPIRXBUF;
    
    		 spi_xmit(0xEA);
    		 DELAY_US(224);
    		 //while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }
    		 //spi_xmit(0x0080);
    
    		 spi_xmit(0x80);
    		 DELAY_US(224);
    		 //while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }
    		 //rdata = SpiaRegs.SPIRXBUF;
    }
    

  • Andrew,

    Thanks for confirming the GPIO setup. As I warned, it was a basic question. Sometimes those things slip through during a debug and you don't realize it.

    Have you ever at any point gotten the LTC to respond with any data at all? To me, it looks like the LTC is not ever responding. you don't see any valid transitions on the SOMI line. It seems as though the SPI itself is operating as expected. If you have not ever gotten a valid (or any) transfer from the LTC, I would suggest digging into the HW requirements of the LTC. Ensure it is hooked up and configured properly. Check your clock polarity, phase, word length, etc to make sure they match. What is the actual frequency you are running at? Is it below 25MHz? which GPIOs are you using on the C28x?

    One suggestion I have is to add a delay between spi_xmit() and reading SPIRXBUF. It should be at least the length of time it will take to clock the entire word out of the chip. The most straightforward way for now is to poll the SPIFFRX.bit.FFSX < 1. Here you are waiting until the RX has received a single word.

    I apologize for all of the questions. I am hoping one of them triggers something for you. These are the things that you need to verify when writing a HW driver for an external chip.

    I hope this helps a bit more!
    -Mark
  • Hi Mark,

    I welcome all your questions as they may help guide me through my peripheral interfacing with the SPI. Moving onwards, I just figured out that the external hardware uses CPOL and CPHA = 1, so I set SpiaRegs.SPICTL.bit.CLK_PHASE = 1; and SpiaRegs.SPICCR.bit.CLKPOLARITY = 1; respectively. My SPICHAR is set to 0x7 (8bits/character or 2 hex values) and baud rate set to 1 Mhz (max speed of the external hardware). I configured the LSPCLK to change from SYSCLK/4 (default) to SYSCLK/10 using the ClkCfgRegs.LOSPCP.bit.LSPCLKDIV = 0x006; register. I tried including a delay in a variety of ways, using interrupts, DELAY_US(), and SpiaRegs.SPIFFRX.bit.RRST checkers, but none seem to be polling any data to my hardware.

    It seems to me that I am able to transmit data at least out of the TMS320F28377D control card but for some reason the receive buffer receives the very same information. I disabled my SPI loopback bit as well so it doesn't explain why I may still be receiving a loopback to my control card. The hardware wire connection is hooked up properly (at least I think so!) with the control pins -> GPIO16, GPIO17, GPIO18, GPIO19 (67, 69, 71, 73 on the control card) respectively to my external hardware.

    I feel like I must be missing something very trivial to my project and that once I solve this communication issue, I can be on my way.
    Let me know if you can think of any other questions that might aid in getting SPI working with this thing.

    Thank you,
    Andrew H

    Below here is my SPI setup configuration for FIFO and SPI:

    void spi_init()
    {
    SpiaRegs.SPICCR.bit.SPISWRESET = 0;
    SpiaRegs.SPICCR.bit.CLKPOLARITY = 1; //important that CPHA and CPOL = 1 reference to LTC6804-2 timing datasheet
    SpiaRegs.SPICCR.bit.SPILBK = 0;
    SpiaRegs.SPICCR.bit.SPICHAR = 0x7; //8bit/char for 2 hex values
    //SpiaRegs.SPICCR.bit.SPICHAR = 0xF;
    SpiaRegs.SPICCR.bit.HS_MODE = 0;

    SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0;
    SpiaRegs.SPICTL.bit.CLK_PHASE = 1; //important that CPHA and CPOL = 1 reference to LTC6804-2 timing datasheet
    SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; //master = 1, slave = 0
    SpiaRegs.SPICTL.bit.TALK = 1;
    SpiaRegs.SPICTL.bit.SPIINTENA = 0; //enable/disable interrupts

    //SpiaRegs.SPISTS --> not used..yet

    //SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = 0x20; //baud rate LSPCLK/#
    SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = 0x60; //some arbitrary slower speed

    SpiaRegs.SPIPRI.bit.FREE = 1;
    SpiaRegs.SPICCR.bit.SPISWRESET = 1;
    }


    void spi_fifo()
    {
    SpiaRegs.SPIFFTX.bit.SPIRST = 0;
    SpiaRegs.SPIFFTX.bit.TXFFIENA = 1;
    SpiaRegs.SPIFFTX.bit.TXFIFO = 1;
    SpiaRegs.SPIFFTX.bit.SPIFFENA = 1;
    //SpiaRegs.SPIFFTX.bit.TXFFST
    SpiaRegs.SPIFFTX.bit.TXFFINTCLR = 0;
    SpiaRegs.SPIFFTX.bit.TXFFIENA = 0; //when ISR is used, enable this!
    SpiaRegs.SPIFFTX.bit.TXFFIL = 0;

    //SpiaRegs.SPIFFRX.bit.RXFFOVF
    SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = 0;
    SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1;
    //SpiaRegs.SPIFFRX.bit.RXFFST //read status
    //SpiaRegs.SPIFFRX.bit.RXFFINT = 0;
    SpiaRegs.SPIFFRX.bit.RXFFINTCLR = 0;
    SpiaRegs.SPIFFRX.bit.RXFFIENA = 0; //when ISR is used, enable this!
    //it is an interrupt flag enabler
    //SpiaRegs.SPIFFRX.bit.RXFFIL

    SpiaRegs.SPIFFCT.bit.TXDLY = 0;

    SpiaRegs.SPIFFTX.bit.SPIRST = 1;
    }
  • Hi again,

    This is just an update to hooking up my SPI setup to my external hardware. It looks like I may have made a mistake with the CPOL and CPHA being incorrectly configured on the TI CCS side. In the external module's datasheet (LTC6804-2) it operates with CPOL = 1 and CPHA = 1. In addition, chunking data onto the SPITXBUF required that I shift it by << 8 in order to correctly transmit 8 bit information. Overall, there were a variety of small things that all needed adjustment (ie.use a GPIO for constant low CS as opposed to SPISTEA). Once again, thanks for your help Mark!

    Best Regards,

    Andrew H

  • Glad that you figured it out!

    Since it looks like you spent some solid time getting a c28x to work with the LTC, would you want to attach your code here?  It might benefit others who are trying to do the same thing! 

    -Mark