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.

TM4C129ENCPDT: Configure TivaWare Device as I2C/SMBus Slave

Part Number: TM4C129ENCPDT


Hi,

I am working on a platform that will be using the TM4C129ENCPDT Arm chip. For development, I'm using the EK-TM4C129EXL.

This will be acting as an I2C/SMBus slave, which will receive commands from a host board acting as the master. My board will parse the command (and any params) sent to it by the master, and return any necessary data when necessary. For testing, I am trying to setup my device in slave mode, and am connecting an Analog Discovery 2 to send commands as an I2C master. Ideally, once the slave receives the stop condition, an interrupt will fire, allowing me to pull the contents of the message from the Rx buffer. 

I am using the corresponding SW API for development. 

I am having issues getting the I2C interrupt to proc. I've used the AD2 as an I2C master before, so I suspect the issue is likely somewhere in my C code (posted below). 

////////////////////////////////////////////////
// code in tm4c129encpdt_startup_ccs.c
extern void i2cIntHandler(void);
...
#pragma DATA_SECTION(g_pfnVectors, ".intvecs")
void (* const g_pfnVectors[])(void) =
{
    (void (*)(void))((uint32_t)&__STACK_TOP),
                                            // The initial stack pointer
    ResetISR,                               // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    ...
    i2cIntHandler,                          // I2C0 Master and Slave
    ...
};
////////////////////////////////////////////////
////////////////////////////////////////////////
// code in init.c

#include "init.h"

#include <stdio.h>

#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"

void i2cIntHandler(void)
{
    uint8_t buffer[4] = {0};
    uint32_t x = 0u;

    x = I2CFIFODataGetNonBlocking(I2C0_BASE, buffer);

    uint32_t y = x;
}

void initSMBus(void)
{
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2); // configure SCL line
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);    // configure SDA line

    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));

    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);

    I2CSlaveEnable(I2C0_BASE);
    I2CSlaveFIFOEnable(I2C0_BASE, I2C_SLAVE_RX_FIFO_ENABLE);
    I2CRxFIFOConfigSet(I2C0_BASE, I2C_FIFO_CFG_RX_SLAVE);

    uint8_t address = 0x12;
    I2CSlaveInit(I2C0_BASE, address);
    I2CSlaveAddressSet(I2C0_BASE, 0, address);

    I2CSlaveIntEnable(I2C0_BASE);
    I2CSlaveIntEnableEx(I2C0_BASE, I2C_SLAVE_INT_STOP);
    I2CIntRegister(I2C0_BASE, i2cIntHandler);
}

I will also attach a screenshot of my AD2 setup. 

Any ideas as to what my issues might be? I am confident that my "master" is correctly connected to the devkit. 

Thank you,

Zach Sharp

  • Hello Zach,

    Remove this function call as it's only for TM4C123x devices:

    I2CSlaveIntEnable(I2C0_BASE);

    You need to enable the interrupts at the NVIC level too:

    IntEnable(INT_I2C0);

    Also for certainty, make sure the Master Interrupts are enabled as well:

    IntMasterEnable();

    Best Regards,

    Ralph Jacobi

  • Hmmm I'm still having issues. I do have other interrupts working in the system (timer and ADCs) so I know that the master interrupts are enabled.

    After further debugging, it looks like there might be some issue with the pull ups. Here is a scope capture of the I2C SCL and SDA lines after initialization, which should be held high per the I2C protocol.

    To my understanding, the following API calls will configure the pull-up resistors for each of the lines, unless I am misunderstanding the documentation. These functions are from the TivaWare libraries gpio.c/.h library files. 

    void
    GPIOPinTypeI2CSCL(uint32_t ui32Port, uint8_t ui8Pins)
    {
        //
        // Check the arguments.
        //
        ASSERT(_GPIOBaseValid(ui32Port));
    
        //
        // Make the pin(s) be peripheral controlled.
        //
        GPIODirModeSet(ui32Port, ui8Pins, GPIO_DIR_MODE_HW);
    
        //
        // Set the pad(s) for push-pull operation.
        //
        GPIOPadConfigSet(ui32Port, ui8Pins, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
    }
    
    void
    GPIOPinTypeI2C(uint32_t ui32Port, uint8_t ui8Pins)
    {
        //
        // Check the arguments.
        //
        ASSERT(_GPIOBaseValid(ui32Port));
    
        //
        // Make the pin(s) be peripheral controlled.
        //
        GPIODirModeSet(ui32Port, ui8Pins, GPIO_DIR_MODE_HW);
    
        //
        // Set the pad(s) for open-drain operation with a weak pull-up.
        //
        GPIOPadConfigSet(ui32Port, ui8Pins, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD);
    }

    So I think the root of the issue is something related to the pull-up resistor configuration, though I'm not too sure what else needs to be done in SW. I wonder if there is a jumper or 0-Ohm resistor that I need to populate on the TM4C129ENCPDT devkit.

    Thank you for your help.

  • Hello Zach,

    Thanks for sharing that detail about system setup. The next issue is now clear.

    The internal pull-up resistors on the TM4C MCU are not strong enough to used for an I2C bus application which means the following:

    1. You need to use external pull-up resistors on the pins for I2C to function correctly.
    2. The TivaWare I2C API does not configure for a pull-up resistor so there isn't a situation where there are parallel resistors on the I2C bus lowering the overall resistance.

    Best Regards,

    Ralph Jacobi

  • Thank you for the quick response.

    I'll go ahead and give that a shot and report back.

  • Yup! Adding the external pullups resolved the issue, and I am getting my interrupt to successfully trigger. Thank you for the assistance Slight smile