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.

F28027 Waiting for SPI to finish transmit

I have a question about the SPI on the F28027 in master mode.

I'd like to the software to control the Slave Select instead of relying on the SPISTE.

In order to control the Slave Select, I have to wait for the SPI to finish transmitting.
I'm just wondering how to actually know when transmission has finished?

I've looked through the TMS320x2802x, 2803x Piccolo Serial Peripheral
Interface (SPI). 
I've tried polling the SPISTS register, particularly the SPI INT FLAG bit (bit 6).
I thought it went high once it finished transmitting.
I've also tried reading the SPISTEA line of GPIO19.

Here is a snippet of the coded I've tried to transmit and wait for it to finish transmitting.

However it just hangs. 
Could some one let me know how to wait for the SPI to finish transmitting?
The commented out while loops are different ways I've attempted to wait

    	GPIO_setLow(myGpio, GPIO_Number_0);
        SPI_write(mySpi, 0xA5 << 8);
        SPI_write(mySpi, 0x5A << 8);
        // Wait until data is tx

        //while (SpiaRegs.SPISTS.bit.BUFFULL_FLAG !=0);
        while (SpiaRegs.SPISTS.bit.INT_FLAG == 0);
    	//while(!GpioDataRegs.GPADAT.bit.GPIO19);

GPIO_setHigh(myGpio, GPIO_Number_0);

  • I thought reading STEINV would work, but there's a note saying "STEINV feature is not avaliable on TMS320x2802x devices."
  • The answer depends on if you are using FIFO or not.

    If you are not using FIFO, the SPISTS bit can be used to detect if the transmission is complete.
    If you are using FIFO, you can use the SPIFFRX.RXFFST to detect when the SPI has completed transmitting. Since the SPI is a shift register, when the receiver has received the expected number of data, you know that the transmitter has completely transmitted the data.

    -Mark
  • We've done a similar thing, but we use the while loop below. As Mark mentioned earlier, for this to work you need to be using FIFO.

    while (SpiaRegs.SPIFFRX.bit.RXFFST != 1) { } // wait until the SPI data has been transmitted.


    you can also use: while (SpibRegs.SPIFFRX.bit.RXFFST == 0) { }. They seem to work the same for us. Hope that helps!

    -Greg
  • Hey thanks for your help guys! :)

    I am using the SPI Fifos.  This is how I'm enabling them:

        // Initialize SPI FIFO registers
        SPI_enableChannels(mySpi);
        SPI_enableFifoEnh(mySpi);
    
    	SPI_resetTxFifo(mySpi);
        SPI_resetRxFifo(mySpi);
    
        //house keeping
        SPI_clearTxFifoInt(mySpi);
        SPI_clearRxFifoInt(mySpi);


    I've changed my transmit and transmit wait code to:

        	while(SPI_getTxFifoStatus(mySpi) == SPI_FifoStatus_4_Words);
        	GPIO_setLow(myGpio, GPIO_Number_0);
            SPI_write(mySpi, 0xA5 << 8);
            SPI_write(mySpi, 0x5A << 8);
            
    	while (SpiaRegs.SPIFFRX.bit.RXFFST != 1)
            {} 
            GPIO_setHigh(myGpio, GPIO_Number_0);

    However, it seems to get in an infinite loop at:

    while (SpiaRegs.SPIFFRX.bit.RXFFST != 1)

  • so it looks to me like you're wanting to send A55A through SPI... Can you do this all in one 16 bit block? I'm not sure what your application is, but if you'll always be sending 16 bits at a time, it might be easier to configure the SPI to send 16 bits and then just do a SPI_write(mySpi, 0xA55A). I understand that sometimes it just makes things easier to send everything in groups of 8 bits though.

    I think part of the problem might be that you're not waiting for each set of bits to be transmitted. For example, you might want to do something similar to

    SPI_write(mySpi, 0xA5 << 8);
    while (SpiaRegs.SPIFFRX.bit.RXFFST != 1){}
    
    SPI_write(mySpi, 0x5A << 8); 
    while (SpiaRegs.SPIFFRX.bit.RXFFST != 1){}


    Also, do you know if your FIFO is setup correctly? when we're sending SPI data, we don't check on anything about the fifo. We simply initialize the SPI fifo at the begining of the code, and the just call an SPI_write function. Below is the code we use for our FIFO initialization, but i'm not sure if it will fit your application or not.

    void spi_fifo_init()
    {
    // Initialize SPI FIFO registers
        SpiaRegs.SPIFFTX.all = 0xE040;
        SpiaRegs.SPIFFRX.all = 0x2044;
        SpiaRegs.SPIFFCT.all = 0x0;
    }

    I hope that helps!!

  • Hey Gregory.  I appreciate your help.  My application actually requires me to only send 8 bits at a time.The code that I posted is not from my application.  It's more or less code I've used to figure out how to get the software controlled slave select to work with the FIFOs.
    I was sending 0xA5 and 0xA5 just because the bit patterns are easy to see in a logic analyzer.

    I've made the changes you've suggested with enabling the FIFOs.  I've attempted to send just one byte and the code enters an infinite loop at:

    while (SpiaRegs.SPIFFRX.bit.RXFFST != 1){}

    My logic analyzer shows all 8 bits has been sent and the hardware controlled slave select goes high. But the software controlled slave select doesn't because of the infinite loop.  Pin 19 is the hardware controlled slave select.

    I'm going to just post my entire code for this.  Maybe you can see what's going on better?

    #include "DSP28x_Project.h"
    
    #include "f2802x_common/include/clk.h"
    #include "f2802x_common/include/gpio.h"
    #include "f2802x_common/include/pie.h"
    #include "f2802x_common/include/pll.h"
    #include "f2802x_common/include/spi.h"
    #include "f2802x_common/include/wdog.h"
    
    void spi_fifo_init(void);
    void spi_init(void);
    
    CLK_Handle myClk;
    GPIO_Handle myGpio;
    PIE_Handle myPie;
    SPI_Handle mySpi;
    
    void main(void)
    {
        CPU_Handle myCpu;
        PLL_Handle myPll;
        WDOG_Handle myWDog;
        // Initialize all the handles needed for this application
        myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
        myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
        myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
        myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
        myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
        mySpi = SPI_init((void *)SPIA_BASE_ADDR, sizeof(SPI_Obj));
        myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
    
        // Perform basic system initialization
        WDOG_disable(myWDog);
        (*Device_cal)();
    
        //Select the internal oscillator 1 as the clock source
        CLK_setOscSrc(myClk, CLK_OscSrc_Internal);
    
        PLL_setup(myPll, PLL_Multiplier_1, PLL_DivideSelect_ClkIn_by_4);
        CLK_setLowSpdPreScaler(myClk, CLK_LowSpdPreScaler_SysClkOut_by_14);
    
        // Disable the PIE and all interrupts
        PIE_disable(myPie);
        PIE_disableAllInts(myPie);
        CPU_disableGlobalInts(myCpu);
        CPU_clearIntFlags(myCpu);
    
    
        // Initalize GPIO
        GPIO_setPullUp(myGpio, GPIO_Number_16, GPIO_PullUp_Enable);
        GPIO_setPullUp(myGpio, GPIO_Number_17, GPIO_PullUp_Enable);
        GPIO_setPullUp(myGpio, GPIO_Number_18, GPIO_PullUp_Enable);
        GPIO_setPullUp(myGpio, GPIO_Number_19, GPIO_PullUp_Enable);
        GPIO_setQualification(myGpio, GPIO_Number_16, GPIO_Qual_ASync);
        GPIO_setQualification(myGpio, GPIO_Number_17, GPIO_Qual_ASync);
        GPIO_setQualification(myGpio, GPIO_Number_18, GPIO_Qual_ASync);
        GPIO_setQualification(myGpio, GPIO_Number_19, GPIO_Qual_ASync);
        GPIO_setMode(myGpio, GPIO_Number_16, GPIO_16_Mode_SPISIMOA);
        GPIO_setMode(myGpio, GPIO_Number_17, GPIO_17_Mode_SPISOMIA);
        GPIO_setMode(myGpio, GPIO_Number_18, GPIO_18_Mode_SPICLKA);
        GPIO_setMode(myGpio, GPIO_Number_19, GPIO_19_Mode_SPISTEA_NOT);
    
        // Setup a debug vector table and enable the PIE
        PIE_setDebugIntVectorTable(myPie);
        PIE_enable(myPie);
    
        spi_init();         // Initialize SPI
        spi_fifo_init();    // Initialize the SPI FIFOs
    
    
        GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
        GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Output);
    
        GPIO_setHigh(myGpio, GPIO_Number_0);
    
        // Transmit data
        GPIO_setLow(myGpio, GPIO_Number_0);
        SPI_write(mySpi, 0xAA << 8);
        while (SpiaRegs.SPIFFRX.bit.RXFFST != 1){}
    
        GPIO_setHigh(myGpio, GPIO_Number_0);
        while(1);
    }
    
    
    
    void spi_init()
    {
        CLK_enableSpiaClock(myClk);
    
        SPI_setCharLength(mySpi, SPI_CharLength_8_Bits);
    
        // Enable master mode, normal phase,
        // enable talk, and SPI int disabled.
        SPI_setMode(mySpi, SPI_Mode_Master);
        SPI_enableTx(mySpi);
    
        SPI_setBaudRate(mySpi, (SPI_BaudRate_e)126);
    
        SPI_enable(mySpi);
    
        // Set so breakpoints don't disturb xmission
        SPI_setPriority(mySpi, SPI_Priority_FreeRun);
    
        return;
    }
    
    void spi_fifo_init()
    {
        // Initialize SPI FIFO registers
        SpiaRegs.SPIFFTX.all = 0xE040;
        SpiaRegs.SPIFFRX.all = 0x2044;
        SpiaRegs.SPIFFCT.all = 0x0;
    }
    
    

  • Zach,

    Have you been able to resolve your questions?

    Can you look at the value of RXFFST while the code is hung up in the while loop?

    Thanks,
    Mark