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/LAUNCHXL-F28379D: SPI FIFO Interrupt issue at 10Mhz

Part Number: LAUNCHXL-F28379D


Tool/software: Code Composer Studio

I'm trying to communicate via SPI using the F28379D LaunchPad as slave with 10Mhz baudrate. But there are some problems with the data received.

1) When using a buffer with 8 word to transmit through FIFO, the data received shifts 1 bit (e.g. transmitted: 0x000B, received: 0x0003), and it shifts the entire buffer(e.g. trasmitted: 0xFFFF, 0x0000, 0x016, 0x22FF, 0x029A, 0x008, 0x0018, 0x002A, received: 0x7FFF, 0x8000, 0x000B, 0x117F, 0x814D, 0x0004, 0x000C, 0x0015). The last bit become the first received, and so on. The same problem using 5MHz. [issue solved, see edit2]

2) When using 1MHz or 2MHz baudrate it works perfectly, but with 8 word sized buffer at max. I couldn't find a pattern with a larger buffer, but it keeps showing the preset data at a random sequence(e.g. transmitted: 0xFFFF, 0x0000, 0x016, 0x22FF, 0x029A, 0x008, 0x0018, 0x002A, 0x44CB, received: 0x002A, 0x44CB, 0x0016, 0x22FF, 0x029A, 0x0008, 0x0018, 0x002A, 0x44CB) it's always some of the preset data, but not necessarily at the same order or the same data. [issue solved, see edit1]

3) I did realized also that the ISR is executed 2 times upon the start as soon I run the code, even keeping the CS pin high.[issue solved, seed edit3]

edit 1: Solved the 2nd issue. Dreceasing the SPI_FIFO_TX8 and SPI_FIFO_TX8, overflow directives. I thought that it was size directives but it's entirely opposite. 

edit 2: Solved the 1st issue. Changing the mode of SPI, to use phase 1(i.e directive mode from SPI_PROT_POL0PHA0 to SPI_PROT_POL0PHA1). 

edit3: Solved the 3rd issue by changing the SPI_FIFO_TX8 and SPI_FIFO_RX8 to SPI_FIFO_TX0 and SPI_FIFO_RX0, now it's going to always generate an interrupt if it keeps with any slot in the FIFO with no data. Also incresead the buffer size to 16, so it always fit and will generate an interrupt as soon as it is read from the FIFO. 

#include "driverlib.h"
#include "device.h"

//defines
#define FIFOTX SPI_FIFO_TX8 //TRANSMISSION FIFO SIZE
#define FIFORX SPI_FIFO_RX8 //RECEIVED FIFO SIZE also not used
#define buffer_size 8
#define BAUD_R 1000000

//Globals
volatile uint16_t rData[buffer_size]; //not used
uint16_t sData[buffer_size]={0xFFFF, 0x0000, 0x016, 0x22FF, 0x029A, 0x008, 0x0018, 0x002A};

// Function Prototypes
void initSPI(void);
void initSPI_GPIO(void);
__interrupt void spibTxFIFOISR(void);


// Main
void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Disable pin locks and enable internal pullups.
    //
    Device_initGPIO();

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //
    // Set up SPI, initializing it for FIFO mode
    //
    Interrupt_register(INT_SPIB_TX, &spibTxFIFOISR);
    initSPI_GPIO();
    initSPI();

    Interrupt_enable(INT_SPIB_TX);

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;

    //
    // Loop forever. Suspend or place breakpoints to observe the buffers.
    //
     while(1)
    {
         ;
    }
}

void initSPI()
{
    //
    // Must put SPI into reset before configuring it
    //
    SPI_disableModule(SPIB_BASE);

    //
    // SPI configuration. Use a 12MHz SPICLK and 16-bit word size.
    //

    SPI_setConfig(SPIB_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA0,
                  SPI_MODE_SLAVE, BAUD_R, 16);
    SPI_disableLoopback(SPIB_BASE);
    SPI_setEmulationMode(SPIB_BASE, SPI_EMULATION_STOP_AFTER_TRANSMIT);
    //SPI_enableHighSpeedMode(SPIB_BASE);

    //FIFO and interrupt config

    SPI_enableFIFO(SPIB_BASE);
    SPI_clearInterruptStatus(SPIB_BASE, SPI_INT_TXFF);
    SPI_setFIFOInterruptLevel(SPIB_BASE, FIFOTX, FIFORX);
    SPI_enableInterrupt(SPIB_BASE, SPI_INT_TXFF);
    // Configuration complete. Enable the module.
    //
    SPI_enableModule(SPIB_BASE);
}

void initSPI_GPIO()
{
    EALLOW;


    //SPI B CONFIG

    GPIO_setPadConfig(63, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(64, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(65, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(66, GPIO_PIN_TYPE_PULLUP);

    GPIO_setDirectionMode(63, GPIO_DIR_MODE_IN);
    GPIO_setDirectionMode(64, GPIO_DIR_MODE_OUT);
    GPIO_setDirectionMode(65, GPIO_DIR_MODE_IN);
    GPIO_setDirectionMode(66, GPIO_DIR_MODE_IN);

    GPIO_setQualificationMode(63, GPIO_QUAL_ASYNC);
    GPIO_setQualificationMode(64, GPIO_QUAL_ASYNC);
    GPIO_setQualificationMode(65, GPIO_QUAL_ASYNC);
    GPIO_setQualificationMode(66, GPIO_QUAL_ASYNC);

    GPIO_setPinConfig (GPIO_63_SPISIMOB);
    GPIO_setPinConfig (GPIO_64_SPISOMIB);
    GPIO_setPinConfig (GPIO_65_SPICLKB);
    GPIO_setPinConfig (GPIO_66_SPISTEB);


    EDIS;
}
//
// SPI A Transmit FIFO ISR
//
__interrupt void spibTxFIFOISR(void)
{
    uint16_t i;

    //
    // Send data
    //
    for(i = 0; i < buffer_size; i++)
    {
       SPI_writeDataNonBlocking(SPIB_BASE, sData[i]);
    }

    //
    // Clear interrupt flag and issue ACK
    //
    SPI_clearInterruptStatus(SPIB_BASE, SPI_INT_TXFF);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
}

  • 1. The scenario where everything is shifted by 1 bit makes me think of a mismatch in the expected phase/polarity settings. Do you see any differences when you adjust them? I see you have a commented out call for enabling high-speed mode--no difference with that enabled?

    2. In this scenario what FIFO interrupt level are you using? Is there any FIFO overflow happening?

    3. Since this is the slave side, the transmit function is really just filling up the FIFO to have it ready for whenever the master starts the clock, so it makes sense that you'd get the interrupts even though the CS/CLK aren't active.

    Whitney

  • 1. Yes, the setting between master and slave is at the same phase/polarity. I'm gonna try to adjust this, will report soon. About the high-speed mode commented, there is no difference when it's enabled, also I couldn't find the right pins to use this mode. [edit 2]

    2.I've already noticed that, as soon as I posted. It had happened and I solved that. Just changed the FIFO levels(i.e. SPI_FIFO_TX8 or SPI_FIFO_TX8 directives)

    3. I didn't get it, Isn't it suposed to be executed only when the clock is triggered? The function to fill up the FIFO is inside the interrupt routine. And why only 2 times? The master isn't sending anything to this slave, already disconnected one from another and set the CS high, the registers is modified as soon as i run the code. Doesn't make any sense to me.

    edit 2: 1. Reporting about changing the Polarity/phase: Somehow it worked by changing phase to 1, both polarity 0 or 1 works fine as well. Could this work because there is some kind of bus delay?

  • The TX FIFO interrupt is generated based off how much space is in the FIFO, so if the FIFO level is below the interrupt threshold for any reason (start up, reset of the FIFO, transmission shifted data out, etc...), it will generate the interrupt. Even if the master isn't putting out meaningful data, the master always drives the clock in SPI.

    It's happening twice at the beginning because it's a 16-word FIFO and your FIFO interrupt level is 8 words--there's still space for 8 after the first 8 are loaded so another interrupt is generated.

    Whitney

  • That's exactly what was happening! Changed the FIFO overflow directive, and the buffer size to fit. Now it only happens once.