Embedded Systems · Embedded Buses
Sizing Pull-Up Resistors Against Bus Capacitance and Rise Time
The two inequalities that bound a pull-up value: the rise time the mode allows and the sink current a device guarantees, and why the window closes as the bus gets faster.
A pull-up resistor on an open-drain bus has to satisfy two constraints that pull in opposite directions. It must be small enough that the line rises to a valid high level within the fraction of a bit period the protocol allows. It must be large enough that a device which is holding the line low sinks the resulting current without pulling the low level above the guaranteed-low threshold. Between those two bounds is a window, and the width of that window is the real design margin of the bus. On a short, lightly loaded bus the window is enormous and any value in a common range works. On a long bus, or at a high rate, the window can close entirely, and no single resistor value satisfies both.
The rise is an RC curve, not a step
When every device releases the line, the capacitance from the line to ground charges through the pull-up. The capacitance is not a single component: it is the sum of the pin capacitance of every attached device, the trace capacitance, the connector capacitance, and the capacitance of the cable if the bus leaves the board. The specification puts a ceiling on that total — 400 picofarads for the standard and fast modes — and it is a ceiling on the sum, not on any one part.
The voltage follows an exponential approach to the supply rail with a time constant equal to the resistance times the capacitance. The protocol does not require the line to reach the rail. In the standard and fast modes the rise time is specified across a window rather than to a rail: from 0.3 times the supply, the guaranteed-low level, to 0.7 times the supply, the guaranteed-high level. The quantity to compute is therefore the time the line spends crossing that window, which is the time constant multiplied by the natural logarithm of the ratio of the two remaining distances to the rail — 0.7 of the supply at the lower threshold and 0.3 at the upper one.
For the 0.3-to-0.7 window the multiplier is about 0.85. So a bus with 400 picofarads of load and a 1.5-kilohm pull-up has a time constant of 600 nanoseconds and takes roughly 510 nanoseconds to cross the window, against the 300 nanoseconds that fast mode allows. The value fails, and no amount of care elsewhere fixes it: the only remedies are less capacitance, a smaller resistor, or a slower mode.
Working backwards gives the design equation. For a required rise time t and a total capacitance C, the maximum resistance is t divided by the product of C and the logarithmic factor. With 400 picofarads and 300 nanoseconds the bound is roughly 880 ohms. That is the maximum, not the recommendation.
The other bound, from the sink current
The low level is set by the device that is pulling the line down. The specification requires that a device with a low output can hold the line below a guaranteed-low threshold while sinking a specified current. That current is what the pull-up feeds into it: the supply divided by the resistance, plus whatever else is on the line.
The classic figure is three milliamps at 0.4 volts, and devices specified for the faster modes may guarantee more. Rearranging gives a minimum resistance: the drop from the supply to the guaranteed-low level, divided by the sink current the device promises. At 3.3 volts and three milliamps, with the low level allowed to rise to 0.4 volts, that is about 970 ohms. A smaller resistor demands more current than the device promises to sink, and the low level rises above the threshold, where a receiver may read it as indeterminate.
So the two bounds are: resistance below the rise-time limit, and resistance above the sink-current limit. With 400 picofarads of load at 300 nanoseconds of allowed rise time, the upper bound is about 880 ohms, and the lower bound at 3.3 volts with three-millamp devices is about 970 ohms. The window is empty. That is the arithmetic behind the practical rule that a fully loaded fast-mode bus cannot be driven by ordinary pull-ups with devices that guarantee only three milliamps: at the maximum load the specification permits, the two inequalities contradict each other, and the answer is fewer devices, shorter wiring, active pull-ups, or a slower clock.
import math
def bounds(vdd, c_total, t_rise, i_sink, v_il, v_lo=0.3, v_hi=0.7):
"""Pull-up range for one segment; rise time is measured v_lo..v_hi of VDD."""
r_max = t_rise / (c_total * math.log(v_hi / v_lo))
r_min = (vdd - v_il) / i_sink # keep the low level under V_IL
return r_min, r_max
r_min, r_max = bounds(3.3, 400e-12, 300e-9, 3e-3, 0.4)
print(f"{r_min:.0f} ohm .. {r_max:.0f} ohm") # window is empty at this load
The function makes the sensitivity visible. Halving the capacitance doubles the upper bound, and the window opens. Raising the supply raises the minimum resistance for the same sink current, which tightens the window from below. Lowering the supply widens the window at the low end but reduces noise margin at the high end.
Why the load is usually the cable
The pin capacitance of a typical device is a few picofarads, and a few dozen devices on a board contribute perhaps a hundred picofarads. The rest is interconnect. A ribbon cable or a length of unshielded twisted pair adds tens of picofarads per metre, so a couple of metres of cable dominates the total.
This is why the same resistor value that works on a bench with two devices fails on a bus that leaves the board. The capacitance is not visible on a schematic; it is a property of the physical layout, and it grows with every device added, every connector inserted, and every metre of cable.
The practical consequences are a set of rules that are really one rule. Keep the bus short. Keep stubs short, because a stub is a capacitance and also an impedance discontinuity. Avoid connectors where possible. Add devices sparingly, and count the pin capacitance in the budget when deciding whether one more sensor fits. Measure the rise time on a loaded bus rather than assuming it, since the capacitance of a cable is rarely what the datasheet claims once connectors and termination are included.
The intermediate remedies
Before abandoning the rate, there are several options that extend the window.
Reducing the supply voltage lowers the current through the pull-up for a given resistance, which loosens the sink-current bound, and it also lowers the absolute noise margin. Some devices are specified only over a narrow supply range, so this is often not available.
Splitting the bus into segments with a buffer between them isolates capacitance. A buffer that repeats the two-wire protocol presents only its own pin capacitance to each side, so each segment can be sized independently. This is the standard answer for a bus that must span a backplane or connect several boards. The cost is a device that must handle arbitration and stretching correctly, which not every buffer does.
An active pull-up replaces the resistor with a current source or a switched transistor that pulls the line high briefly after it is released and then turns off. It produces a fast rise without the steady-state current of a small resistor, so both bounds can be met at once. The trade is complexity and the risk of a driver that fights a device which is still holding the line low.
Lowering the bus rate is the option that always works. Since the rise time is a fixed fraction of the bit period, halving the rate doubles the allowed rise time and doubles the maximum resistance. A bus that cannot meet fast-mode timing at 400 picofarads is comfortable at the standard rate, which is why a design that must tolerate a long cable usually runs slower rather than fighting the capacitance.
Reading a marginal bus from its symptoms
A bus with too large a pull-up shows a characteristic failure pattern. Transactions succeed when the bus is lightly loaded and fail when more devices are attached or when the cable is longer. The failures appear as not-acknowledges and as corrupted reads, not as hard errors, and they become more frequent as temperature rises, because the resistance of a carbon or thick-film resistor drifts upward and the rise time with it. A scope probe on the clock line shows a visibly rounded rise that fails to reach the rail before the next falling edge.
A bus with too small a pull-up fails differently. The low level is elevated, and the failure appears on devices that sink the least current or that are at the far end of the bus where the accumulated drop is largest. Power consumption rises, which matters on a battery-powered device where the bus may be held low for long periods: a device holding the line low through a small resistor dissipates the full supply across that resistor for the whole low period, and the average current is the duty cycle times that figure.
Both failure modes get worse as more devices are added, which is why a bus that worked with three devices can fail with six even though each new device is individually within specification. The total capacitance and the total leakage both grow with device count, and the pull-up was sized for the original load.
What the resistor does not fix
The pull-up sets the rise, and nothing else. It cannot correct a ground offset between two boards, which appears as a shift in the threshold and is addressed by the differential approach in differential signalling and bus termination. It cannot prevent a device from holding the line low indefinitely, which is the lockup in clock stretching and stuck-bus recovery. And it cannot recover the throughput lost to a slave that stretches the clock, because stretching adds to the low period rather than the high one.
The one thing it does determine is whether the high level is ever reached before the next edge. That is a purely electrical question with two inequalities and one measured quantity, and the measured quantity — total capacitance — is the number that must come from the board rather than from the datasheet.
References
- UM10204: I2C-bus specification and user manual — NXP Semiconductors
- The I2C-bus specification, version 2.1 — Philips Semiconductors, 2000
- SMBus Specification, Version 3.0 — SBS Implementers Forum