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.

TMS320F28027: Cannot use I2C and SPI buses together but both work fine when used separately

Part Number: TMS320F28027

I'm trying to use the I2C and SPI buses on my project.

The problem is that when I attempt to use both together by uncommenting each respective block of code, the SPI and I2C don't work right.

Both blocks work perfectly when the other is commented out. I use the SPI bus to program a DAC and PGA, and use the I2C bus to program a bank of LEDs.

I'll paste the relevant code below. As an example the code labeled "ERROR: HANGS HERE" gets stuck waiting for an ACK when the SPI block is also compiled in but always works when the SPI code is commented out.

I realize it's difficult to make suggestions based on code snippets, but does anyone have an idea where I should look for the problem? This program is running from flash and I copy time-critical functions to RAM.

// Using the I2C bus.  Works fine if SPI is not compiled in.

void set_leds(Uint16 slave_addr, Uint16 on_off)
{
    int i;
    I2caRegs.I2CSAR = slave_addr;
    I2caRegs.I2CMDR.all = 0x4620;       // FREE, MST, TRX, IRS
    I2caRegs.I2CCNT = LEN_ON_MSG;
    I2caRegs.I2CMDR.bit.STT = 1;        // Start condition
    I2caRegs.I2CMDR.bit.STP = 1;        // Stop condition will be generated when CNT=0
    if (on_off == ON)
    {
        for (i=0; i<LEN_ON_MSG; i++)
        {
            I2caRegs.I2CDXR = on_msg[i];
            while (I2caRegs.I2CSTR.bit.XRDY == 0);  // ERROR:  HANGS HERE
        }
    }
    else
    {
        for (i=0; i<LEN_ON_MSG; i++)
        {
            I2caRegs.I2CDXR = off_msg[i];
            while (I2caRegs.I2CSTR.bit.XRDY == 0);
        }
    }
}
...
...
...
// I2C initialization.

void i2c_init(void)
{
    I2caRegs.I2CMDR.all = 0;                // Disable I2C module and clear all options
    I2caRegs.I2CFFTX.all = 0;
    I2caRegs.I2CFFRX.all = 0;

    // Set the clock rates:
    //    Module clock rate: (CPU clock)/(IPSC + 1) = 10 MHz.
    //    I2C bus clock divider registers: 10 MHz/((ICCL+d)+(ICCH+d))
    //      where'd'=5 (see sprufz9d.pdf) produces bus clock at 300 KHz, 50% duty cycle.
    I2caRegs.I2CPSC.all = 5;                // 60 MHz/(IPSC+1) = 10 MHz
    I2caRegs.I2CCLKL = 3;                   // ICCL+d = 6
    I2caRegs.I2CCLKH = 3;                   // ICCH+d = 6
    CLK_enableI2cClock(myClk);
    I2caRegs.I2CSAR = TLC59116_SLAVE_ADDR_60;
    I2caRegs.I2CMDR.bit.IRS = 1;            // Enable I2C module
    while (I2caRegs.I2CMDR.bit.STP != 0);
    return;
}
...
...
...
// SPI initialization. Works fine if I2C is not compiled in.

void spi_init()
{
    CLK_enableSpiaClock(myClk);
    SPI_resetChannels(mySpi);
    SPI_setCharLength(mySpi, SPI_CharLength_16_Bits);
    SPI_setMode(mySpi, SPI_Mode_Master);
    SPI_setBaudRate(mySpi, SPI_BaudRate_500_KBaud);
    SPI_setPriority(mySpi, SPI_Priority_FreeRun);
    SPI_enableChannels(mySpi);
    SPI_disableLoopBack(mySpi);
    SPI_enableTx(mySpi);
    SPI_setTriWire(mySpi, SPI_TriWire_ThreeWire);
    SPI_setClkPhase(mySpi, SPI_ClkPhase_Delayed);
    SPI_setClkPolarity(mySpi, SPI_ClkPolarity_OutputRisingEdge_InputFallingEdge);
    SPI_enable(mySpi);
    return;
}

void spi_fifo_init(void)
{
    SPI_enableFifoEnh(mySpi);
    SPI_resetTxFifo(mySpi);
    SPI_clearTxFifoInt(mySpi);
    return;
}

  • I forgot to include the GPIO initialization.

    // GPIO initialization
    void gpio_init(void)
    {
        // Set up GPIO 12 (J2/pin 3) as output for debugging on scope.
        GPIO_setMode(myGpio, GPIO_Number_12, GPIO_0_Mode_GeneralPurpose);
        GPIO_setDirection(myGpio, GPIO_Number_12, GPIO_Direction_Output);
    
        // Set up GPIOs 28 and 29 for use with serial I/O.
        GPIO_setPullUp(myGpio, GPIO_Number_28, GPIO_PullUp_Enable);
        GPIO_setPullUp(myGpio, GPIO_Number_29, GPIO_PullUp_Disable);
        GPIO_setQualification(myGpio, GPIO_Number_28, GPIO_Qual_ASync);
        GPIO_setMode(myGpio, GPIO_Number_28, GPIO_28_Mode_SCIRXDA);
        GPIO_setMode(myGpio, GPIO_Number_29, GPIO_29_Mode_SCITXDA);
    
        // Set up GPIOs 32 and 33 for use by the I2C.
        GPIO_setPullUp(myGpio, GPIO_Number_32, GPIO_PullUp_Enable);
        GPIO_setPullUp(myGpio, GPIO_Number_33, GPIO_PullUp_Enable);
        GPIO_setQualification(myGpio, GPIO_Number_32, GPIO_Qual_ASync);
        GPIO_setQualification(myGpio, GPIO_Number_33, GPIO_Qual_ASync);
        GPIO_setMode(myGpio, GPIO_Number_32, GPIO_32_Mode_SDAA);
        GPIO_setMode(myGpio, GPIO_Number_33, GPIO_33_Mode_SCLA);
    
        // Set up GPIOs 6, 7, 16, 17, 18 for SPI.
        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_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_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);
    
        // Set up GPIO 6 and 7 used as chip select for PGA (6) and DAC (7).
        GPIO_setDirection(myGpio, GPIO_Number_6, GPIO_Direction_Output);
        GPIO_setMode(myGpio, GPIO_Number_6, GPIO_6_Mode_GeneralPurpose);
        GPIO_setDirection(myGpio, GPIO_Number_7, GPIO_Direction_Output);
        GPIO_setMode(myGpio, GPIO_Number_7, GPIO_7_Mode_GeneralPurpose);
        GPIO_setPullUp(myGpio, GPIO_Number_6, GPIO_PullUp_Disable);
        GPIO_setPullUp(myGpio, GPIO_Number_7, GPIO_PullUp_Disable);
    
        GPIO_setHigh(myGpio, GPIO_Number_6);
        GPIO_setHigh(myGpio, GPIO_Number_7);
    }

  • Hi Mike,

    Do they both work if you exclusively run from RAM (assuming you have the memory available)? Can you please share more of what you have on the SPI side, all you have is init functions.

    Could you confirm that the I2caRegs.I2CDXR register has successfully been written to in order for the while loop to break. If possible could you probe the I2C and SPI signals to see if there is any activity on either bus.

    Best,
    Kevin
  • Kevin, here is an example of the code that accesses the SPI:

    void DAC_program(void)
    {
        // First output byte contains bits GA and SHDN in bits 13 and 12, and second contains the output value in bits 11-0.
        GPIO_setLow(myGpio, GPIO_Number_7);  // Chip select for this device
        SPI_write(mySpi, (0x3F<<8) | 0xFFF);
        DELAY_US(100);
        GPIO_setHigh(myGpio, GPIO_Number_7);
    }

    Our hardware engineer told me that he had to cut traces on the Launchpad to get the SPI and I2C to work simultaneously, namely JP5/JP6/JP8/JP10.  I'm waiting to see if he can run my code before modifying my boards.

    -- Mike

  • Hi Mike,

    You shouldn't need to 'cut' any traces for I2C/SPI to work simultaneously on this board. Maybe there is an accidental short being created on JP4-JP11, since on the Launchpad you need to populate a 0 ohm resistor or create a solder bridge for access to GPIO 16, 17, 32, or 33. Your board will need to be modified, see below:

    Best,

    Kevin

  • Hi Mike,

    Sorry, you were right.

    You would need to cut some of the traces for both SPI and I2C to work. The signal pairs are tied together between the jumper pairs and the header pin.

    Best,
    Kevin
  • I'm going to ship off my boards to our hardware engineer, after I finish making some firmware changes, and he'll cut these traces and make some other minor fixes.

    Then I'll have a chance to try both buses working at the same time.

    Thanks.

    -- Mike