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.

TMS320F28335: Using SPI to communicate with the FPGA

Part Number: TMS320F28335


Hi team,

Here's an issue from the customer may need your help:

The DSP (TMS320F28335) is used to communicate with the FPGA board (PyNQ-Z2) using SPI.

Customer wants to use DSP as master to transfer floating point numbers (for example: 0.12 0.121 0.122...) to FPGAs as slave. However, during testing, it was found that the FPGA may receive incorrect values.

Earlier guessing that it might be possible to have one more 0 first (when expressed in binary), for example, if 111111111111111111 was originally transmitted, the result would be 0111111111111111.  More than one is pushed to the next column, and after the customer tries to push one bit forward manually, there are still some values that are wrong.

Here's some of the result after moving one bit backwards:(the red part has a critical error)

0.120   -> 0.11951171606779099

0.121  ->  0.12099999934434891

0.122  ->  0.12200000137090683

0.123  ->  0.12300000339746475

0.124  ->  0.12399999797344208

0.125  ->  0.1259765774011612

0.126  ->  0.12502342462539673

0.127  ->  0.12797658145427704

0.128  ->   0.12702342867851257

0.129  ->  0.12997658550739288

0.130  -> 0.12902343273162842

......

DSP has referenced below example:

https://dev.ti.com/tirex/explore/node?a=AocYeEd__2.0.0&node=A__AHg0dkUKptZrNiSRKvCtVw__c2000ware_software_package__gYkahfz__LATEST&r=AocYeEd__1.0.0&r=AocYeEd__LATEST&search=F28335

And below is the modified program code:

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
//#include "DSP2833x_Device.h"

//
// Function Prototypes
//
//__interrupt void ISRTimer2(void);
void delay_loop(void);
void spi_xmit(Uint16 a);
void spi_fifo_init(void);
void spi_init(void);
void error(void);

union datatype{
    float f_type;
    Uint16 u_type[2];
};
union datatype sdata;
union datatype rdata;

char data_switch=0;

//
// Main
//
void main(void)
{

    sdata.f_type = 0.12;

    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP2833x_SysCtrl.c file.
    //
    InitSysCtrl();

    //
    // Step 2. 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.
    //
    // InitGpio();  // Skipped for this example
    
    //
    // Setup only the GP I/O only for SPI-A functionality
    // This function is found in DSP2833x_Spi.c
    //
    InitSpiaGpio();

    //
    // Step 3. 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();

    //
    // Step 4. Initialize all the Device Peripherals:
    // This function is found in DSP2833x_InitPeripherals.c
    //
    // InitPeripherals();    // Not required for this example
    spi_fifo_init();         // Initialize the Spi FIFO
    spi_init();              // init SPI

    //
    // Step 5. User specific code:
    //
    
    //
    // Interrupts are not used in this example.
    //



    int count = 0;
    for(;;)
    {
        if(count < 100)
        {
            spi_xmit(sdata.u_type[data_switch]);

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

            }
            rdata.u_type[data_switch] = SpiaRegs.SPIRXBUF;

            if(data_switch==0)
            {
                data_switch=1;
            }
            else
            {
                sdata.f_type = sdata.f_type + 0.001;
                count ++;
                data_switch=0;
            }

            delay_loop();
        }
    }
}

//
// delay_loop - Step 7. Insert all local Interrupt Service Routines (ISRs) and 
// functions here:
//
void 
delay_loop()
{
    long      i;
    for (i = 0; i < 1000000; i++)
    {

    }
}

//
// error -
//
void 
error(void)
{
    __asm("     ESTOP0");						// Test failed!! Stop!
    for (;;);
}

//
// spi_init -
//
void 
spi_init()
{
    SpiaRegs.SPICCR.all =0x000F;	// Reset on, rising edge, 16-bit char bits
    
    //
    // Enable master mode, normal phase, enable talk, and SPI int disabled.
    //
    SpiaRegs.SPICTL.all =0x0006;
    SpiaRegs.SPIBRR =0x007F;
    SpiaRegs.SPICCR.all =0x008F;   // Relinquish SPI from Reset
    SpiaRegs.SPIPRI.bit.FREE = 1;  // Set so breakpoints don't disturb xmission

}

//
// spi_xmit -
//
void 
spi_xmit(Uint16 a)
{
    SpiaRegs.SPITXBUF=a;
}

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

Could you help check this case? Thanks.

Best Regards,

Cherry

  • Cherry,

    This sounds like an issue with the SPI clock polarity and phase setting. Has the customer confirmed that the SPI MOSI pin is switching as expected by the FPGA? 

  • Hi Gus,

    Thanks for your help.

    Customer has verified FPGA and DSP settings (both set to clock polarity = 0, clock phase = 0). The customer is trying to modify the program in the FPGA section, although an additional 0 issue still exists, it is able to get the correct value for the time being now.

    Also, there is a problem with the value that the FPGA sends back to the DSP, which requires a cyclic shift to get the correct value, for example:

    The FPGA was originally transmitting  0, 1, 2, 3, 4, ...., 32768, 32769, 32770, 32771, ....

    DSP receives 0, 2, 4, 6, 8, ....,         1,         3,         5,         7, ....

    The DSP will not get the correct value until the following calculations are made:

    Result = (val << (16 - 1) | (val >> 1)); // val is the value received by the DSP.

    Thanks and regards,

    Cherry

  • Cherry,

    Customer has verified FPGA and DSP settings (both set to clock polarity = 0, clock phase = 0).

    This is exactly my point. These setting may have complete different implementations between FPGA and MCU. Please have the customer review the TRM carefully. A clock polarity = clock phase = 0 result in the timing below, i.e. data switching on rising edge of clock and sample on falling edge of clock. Is this what the FPGA expects?