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