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.

TMS320F28377S: TMS320F28377S SPI Communication Problem

Part Number: TMS320F28377S


Tool/software:

Hello TI Team,

I am using the TMS320F28377S and trying to establish communication using the SPI module. I’ve been working on this for two days but haven’t been able to get it working properly.

When I write my own SPI communication functions without making any changes to the configuration, I am able to write and read data successfully.

The device I am trying to communicate with is an EEPROM chip: 25LC640A-E/SN. Could you please help me with this?

Below are the pin assignments and the code I have prepared.

(Nonfunctional)

void SPI_GPIO_Init(void)
{
EALLOW;

// === MOSI: GPIO24 → SPISIMOB ===
GpioCtrlRegs.GPAGMUX2.bit.GPIO24 = 1; // Set GPIO24 to use GMUX option 1
GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 2; // Set MUX to 2 for SPISIMOB function
GpioCtrlRegs.GPAQSEL2.bit.GPIO24 = 3;

// === MISO: GPIO25 → SPISOMIB ===
GpioCtrlRegs.GPAGMUX2.bit.GPIO25 = 1; // Set GPIO25 to use GMUX option 1
GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 2; // Set MUX to 2 for SPISOMIB function
GpioCtrlRegs.GPAQSEL2.bit.GPIO25 = 3;

// === CLK: GPIO26 → SPICLKB ===
GpioCtrlRegs.GPAGMUX2.bit.GPIO26 = 1; // Set GPIO26 to use GMUX option 1
GpioCtrlRegs.GPAMUX2.bit.GPIO26 = 2; // Set MUX to 2 for SPICLKB function
GpioCtrlRegs.GPAQSEL2.bit.GPIO26 = 3;

// === Set GPIO directions ===
GpioCtrlRegs.GPADIR.bit.GPIO24 = 1; // MOSI: output
GpioCtrlRegs.GPADIR.bit.GPIO25 = 0; // MISO: input
GpioCtrlRegs.GPADIR.bit.GPIO26 = 1; // CLK: output

// === Enable internal pull-up resistors ===
GpioCtrlRegs.GPAPUD.bit.GPIO24 = 0; // Enable pull-up for MOSI
GpioCtrlRegs.GPAPUD.bit.GPIO25 = 0; // Enable pull-up for MISO
GpioCtrlRegs.GPAPUD.bit.GPIO26 = 0; // Enable pull-up for CLK

GpioCtrlRegs.GPBMUX1.bit.GPIO38 = 0; // Set GPIO38 to GPIO function
GpioCtrlRegs.GPBDIR.bit.GPIO38 = 1; // Set as output
GpioCtrlRegs.GPBPUD.bit.GPIO38 = 0; // Enable pull-up resistor
GpioDataRegs.GPBSET.bit.GPIO38 = 1; // Set HIGH initially (inactive)

EDIS;
}



void SPI_INIT()
{

EALLOW;
GpioDataRegs.GPBSET.bit.GPIO38 = 1; // nCS HIGH




CpuSysRegs.PCLKCR8.bit.SPI_B = 1;
SpibRegs.SPICCR.bit.SPISWRESET = 0; // Reset SPI
SpibRegs.SPICCR.bit.CLKPOLARITY = 0; // Clock polarity 0
SpibRegs.SPICTL.bit.CLK_PHASE = 0 ;
SpibRegs.SPICCR.bit.SPICHAR = 7; // 8-bit data
SpibRegs.SPICTL.bit.MASTER_SLAVE = 1; // Master mode
SpibRegs.SPICTL.bit.TALK = 1; // TX enable
SpibRegs.SPIBRR.bit.SPI_BIT_RATE = 21; // Baud Rate
SpibRegs.SPICCR.bit.SPISWRESET = 1; // Release SPI from reset

EDIS;

}

void EEPROM_WriteByte(Uint16 address, Uint8 data)
{
// Write Enable
GpioDataRegs.GPBCLEAR.bit.GPIO38 = 1; // nCS LOW
SPIB_SendByte(0x06); // Write Enable opcode
GpioDataRegs.GPBSET.bit.GPIO38 = 1; // nCS HIGH

// Write Command
SPI_Delay(); 
GpioDataRegs.GPBCLEAR.bit.GPIO38 = 1;

SPIB_SendByte(0x02); // WRITE opcode
SPIB_SendByte((address >> 8) & 0xFF); // Address High Byte
SPIB_SendByte(address & 0xFF); // Address Low Byte
SPIB_SendByte(data); // Data byte

GpioDataRegs.GPBSET.bit.GPIO38 = 1;

DELAY_US(5000); // Wait write cycle (max 5ms)
}

Uint8 EEPROM_ReadByte(Uint16 address)
{
Uint8 value;

GpioDataRegs.GPBCLEAR.bit.GPIO38 = 1;

SPIB_SendByte(0x03); // READ opcode
SPIB_SendByte((address >> 8) & 0xFF); // Address High Byte
SPIB_SendByte(address & 0xFF); // Address Low Byte
value = SPIB_SendByte(0x00); // Dummy write to receive data


DELAY_US(5);
GpioDataRegs.GPBSET.bit.GPIO38 = 1;

return value;
}

Uint16 SPIB_SendByte(Uint16 data)
{
while (SpibRegs.SPISTS.bit.BUFFULL_FLAG == 1); // Wait if TX buffer full
SpibRegs.SPITXBUF = data << 8;

while (SpibRegs.SPISTS.bit.INT_FLAG == 0); // Wait for RX
return SpibRegs.SPIRXBUF & 0x00FF;
}

void SPI_Delay(void)
{
asm(" RPT #50 || NOP"); 
}

I tested in the main loop

void main(void)
{
    for(;;)
    {
        if(spi_write_test==1)
        {
            EEPROM_WriteByte(0x1234, 0xAA);
            spi_write_test=0;
        }

        if(spi_read_test==1)
        {
            EEPROM_ReadByte(0x1234);
            spi_read_test=0;
        }
    }
}

Clock Frequency --> 750kHz

Write sequence

  

Read Sequence

(Functional)

void SPI_GPIO_Init(void)
{
    EALLOW;

    // MOSI (Master Out, Slave In) -> GPIO24
    GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 0; // Set as GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO24 = 1;  // Configure as output

    // MISO (Master In, Slave Out) -> GPIO25
    GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 0; // Set as GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO25 = 0;  // Configure as input

    // CLK (Clock) -> GPIO26
    GpioCtrlRegs.GPAMUX2.bit.GPIO26 = 0; // Set as GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO26 = 1;  // Configure as output

    // CS (Chip Select) -> GPIO38
    GpioCtrlRegs.GPBMUX1.bit.GPIO38 = 0; // Set as GPIO
    GpioCtrlRegs.GPBDIR.bit.GPIO38 = 1;  // Configure as output

    EDIS;
}


void SPI_Delay(void)
{
    asm(" RPT #50 || NOP"); // Short delay between clock transitions
}


void SPI_SendByte(uint8_t data)
{
    int i;

    for (i = 7; i >= 0; i--)
    {
        if ((data >> i) & 0x01)
            GpioDataRegs.GPASET.bit.GPIO24 = 1; // MOSI high
        else
            GpioDataRegs.GPACLEAR.bit.GPIO24 = 1; // MOSI low

        SPI_Delay();

        GpioDataRegs.GPASET.bit.GPIO26 = 1; // CLK high
        SPI_Delay();

        GpioDataRegs.GPACLEAR.bit.GPIO26 = 1; // CLK low
        SPI_Delay();
    }
}



uint8_t SPI_ReadByte(void)
{
    int i;
    uint8_t received = 0;

    for (i = 7; i >= 0; i--)
    {
        // Dummy 0 bit on MOSI
        GpioDataRegs.GPACLEAR.bit.GPIO24 = 1;

        SPI_Delay();

        GpioDataRegs.GPASET.bit.GPIO26 = 1; // CLK high
        SPI_Delay();

        // Sample MISO
        if (GpioDataRegs.GPADAT.bit.GPIO25)
            received |= (1 << i);

        GpioDataRegs.GPACLEAR.bit.GPIO26 = 1; // CLK low
        SPI_Delay();
    }

    return received;
}





void EEPROM_Write_0x1234_0x10(void)
{
    // Step 1: Send WREN command (Write Enable)
    GpioDataRegs.GPBCLEAR.bit.GPIO38 = 1; // CS low
    SPI_SendByte(0x06); // WREN command
    GpioDataRegs.GPBSET.bit.GPIO38 = 1;   // CS high
    SPI_Delay(); // Small delay if needed

    // Step 2: Send WRITE command + Address + Data
    GpioDataRegs.GPBCLEAR.bit.GPIO38 = 1; // CS low

    SPI_SendByte(0x02);   // WRITE command
    SPI_SendByte(0x12);   // Address MSB (0x12 for 0x1234)
    SPI_SendByte(0x34);   // Address LSB (0x34 for 0x1234)
    SPI_SendByte(0xAA);   // Data byte (0x10)

    GpioDataRegs.GPBSET.bit.GPIO38 = 1;   // CS high

    // Step 3: Wait for write cycle to complete (typical 5ms)
    DELAY_US(5000); // 5 milliseconds wait
}



uint8_t EEPROM_Read_0x1234(void)
{
    uint8_t read_data;

    GpioDataRegs.GPBCLEAR.bit.GPIO38 = 1; // CS low - start communication

    SPI_SendByte(0x03);   // READ command
    SPI_SendByte(0x12);   // Address MSB
    SPI_SendByte(0x40);   // Address LSB

    read_data = SPI_ReadByte(); // Read one byte

    GpioDataRegs.GPBSET.bit.GPIO38 = 1;   // CS high - end communication

    return read_data;
}

Main Loop

void main(void)
{
    for(;;)
    {
        if(spi_write_test==1)
        {
            EEPROM_Write_0x1234_0x10();
            spi_write_test=0;
        }

        if(spi_read_test==1)
        {
            EEPROM_Read_0x1234();
            spi_read_test=0;
        }
    }
}

Write 

Read

EEPROM Device command table

  • Hello,

    Apologies, I have a couple immediate follow-up questions for clarity.

    1. Is the provided code the functional or nonfunctional code?
    2. What are the differences between the functional and nonfunctional code, exactly?
    3. When using the nonfunctional code, what is the fail state? i.e. is there no communication whatsoever, is it junk data, incorrectly formatted, etc.?

    Additionally, please note that we discourage posting large code blocks in the body of a message. Please try and use the attachment functionality, as otherwise we've seen e2e run into performance issues in the past if there's too much content on one page.

    Regards,
    Jason Osborn

  • Thank you for your response.
    First of all, the lines in the initial code block correspond to the moment when I attempt to communicate with the EEPROM device but fail to establish communication. The second code block represents the structure I tested while in debug mode. The last code block I shared shows the lines from the version where I was able to successfully communicate with the EEPROM device without using the SPI module.

    As for the oscilloscope captures:

    • The first two images correspond to the failed communication attempt, i.e., they reflect what happened during the execution of the first code block.

    • The last set of images represents the moment when communication was successfully established with the EEPROM device without using the SPI module.

    When attempting EEPROM communication, I first send 0x06 to issue the Write Enable command.
    Then I send 0x02, indicating that a Write operation will follow.
    The address 0x1234 is the target location I intend to write to. In the first example, I attempt to write the value 0xAA to this address; in the second example, I try to write 0x10.

    For reading, I send 0x03 followed by the target address to indicate a Read operation. As a result, in one example I am unable to read any data from address 0x1234, while in another, I successfully read back 0x10.

    I hope this explanation provides clarity.
    Best regards,
    Omer ARSLAN

  • Hello again,

    Upon examining the oscilloscope waveforms, I noticed that the clock signal rises almost simultaneously with the data. Since the EEPROM I’m using samples data on the rising edge of the clock, I suspected that advancing the data slightly ahead of the clock might resolve the issue.

    To test this, I removed the series resistors on the MISO and MOSI lines (set them to 0Ω) and increased the series resistor on the CLK line to 200Ω. With this configuration, communication started working reliably.

    Now, my question is:
    Is there a way to achieve this same timing adjustment on the TMS320F28377S, using the SPI module, without modifying the hardware? Specifically, can I delay the clock signal or advance the data output through a register setting?

    I’m concerned that the resistor-based delay might cause issues under varying temperature conditions (cold and hot environments), which is why I would prefer a more robust software-based or hardware-supported solution.

    Additionally, could you recommend ideal values for series resistors and pull-down resistors on SPI lines to ensure signal integrity?

    Thank you!

    Best regards,
    Omer ARSLAN

  • Omer,

    Take a look at the following table and figure from the F28377S device TRM:

    By adjusting the CLKPOLARITY and CLK_PHASE bits of the SPI configuration, you can adjust the clocking scheme. It sounds like you currently have scheme [x,0], while you want [x,1]? Adjusting this value should remove the need for any external resistor delay.

    For resistors, a pull-up on the CS pin (also called STE or PTE) is sometimes recommended, but generally speaking, SPI does not need external pull-up/pull-down resistors- the C2000 internal pull-up is usually sufficient. If your application is particularly noisy, adding external pull-ups may assist- I can't provide a specific value for you, because that will depend on the requirements of your application.

    Regards,
    Jason Osborn