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.
Hello everyone,
For those who have been helping me in the past (much appreciated by the way), this is the latest update of the SPI code I have been working on.
So far, the data sent from the master (CC3200-LAUNCHXL) to the slave (TMDSDOCK28335) is correct. But the problem lies on the fifth transfer (which is the only time the slave is sending data), the values are completely wrong. I try to fix the received data using some correction code, but I still get the lsb wrong. I have some example data along with the code so you can see the problem.
What is loaded into the TMDSDOCK28335 transfer buffer | What is being received on the receive buffer | After the receive buffer correction (lines 151-155 from CC3200 code) |
0x0011 | 0x0080 | 0x0010 |
0xAAAA | 0x5555 | 0xAAAA |
0x5555 | 0xAA2a | 0x5554 |
0xFFFF | 0xFF7F | 0xFFFE |
0x0000 | 0x0000 | 0x0000 |
0xABCD | 0xE655 | 0xABCC |
0x274E | 0xA713 | 0x274E |
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) originally 100,000 #define TR_BUFF_SIZE 2 //*****Start of Global Variables***** static unsigned char sendtoDSP[TR_BUFF_SIZE]; static unsigned char receivefromDSP[TR_BUFF_SIZE]; unsigned int char_array_to_int, store_msb, remove_lsb,correct_integer_backwards, correct_integer; //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(){ //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 8 bits per character (SPI_WL_8) 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_8)); //Enable SPI for Communication //GSPI_BASE = Macro for the SPI Base Address (0x44021000) MAP_SPIEnable(GSPI_BASE); while(1){ //Load first data set into transfer buffer sendtoDSP[0] = 'A'; //0x41 sendtoDSP[1] = 'B'; //0x42 //Send data over MOSI pin //1st argument is base address of SPI Module (GSPI_BASE) //2nd argument is pointer to transfer buffer (sendtoDSP) //3rd argument is pointer to receive buffer (receivefromDSP) //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,sendtoDSP,receivefromDSP,2,SPI_CS_ENABLE|SPI_CS_DISABLE); //Load second data set into transfer buffer sendtoDSP[0] = 'C'; //0x43 sendtoDSP[1] = 'D'; //0x44 MAP_SPITransfer(GSPI_BASE,sendtoDSP,receivefromDSP,2,SPI_CS_ENABLE|SPI_CS_DISABLE); //Load third data set into transfer buffer sendtoDSP[0] = 'E'; //0x45 sendtoDSP[1] = 'F'; //0x46 MAP_SPITransfer(GSPI_BASE,sendtoDSP,receivefromDSP,2,SPI_CS_ENABLE|SPI_CS_DISABLE); //Load fourth data set into transfer buffer sendtoDSP[0] = 'G'; //0x47 sendtoDSP[1] = 'H'; //0x48 MAP_SPITransfer(GSPI_BASE,sendtoDSP,receivefromDSP,2,SPI_CS_ENABLE|SPI_CS_DISABLE); //Load nothing into transfer buffer for fifth transfer sendtoDSP[0] = 0x00; sendtoDSP[1] = 0x00; MAP_SPITransfer(GSPI_BASE,sendtoDSP,receivefromDSP,2,SPI_CS_ENABLE|SPI_CS_DISABLE); //Receive Buffer Correction char_array_to_int = (receivefromDSP[1]<<8)|(receivefromDSP[0]&0xFF); store_msb = (char_array_to_int>>15)&0x0001; remove_lsb = (char_array_to_int<<1)&0xFFFE; correct_integer_backwards = remove_lsb|store_msb; correct_integer = ((correct_integer_backwards<<8)&0xFF00)|((correct_integer_backwards>>8)&0x00FF); } }
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 int first_data_set, second_data_set, third_data_set, fourth_data_set, fifth_data_set; 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 with nothing SpiaRegs.SPITXBUF = 0x0000; //Wait until first set of data is received while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } //Read in first set of data first_data_set = SpiaRegs.SPIRXBUF; //Load Transfer Buffer with nothing SpiaRegs.SPITXBUF = 0x0000; //Wait until second set of data is received while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } //Read in second set of data second_data_set = SpiaRegs.SPIRXBUF; //Load Transfer Buffer with nothing SpiaRegs.SPITXBUF = 0x0000; //Wait until third set of data is received while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } //Read in third set of data third_data_set = SpiaRegs.SPIRXBUF; //Load Transfer Buffer with nothing SpiaRegs.SPITXBUF = 0x0000; //Wait until fourth set of data is received while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } //Read in fourth set of data fourth_data_set = SpiaRegs.SPIRXBUF; //Load Transfer Buffer with new command value SpiaRegs.SPITXBUF = 0xAAAA; //Test values to be sent back over SPI are loaded in here //Wait until server CC3200 request for new command value while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } //Read in fifth set of data (should be nothing) fifth_data_set = SpiaRegs.SPIRXBUF; } } 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 =0x007F; //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; }
This picture below is when the TMDSDOCK28335 is sending 0x274E, and I am receiving 0xA713 (as stated in the chart). Bits change roughly every 10us (or 100kHz). I also think the "spikes" at each end are start and stop signals? Also, it appears that the data is right, but I may be reading it in wrong.
This picture below is when TMDSDOCK is sending 0xFFFF, but I am still receiving 0xFF7F. Again, the data coming in is right, but is being read wrong.
This picture below is when TMDSDOCK is sending 0xABCD, but I am still receiving 0xE655. Again, the data coming in is right, but it appears there is an extra high bit tagged on the end.
This picture below is when TMDSDOCK is sending 0x5555, but I am still receiving 0xAA2A. Notice that the fourth high bit stay high for twice as long as it should, and so does the last bit.
If you look at my comment on line 98 of the CC3200 code, the clock polarity and phase has been set to 0 using the macro SPI_SUB_MODE_0. On the TMDSDOCK28335 code, the register SpiaRegs.SPICCR.all is equal to 0x008F (0b0000000010001111). Bit 6 controls the clock polarity, and when this bit is set to 0, data is outputted on rising edge and data incoming is falling edge. The register SpiaRegs.SPICTL.all is equal to 0x0002 (0b0000000000000010). Bit 3 controls the clock phase, and when this bit is set to 0, then normal SPI clocking scheme (without being delayed one-half cycle). I have all of this as comments in both code sets, plus more, if you need any more information on why I set the registers as I did.
The bit rate set by the CC3200 is 100,000 bits per second (there is a macro setup for it on line 24). So that should make the SPICLK pin be 10uH.