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.

CCS/TMDSDOCK28335: SPI Connection Between TMDSDOCK28335/CC3200-LAUNCHXL

Part Number: TMDSDOCK28335
Other Parts Discussed in Thread: CC3200-LAUNCHXL, CC3200

Tool/software: Code Composer Studio

Hello everyone,

I'm trying to send two characters of eight bits each from the CC3200-LAUNCHXL (master) to the TMDSDOCK28335 (slave), and also send two characters of eight bits each back to the CC3200-LAUNCHXL from the TMDSDOCK28335 simultaneously. The written code sends the characters 'A' and 'B' from the CC3200-LAUNCHXL to the TMDSDOCK28335 while sending 'C' and 'D' from the TMDSDOCK28335 to the CC3200-LAUNCHXL. On the next transfer, the same characters are sent, but in reverse order ('B' and 'A' to the TMDSDOCK28335, and 'D' and 'C' to the CC3200-LAUNCHXL). Basically, the letters are swapped around before each transfer, but 'A' and 'B' is always going from the CC3200-LAUNCHXL to the TMDSDOCK28335, and 'C' and 'D' is always going from the TMDSDOCK28335 to the CC3200-LAUNCHXL.

The CC3200-LAUNCHXL successfully sends 'A' and 'B' each time, for I can read the receive registers on the TMDSDOCK28335 and verify they are correct. But when I try to send 'C' and 'D' from the TMDSDOCK28335 to the CC3200-LAUNCHXL, I always get '!', ''', or '.'. So for some reason, the contents of the transfer register on the TMDSDOCK28335 are changing during the actual transfer. Does anyone know what the problem could be?

Test Data Example:


I tried hardcoding some HEX values into SpiaRegs.SPITXBUF, and this is what generally happens. Lets say I have this setup of SpiaRegs.SPITXBUF = 0xB2E9 (which is 0b1011001011101001), then I expected the receive registers on the CC3200-LAUNCHXL side to have g_ucRxBuff[0] = 0b11101001 (0xE9) and g_ucRxBuff[1] = 0b10110010 (0xB2), but what I read is g_ucRxBuff[0] = 0b01110100 (0x74) and g_ucRxBuff[1] = 0b11011001 (0xD9). If you take the msb of g_ucRxBuff[0] and placed it right behind the lsb (where it basically becomes the lsb, but does not replace the originally lsb) of g_ucRxBuff[1], and shift both g_ucRxBuff[0] and g_ucRxBuff[1] bit values to left one time, then you get the correct HEX values (g_ucRxBuff[0] = 0xE9 and g_ucRxBuff[1] = 0xB2).

CC3200-LAUNCHXL Code

//Code is based off of "SPI Demo" that came with the CC3200-LAUNCHXL board

//Standard Includes
#include <string.h>

//Driver Library Includes
#include "hw_types.h"
#include "hw_memmap.h"
#include "hw_common_reg.h"
#include "hw_ints.h"
#include "spi.h"
#include "rom.h"
#include "rom_map.h"
#include "utils.h"
#include "prcm.h"
#include "uart.h"
#include "interrupt.h"

//Common Interface Includes
#include "uart_if.h"
#include "pinmux.h"

//Useful Macros
#define SPI_IF_BIT_RATE  100000 //in bits per second (bps)
#define TR_BUFF_SIZE     2

//*****Start of Global Variables*****
static unsigned char g_ucTxBuff[TR_BUFF_SIZE];
static unsigned char g_ucRxBuff[TR_BUFF_SIZE];
static unsigned char ucTxBuffNdx;
static unsigned char ucRxBuffNdx;

//Not too sure what this stuff does here, but came with SPI example
#if defined(ccs)
extern void (* const g_pfnVectors[])(void);
#endif
#if defined(ewarm)
extern uVectorEntry __vector_table;
#endif
//*****End of Global Variables*****

//*****Start of Board Initialization & Configuration***** (Came with SPI Demo as well)
static void
BoardInit(void)
{
/* In case of TI-RTOS vector table is initialize by OS itself */
#ifndef USE_TIRTOS
  //
  // Set vector table base
  //
#if defined(ccs)
    MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
#endif
#if defined(ewarm)
    MAP_IntVTableBaseSet((unsigned long)&__vector_table);
#endif
#endif
    //
    // Enable Processor
    //
    MAP_IntMasterEnable();
    MAP_IntEnable(FAULT_SYSTICK);

    PRCMCC3200MCUInit();
}
//*****End of Board Initialization & Configuration*****

void main(){

   //Character generator variable
   char character1 = 'A';
   char character2 = 'B';

   //Initialize Board Configurations
   BoardInit();

   //Muxing UART and SPI Lines
   //All this does is configure pins for MOSI, MISO, Chip Select, and Clock.
   PinMuxConfig();

   //Enable the SPI Module Clock
   //Enables clock to peripheral
   //PRCM_GSPI = Macro for the SPI Peripheral (0x00000003)
   //PRCM_RUN_MODE_CLK = Ungates clock to the peripheral (could also be PRCM_SLP_MODE_CLK
   //which keeps the clocks ungated in sleep)
   MAP_PRCMPeripheralClkEnable(PRCM_GSPI,PRCM_RUN_MODE_CLK);

   //Reset the Peripheral
   //PRCM_GSPI = Macro for the SPI Peripheral (resets the SPI Peripheral)
   MAP_PRCMPeripheralReset(PRCM_GSPI);

   //Reset SPI
   //Performs a software reset to the SPI Module
   //GSPI_BASE = Macro for the SPI Base Address (0x44021000)
   MAP_SPIReset(GSPI_BASE);

   //Configure SPI Interface (all values are MACROS)
   //1st argument is base address of SPI Module (which is GSPI_BASE)
   //2nd argument is rate of clock being supplied to SPI Module
   //3rd argument is the desired bit rate (which is defined in the "useful macro" section above)
   //4th argument is SPI_MODE_MASTER, which configures board as the master
   //5th argument is SPI_SUB_MODE_0, which sets clock polarity and phase to 0
   //6th argument is logical OR combination, which sets chip select to be controlled by software (SPI_SW_CTRL_CS),
   //sets module to 4 pin mode (SPI_4PIN_MODE), sets turbo mode off (SPI_TURBO_OFF) and I have no idea what turbo mode is,
   //sets chip select to be active low (SPI_CS_ACTIVELOW), and sets the bit length to 16 bits, or 2 characters (SPI_WL_16)
   MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI),SPI_IF_BIT_RATE,SPI_MODE_MASTER,SPI_SUB_MODE_0,
   (SPI_SW_CTRL_CS |
   SPI_4PIN_MODE |
   SPI_TURBO_OFF |
   SPI_CS_ACTIVELOW |
   SPI_WL_16));

   //Enable SPI for Communication
   //GSPI_BASE = Macro for the SPI Base Address (0x44021000)
   MAP_SPIEnable(GSPI_BASE);

   while(1){
   //Load two 8 bit characters into transfer buffer
   g_ucTxBuff[0] = character1;
   g_ucTxBuff[1] = character2;

   //Send characters over MOSI pin
   //1st argument is base address of SPI Module (GSPI_BASE)
   //2nd argument is pointer to transfer buffer (g_ucTxBuff)
   //3rd argument is pointer to receive buffer (g_ucRxBuff)
   //4th argument is size of data in bytes (1 byte = 8 bits)
   //5th argument is logical OR that enable chip select pin before transmission,
   //and disables chip select pin after transmission (SPI_CS_ENABLE|SPI_CS_DISABLE)
   MAP_SPITransfer(GSPI_BASE,g_ucTxBuff,g_ucRxBuff,2,SPI_CS_ENABLE|SPI_CS_DISABLE);

   //character generator
   if(character1==65){character1 = 'B';}
   else{character1 = 'A';}
   if(character2==66){character2 = 'A';}
   else{character2 = 'B';}
   UtilsDelay(100000);
   }
   //while(1){}
}

TMDSDOCK28335 Code

//Code Based off of TMS320F28335 SPI Example

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

//Prototype statements for functions found within this file.
void spi_fifo_init(void);
void spi_init(void);

//Global variables (used to read registers)
unsigned char rdata1;
unsigned char rdata2;
unsigned char sdata[2] = {'C','D'};

void main(void){

   //Initialize System Control:
   //PLL, WatchDog, enable Peripheral Clocks
   //This example function is found in the DSP2833x_SysCtrl.c file.
   InitSysCtrl();

   //Initialize GPIO:
   //This example function is found in the DSP2833x_Gpio.c file and
   //illustrates how to set the GPIO to it's default state.
   //Setup only the GP I/O only for SPI-A functionality
   //This function is found in DSP2833x_Spi.c
   InitSpiaGpio();

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

   spi_fifo_init();   // Initialize the Spi FIFO
   spi_init();        // init SPI

   //User specific code:
   //Interrupts are not used in this example.
   for(;;)
   {
     //Load Transfer Buffer
     SpiaRegs.SPITXBUF = sdata[1]|(sdata[0] << 8);

     //character generator
     if(sdata[0]==67){sdata[0] = 'D';}
     else{sdata[0] = 'C';}
     if(sdata[1]==68){sdata[1] = 'C';}
     else{sdata[1] = 'D';}

     //Wait until data is received
     while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }
     rdata1 = SpiaRegs.SPIRXBUF & 0xFF;
     rdata2 = (SpiaRegs.SPIRXBUF & 0xFF00) >> 8;
   }
}

void spi_init(){

   //SPICCR is a 8 bit register
   //Bit 7 (Software Reset): Set to 0, must be cleared before configuration
   //Bit 6 (Clock Polarity): Set to 0, data outputted on rising edge and data incoming is falling edge
   //Bit 5 (Reserved): No writing allowed
   //Bit 4 (SPI Loopback): Set to 0 to disable, only for internal test only
   //Bit 3-0 (Character length bits): Set to 0b1111 for 16 bit character (CC3200 is sending two character totaling 16 bits)
   SpiaRegs.SPICCR.all =0x000F;

   //SPICTL is a 8 bit register
   //Bit 7-5 (Reserved): No writing allowed
   //Bit 4 (Overrun Interrupt Enable): Set to 0 for the time being, just trying to do a simple SPI connection
   //Bit 3 (Clock Phase): Set to 0, normal SPI clocking scheme (without being delayed one-half cycle)
   //Bit 2 (Master/Slave bit): Set to 0 to be the slave
   //Bit 1 (Talk bit): Set to 1, trying to send data back
   //Bit 0 (SPI Interrupt Enable): Set to 0, not worried about interrupts right now
   SpiaRegs.SPICTL.all =0x0002;

   //This register does not matter since clock is coming from CC3200-LAUNCHXL
   SpiaRegs.SPIBRR =0x000F;

   //SPICCR is a 8 bit register
   //Bit 7 (Software Reset): Set to 1, must be set when ready for data transmission
   //Bit 6 (Clock Polarity): Set to 0, data outputted on rising edge and data incoming is falling edge
   //Bit 5 (Reserved): No writing allowed
   //Bit 4 (SPI Loopback): Set to 0 to disable, only for internal test only
   //Bit 3-0 (Character length bits): Set to 0b1111 for 16 bit character (CC3200 is sending two character totaling 16 bits)
   SpiaRegs.SPICCR.all =0x008F;

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

void spi_fifo_init(){

   //Initialize SPI FIFO registers
   SpiaRegs.SPIFFTX.all=0xE040;
   SpiaRegs.SPIFFRX.all=0x204f;
   SpiaRegs.SPIFFCT.all=0x0;
}

  • Dalen,

    Have you tried to use a oscilloscope and looked at the data that is being transmitted? Your data would be correct, if you shifted it, so I am wondering if somewhere in this shifting process something is going wrong.

    Also you can try sending only one byte, and see what you receive on the CC3200 side.

    Let me know your findings,

    Vince Rodriguez
  • I tried sending one byte at a time, and turns out the same thing is happening as well. Although it does not fix the problem, I did come up with a "quick fix" solution that has not failed me yet.

    unsigned int char_array_to_int = (g_ucRxBuff[1] << 8)|(g_ucRxBuff[0] & 0xFF);
    unsigned int store_msb = (char_array_to_int >> 15) & 0x0001;
    unsigned int keep_bits_except_lsb (char_array_to_int << 1) & 0xFFFE;
    unsigned int correct_integer = keep_bits_except_lsb|store_msb;
  • Dalen,

    Have you checked the whether you are checking the data on the rising or falling edge of the clock? I would check and ensure both the CC3200 is C2000 are the same.


    VR
  • The data is being checked on the rising edge, and yes both CC3200 and C2000 have the same clock polarity and phase, which is 0.

    I did make a change since posting this code. The word length is now 8 (SPI_WL_8) and the problem still exist. The last HEX value I read was 0x7F77, and the code I wrote above gives me 0xEEFE. So I flipped the lsb and it gives me 0xEEFF, which is what I was looking for.
  • Nevermind, flipping the lsb does not work. Here are more data values if it helps:
    What I should be receiving What I am actually receiving using the "quick fix" code above that I wrote
    0x0011 0x0080 0x0010
    0xAAAA 0x5555 0xAAAA
    0x5555 0xAA2A 0x5554
    0xFFFF 0xFF7F 0xFFFE
    0x0000 0x0000 0x0000
    0xABCD 0xE655 0xABCC
    0x274E 0xA713 0x274E
  • Sorry, I tried to make three columns to display the data under "What I should be receiving", "What I am actually receiving", and "using the "quick fix" code above that I wrote".
  • I might see the problem.

    In the C2000 Code, change the SPICCR register to this :

    SpiaRegs.SPICCR.all =0x000E;

    or you can set the SPICHAR value by using this line,

    SpibRegs.SPICCR.bit.SPICHAR = 15; //16-bit character

    When setting the SPICHAR, you have to do the number of chars you want - 1.

    Let me know if this helps!

    Vince Rodriguez
  • Hi Vincent,

    Thank you so much for your help. Unfortunately, it did not fix the problem. We can go ahead and close this thread down because I want to update the problem with the latest code in another thread.