1
\$\begingroup\$

I have an MCU (tm4c123gh6pm) in which I have configured an I2C slave device. At the moment I don't have resistors to wire the required pull-ups, so I want to use two of the MCU's GPIOs for this purpose.

I have configured two GPIOs as inputs with 'weak' pull-up resistors (not sure what 'weak' means):

static void init_pullup_resistors(void) {
    GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_6);
    GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_7);

    GPIOPadConfigSet(GPIO_PORTB_BASE,
                     GPIO_PIN_6 | GPIO_PIN_7,
                     GPIO_STRENGTH_8MA,
                     GPIO_PIN_TYPE_STD_WPU);
}

I have double checked that, before wiring anything, the two I2C pins are low and the 'pull-up' pins are high.

When I connect SDA to one of the 'pull-ups' it remains high, so fine. However, when I do the same with SCL, it goes low directly. If I try to send a frame from my I2C master dev. (which is a Basys 3), I can see a clock signal in SCL, but it only reaches a few millivolts (not the expected 3.3V).

Why is this happening?

More context: I have checked the tm4c123gh6pm datasheet and have found that its internal resistors are way bigger than what an I2C should use (4.7 kOhms):

enter image description here

I suspect this might be causing the problem, but I don't understand how. As you can see, those resistors are supposed to go from 13 to 35 kOhms. However, the header file documentation (TivaWare SDK) speaks about 'weak' pull-ups. I don't know what is this. See below:

#define GPIO_PIN_TYPE_STD       0x00000008  // Push-pull
#define GPIO_PIN_TYPE_STD_WPU   0x0000000A  // Push-pull with weak pull-up
#define GPIO_PIN_TYPE_STD_WPD   0x0000000C  // Push-pull with weak pull-down
#define GPIO_PIN_TYPE_OD        0x00000009  // Open-drain

Having that I2C requires ~4.7 kOhms pull-ups, ~13-35 don't seem weak, but rather the opposite.

Below is how I initialize the I2C slave dev.:

static void I2C1_Init(void) {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinConfigure(GPIO_PA6_I2C1SCL);
    GPIOPinConfigure(GPIO_PA7_I2C1SDA);

    GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);

    I2CSlaveEnable(I2C1_BASE);
    I2CSlaveInit(I2C1_BASE, I2C_SLAVE_ADDRESS);
}
\$\endgroup\$
2
  • 3
    \$\begingroup\$ A weak pull-up is a high resistance - relative to 4.7K, 30K is weak - it is not pulling the signal up as strongly as a 4.7K resistor would. \$\endgroup\$ Dec 24, 2021 at 0:59
  • \$\begingroup\$ I hate myself for suggesting this, but you may be able to make it work if you use about 4 GPIOs with weak pull-up inputs bundled together to provide pull-up for one I2C line. Or 2 on master side and 2 on a slave. But really, just get the resistors. \$\endgroup\$
    – Maple
    Dec 24, 2021 at 1:08

1 Answer 1

2
\$\begingroup\$

First of all "weak pull-up" means low current. Ohm law: higher the resistance, lower the current. It's a wide used term.

Next, I2C bus are open drain bus. Setting the I2C pins to push-pull can cause damage to the devices on the bus. Open drain devices only drives bus down to ground while communicating. If you have push-pull, it can cause short circuit while some device on the bus "connects" it to the ground and the other one drives it high.

Those weak pull-ups you've quoted are described in GPIO section. I.e. it's not supposed to work with the I2C. That's why it's weaker. I2C bus are usually supposed to have external pull-up resistors. Having 4.7K resistance on MCU die will consume much space which would be a waste if the user won't be using I2C Master.

\$\endgroup\$
3
  • \$\begingroup\$ Apologies, I made a mistake. The I2C pins are not push-pull, the push-pull ones are those I use as 'pull-ups'. These are described in the first code snippet, the I2C ones in the second. However I have just noticed that both snippets use the same function name (my bad). I will fix it. \$\endgroup\$
    – Martel
    Dec 24, 2021 at 9:24
  • \$\begingroup\$ @Martel still, MCU internal pull-ups are usually too weak for I2C. Just get some external resistors. There are probably some lying around you - look for the old/broken/unneeded devices around. \$\endgroup\$
    – NStorm
    Dec 24, 2021 at 10:19
  • \$\begingroup\$ "I have configured two GPIOs as inputs with 'weak' pull-up resistors" I think it is clear that OP is not using them as push-pull outputs, but only as ad-hoc pull-ups \$\endgroup\$
    – Maple
    Dec 24, 2021 at 15:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.