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.

CC3200 to CC3200 SPI byte lag

Other Parts Discussed in Thread: CC3200

I have connected two CC3200s and I am using MAP_SPITransfer on the master side and on the slave side I have taken code from the spi demo. I am transferring 4 bytes back and forth (only need three but thought four would work better). Since the master reads at the same time it writes I know that my slave response must be delay by one transfer. However, it seems the response seen by the master is also a byte behind as well as the expected one message behind. From the slave side what seems to be happening is that Tx buffer empty flag is not set until I get a transfer from the main. So tht the slave ISR can never send what it in the first byte of the tx buffer on the first attempt. 

I know this may not seem clear so I have attached the code that I have on the two CC3200s. Each side has a character capture capability. On the master side I have a few pattern choices to send and the slave receives them fine so whatever pattern is sent is immaterial to the problem. On the slave side I can load the tx buffer with a couple of patterns that I want to send back to the master. If I choose a slave tx pattern of  0,0,0,0  for the first exchange, and 0x31, 0x32, 0x33, 0x34, on the 2nd exchange, the master sees 0x00, 0x31, 0x32, 0x33, on the second exchange. This is why I say there is a byte lag. Maybe this is the way it must be unless there is a way to get the tx buffer empty flag to set, because I tried a non-blocking pre-write and it was ignored.

My time line is becoming critical so I hope someone will help a ex-TIer. Your CC3200 is a few quantum leaps beyond the TI-960 I used to program. Besides the forum, I can be reached at:

john.hite@halosmartlabs.com 

Thanks,

John Hite

HARM 78-93, seems I will never forget badge #152301.

or

jvh24521@gmail.com

Thanks,

jh

// Standard includes
#include <string.h>

// Driverlib 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"


#define APPLICATION_VERSION     "1.1.1"

#define SPI_IF_BIT_RATE  100000
#define TR_BUFF_SIZE     100

//*****************************************************************************
//                 GLOBAL VARIABLES -- Start
//*****************************************************************************
static unsigned char g_ucTxBuff[TR_BUFF_SIZE];
static unsigned char g_ucRxBuff[TR_BUFF_SIZE];
static unsigned char ucTxBuffNdx;
static unsigned char ucRxBuffNdx;

#if defined(ccs)
extern void (* const g_pfnVectors[])(void);
#endif
#if defined(ewarm)
extern uVectorEntry __vector_table;
#endif
//*****************************************************************************
//                 GLOBAL VARIABLES -- End
//*****************************************************************************

//*****************************************************************************
//
//! SPI Master mode main loop
//!
//! This function configures SPI modelue as master and enables the channel for
//! communication
//!
//! \return None.
//
//*****************************************************************************
void MasterMain()
{
	int i,j;
    unsigned long ulUserData;
    unsigned long ulDummy;

    unsigned char f[] = {0x11,0x11, 0xEE};
    unsigned char s[] = {0x16, 0x16, 0xE9};


    // Set Tx buffer index
    ucTxBuffNdx = 0;
    ucRxBuffNdx = 0;

    //
    // Reset SPI
    //
    MAP_SPIReset(GSPI_BASE);

    //
    // Configure SPI interface
    //
    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_ACTIVEHIGH |
                     SPI_WL_32));

    //
    // Enable SPI for communication
    //
    MAP_SPIEnable(GSPI_BASE);

    Message("Enabled SPI Interface in Master Mode\n\r");
    Report("\n\rType here (Press enter to exit) :");
    ulUserData = 0;

    while(ulUserData != '\r')
    {
        // Read a character from UART terminal
        ulUserData = MAP_UARTCharGet(UARTA0_BASE);

        // Echo it back
        MAP_UARTCharPut(UARTA0_BASE,ulUserData);

        // Push the character over SPI
        switch ((unsigned char) ulUserData)
         {
         case 's':
         	g_ucTxBuff[0] = 0x01;
         	g_ucTxBuff[1] = 0x01;
         	g_ucTxBuff[2] = ~0x01;
         	break;

         case 'e':
         	g_ucTxBuff[0] = 0x04;
         	g_ucTxBuff[1] = 0x04;
         	g_ucTxBuff[2] = ~0x04;
         	break;

         case 'a':
         	g_ucTxBuff[0] = 0x06;
         	g_ucTxBuff[1] = 0x06;
         	g_ucTxBuff[2] = ~0x06;
         	break;
         default:
         	g_ucTxBuff[0] = 0x35;
         	g_ucTxBuff[1] = 0x36;
         	g_ucTxBuff[2] = 0x37;
         	g_ucTxBuff[3] = 0x38;
         	break;
         }

        Report("\r\n\nMaster sending: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", g_ucTxBuff[0], g_ucTxBuff[1], g_ucTxBuff[2], g_ucTxBuff[3]);
      	MAP_SPITransfer(GSPI_BASE,g_ucTxBuff, g_ucRxBuff,4,
                SPI_CS_ENABLE|SPI_CS_DISABLE);

        Report("\r\nMaster received:   ");
        for (j = 0; j < 8; j++)
        {
        	//Report("c:%c, 0x:%02X", g_ucRxBuff[j], g_ucRxBuff[j]);
        	Report("0x%02X, ", g_ucRxBuff[j]);
        }
    }

    //
    // Disable chip select
    //
    //MAP_SPICSDisable(GSPI_BASE);
}


//*****************************************************************************
//
//! Board Initialization & Configuration
//!
//! \param  None
//!
//! \return None
//
//*****************************************************************************
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();
}

//*****************************************************************************
//
//! Main function for spi demo application
//!
//! \param none
//!
//! \return None.
//
//*****************************************************************************
void main()
{
    //
    // Initialize Board configurations
    //
    BoardInit();

    //
    // Muxing UART and SPI lines.
    //
    PinMuxConfig();

    //
    // Enable the SPI module clock
    //
    MAP_PRCMPeripheralClkEnable(PRCM_GSPI,PRCM_RUN_MODE_CLK);

    //
    // Initialising the Terminal.
    //
    InitTerm();

    //
    // Clearing the Terminal.
    //
    ClearTerm();

    //
    // Display the Banner
    //
    Message("\n\n\n\r");
    Message("\t\t   ********************************************\n\r");
    Message("\t\t        CC3200 SPI Demo Application  \n\r");
    Message("\t\t        		Master mode  \n\r");
    Message("\t\t   ********************************************\n\r");
    Message("\n\n\n\r");

    //
    // Reset the peripheral
    //
    MAP_PRCMPeripheralReset(PRCM_GSPI);

    MasterMain();



    while(1)
    {

    }

}

// Standard includes
#include <string.h>

// Driverlib 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"


#define APPLICATION_VERSION     "1.1.1"

#define SPI_IF_BIT_RATE  100000
#define TR_BUFF_SIZE     100

#define MASTER_MSG       "This is CC3200 SPI Master Application\n\r"
#define SLAVE_MSG        "This is CC3200 SPI Slave Appl\0ication\n\r"

//*****************************************************************************
//                 GLOBAL VARIABLES -- Start
//*****************************************************************************
static unsigned char g_ucTxBuff[TR_BUFF_SIZE];
static unsigned char g_ucRxBuff[TR_BUFF_SIZE];
static unsigned char ucTxBuffNdx;
static unsigned char ucRxBuffNdx;
unsigned long ulUserData = 0;

#if defined(ccs)
extern void (* const g_pfnVectors[])(void);
#endif
#if defined(ewarm)
extern uVectorEntry __vector_table;
#endif
//*****************************************************************************
//                 GLOBAL VARIABLES -- End
//*****************************************************************************
//*****************************************************************************
//
//! Board Initialization & Configuration
//!
//! \param  None
//!
//! \return None
//
//*****************************************************************************
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();
}

//*****************************************************************************
//
//! SPI Slave Interrupt handler
//!
//! This function is invoked when SPI slave has its receive register full or
//! transmit register empty.
//!
//! \return None.
//
//*****************************************************************************
static void SlaveIntHandler()
{
    unsigned long ulRecvData;
    unsigned long ulStatus;

    ulStatus = MAP_SPIIntStatus(GSPI_BASE,true);

    MAP_SPIIntClear(GSPI_BASE,SPI_INT_RX_FULL|SPI_INT_TX_EMPTY);

    //Send
    if(ulStatus & SPI_INT_TX_EMPTY)
    {
        MAP_SPIDataPut(GSPI_BASE,g_ucTxBuff[ucTxBuffNdx]);
        ucTxBuffNdx++;
    }

    //Receive
    if(ulStatus & SPI_INT_RX_FULL)
    {
        MAP_SPIDataGetNonBlocking(GSPI_BASE,&ulRecvData);
        g_ucRxBuff[ucRxBuffNdx%3] = ulRecvData;
        //Report("0x%2X",ulRecvData);
        ucRxBuffNdx++;
    }
}

void SlaveSetup()
{

    // Set Tx buffer index
    //
    ucTxBuffNdx = 0;
    ucRxBuffNdx = 0;

    // Reset SPI
    MAP_SPIReset(GSPI_BASE);

    // Configure SPI interface
    MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI),
                     SPI_IF_BIT_RATE,SPI_MODE_SLAVE,SPI_SUB_MODE_0,
                     (SPI_HW_CTRL_CS |
                     SPI_4PIN_MODE |
                     SPI_TURBO_OFF |
                     SPI_CS_ACTIVEHIGH |
                     SPI_WL_32));

    // Register Interrupt Handler
    MAP_SPIIntRegister(GSPI_BASE,SlaveIntHandler);

    // Enable Interrupts
    MAP_SPIIntEnable(GSPI_BASE,SPI_INT_RX_FULL|SPI_INT_TX_EMPTY);

    // Enable SPI for communication
    MAP_SPIEnable(GSPI_BASE);

    // Print mode on uart
    Message("Enabled SPI Interface in Slave Mode \n\rReceived : ");
}


SlaveMain(void)
{
	int i;
    Report("\n\rType here (Press enter to exit) :");
    ulUserData = 0;

    while(ulUserData != '\r')
    {
        // Read a character from UART terminal
        ulUserData = MAP_UARTCharGet(UARTA0_BASE);

        // Echo it back
        MAP_UARTCharPut(UARTA0_BASE,ulUserData);

        switch (ulUserData)
         {
         case 'c':
         case 'C':
         	g_ucTxBuff[0] = 0x43;
         	g_ucTxBuff[1] = 0x43;
         	g_ucTxBuff[2] = ~0x43;
         	break;

         case 'a':
         	g_ucTxBuff[0] = 0x06;
         	g_ucTxBuff[1] = 0x06;
         	g_ucTxBuff[2] = ~0x06;
         	break;

         case 'n':
         	g_ucTxBuff[0] = 0x15;
         	g_ucTxBuff[1] = 0x15;
         	g_ucTxBuff[2] = ~0x15;
         	break;

         case '1':
         	g_ucTxBuff[0] = 0x31;
         	g_ucTxBuff[1] = 0x32;
         	g_ucTxBuff[2] = 0x33;
         	g_ucTxBuff[3] = 0x34;
         	break;

         default:
          	g_ucTxBuff[0] = (unsigned char)ulUserData;
          	g_ucTxBuff[1] = g_ucTxBuff[0];
          	g_ucTxBuff[2] = ~g_ucTxBuff[0];
          	break;
         }


        Report("\r\nSetting slave return values: ");
        for (i = 0; i < 3; i++)
        {
        	Report("0x%02X, ", g_ucTxBuff[i]);
        }

        ucTxBuffNdx = 0;
        ucRxBuffNdx = 0;
    }
}

//*****************************************************************************
//
//! Main function for spi demo application
//!
//! \param none
//!
//! \return None.
//
//*****************************************************************************
void main()
{
    //
    // Initialize Board configurations
    //
    BoardInit();
    PinMuxConfig();
    MAP_PRCMPeripheralClkEnable(PRCM_GSPI,PRCM_RUN_MODE_CLK);
    InitTerm();
    ClearTerm();
    Message("\n\n\n\r");
    Message("\t\t   ********************************************\n\r");
    Message("\t\t        CC3200 SPI Demo Application  \n\r");
    Message("\t\t        		Slave mode  \n\r");
    Message("\t\t   ********************************************\n\r");
    Message("\n\n\n\r");

    MAP_PRCMPeripheralReset(PRCM_GSPI);

    SlaveSetup();
    SlaveMain();

    while(1);
}

  • Looks like only 1 file came through. Here's the second.

    // Standard includes
    #include <string.h>
    
    // Driverlib 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"
    
    
    #define APPLICATION_VERSION     "1.1.1"
    
    #define SPI_IF_BIT_RATE  100000
    #define TR_BUFF_SIZE     100
    
    //*****************************************************************************
    //                 GLOBAL VARIABLES -- Start
    //*****************************************************************************
    static unsigned char g_ucTxBuff[TR_BUFF_SIZE];
    static unsigned char g_ucRxBuff[TR_BUFF_SIZE];
    static unsigned char ucTxBuffNdx;
    static unsigned char ucRxBuffNdx;
    
    #if defined(ccs)
    extern void (* const g_pfnVectors[])(void);
    #endif
    #if defined(ewarm)
    extern uVectorEntry __vector_table;
    #endif
    //*****************************************************************************
    //                 GLOBAL VARIABLES -- End
    //*****************************************************************************
    
    //*****************************************************************************
    //
    //! SPI Master mode main loop
    //!
    //! This function configures SPI modelue as master and enables the channel for
    //! communication
    //!
    //! \return None.
    //
    //*****************************************************************************
    void MasterMain()
    {
    	int i,j;
        unsigned long ulUserData;
        unsigned long ulDummy;
    
        unsigned char f[] = {0x11,0x11, 0xEE};
        unsigned char s[] = {0x16, 0x16, 0xE9};
    
    
        // Set Tx buffer index
        ucTxBuffNdx = 0;
        ucRxBuffNdx = 0;
    
        //
        // Reset SPI
        //
        MAP_SPIReset(GSPI_BASE);
    
        //
        // Configure SPI interface
        //
        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_ACTIVEHIGH |
                         SPI_WL_32));
    
        //
        // Enable SPI for communication
        //
        MAP_SPIEnable(GSPI_BASE);
    
        Message("Enabled SPI Interface in Master Mode\n\r");
        Report("\n\rType here (Press enter to exit) :");
        ulUserData = 0;
    
        while(ulUserData != '\r')
        {
            // Read a character from UART terminal
            ulUserData = MAP_UARTCharGet(UARTA0_BASE);
    
            // Echo it back
            MAP_UARTCharPut(UARTA0_BASE,ulUserData);
    
            // Push the character over SPI
            switch ((unsigned char) ulUserData)
             {
             case 's':
             	g_ucTxBuff[0] = 0x01;
             	g_ucTxBuff[1] = 0x01;
             	g_ucTxBuff[2] = ~0x01;
             	break;
    
             case 'e':
             	g_ucTxBuff[0] = 0x04;
             	g_ucTxBuff[1] = 0x04;
             	g_ucTxBuff[2] = ~0x04;
             	break;
    
             case 'a':
             	g_ucTxBuff[0] = 0x06;
             	g_ucTxBuff[1] = 0x06;
             	g_ucTxBuff[2] = ~0x06;
             	break;
             default:
             	g_ucTxBuff[0] = 0x35;
             	g_ucTxBuff[1] = 0x36;
             	g_ucTxBuff[2] = 0x37;
             	g_ucTxBuff[3] = 0x38;
             	break;
             }
    
            Report("\r\n\nMaster sending: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", g_ucTxBuff[0], g_ucTxBuff[1], g_ucTxBuff[2], g_ucTxBuff[3]);
          	MAP_SPITransfer(GSPI_BASE,g_ucTxBuff, g_ucRxBuff,4,
                    SPI_CS_ENABLE|SPI_CS_DISABLE);
    
            Report("\r\nMaster received:   ");
            for (j = 0; j < 8; j++)
            {
            	//Report("c:%c, 0x:%02X", g_ucRxBuff[j], g_ucRxBuff[j]);
            	Report("0x%02X, ", g_ucRxBuff[j]);
            }
        }
    
        //
        // Disable chip select
        //
        //MAP_SPICSDisable(GSPI_BASE);
    }
    
    
    //*****************************************************************************
    //
    //! Board Initialization & Configuration
    //!
    //! \param  None
    //!
    //! \return None
    //
    //*****************************************************************************
    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();
    }
    
    //*****************************************************************************
    //
    //! Main function for spi demo application
    //!
    //! \param none
    //!
    //! \return None.
    //
    //*****************************************************************************
    void main()
    {
        //
        // Initialize Board configurations
        //
        BoardInit();
    
        //
        // Muxing UART and SPI lines.
        //
        PinMuxConfig();
    
        //
        // Enable the SPI module clock
        //
        MAP_PRCMPeripheralClkEnable(PRCM_GSPI,PRCM_RUN_MODE_CLK);
    
        //
        // Initialising the Terminal.
        //
        InitTerm();
    
        //
        // Clearing the Terminal.
        //
        ClearTerm();
    
        //
        // Display the Banner
        //
        Message("\n\n\n\r");
        Message("\t\t   ********************************************\n\r");
        Message("\t\t        CC3200 SPI Demo Application  \n\r");
        Message("\t\t        		Master mode  \n\r");
        Message("\t\t   ********************************************\n\r");
        Message("\n\n\n\r");
    
        //
        // Reset the peripheral
        //
        MAP_PRCMPeripheralReset(PRCM_GSPI);
    
        MasterMain();
    
    
    
        while(1)
        {
    
        }
    
    }
    
    

  • HI John,
    There is going to be at least a byte of lag, and depending on your algorithm it could be more. What you are seeing seems like what I would expect from what you are doing. What is exactly you are trying to accomplish for each master transfer?

    -Aaron
  • Hi Aaron,
    Thanks for the reply. I hope you have seen my 2nd post on this topic wherein I go into a good bit more detail.

    What I am doing is sending files from one CC3200 to another CC3200 or similar device. Since we are working with an embedded system that works with OTA updates the designers want to make sure that the file is copied correctly. So we are doing something that looks a lot like XModem CRC16. The files can be quite large so they are broken up and sent in packets with a CRC attached. Each received packet is ACKed or NAKed.

    For example let's say the packet from master to slave is 128 bytes long. Obviously the slave must process it after it is fully received. So I have the master send a short enquiry packet next (the contents are irrelevant) that picks up what the slave has put in its tx buffer. So I know and expect the slave's reply to be a full exchange behind. But not a full exchange and a byte behind.

    I hope my repost explains the problem better, it is here: e2e.ti.com/.../495800

    Thanks,
    jh