Wiki / Protocols

I2C

Two-wire addressable bus (SDA/SCL). Configuration EEPROMs, sensors, and RTCs hang off it, and the EEPROM often holds the secrets.

Controller (MCU) Target (EEPROM/sensor) SDA SCL GND SDA SCL GND
SDA (data) and SCL (clock) are shared by every device on the bus, both pulled up to VCC by resistors. Each target answers only to its own 7-bit address, so many chips coexist on the same two wires - the diagram shows one target for clarity.

I2C (Inter-Integrated Circuit, "I-squared-C") is a two-wire synchronous bus where many addressed devices share one data line (SDA) and one clock line (SCL). A controller starts every transaction and names a target by its 7-bit address; only that device responds. It is how a board wires up its small support chips, and one of those is very often an EEPROM worth reading.

What it is

I2C is a multi-drop, half-duplex bus. Both lines are open-drain and idle HIGH through pull-up resistors to VCC; a device asserts a line by pulling it LOW. A transfer is framed by a START condition (SDA falls while SCL is HIGH) and a STOP (SDA rises while SCL is HIGH), and each byte is acknowledged by the receiver pulling SDA low for a ninth clock (ACK/NACK).

Pin Role
SDA bidirectional data, open-drain
SCL clock, driven by the controller
GND common reference

7-bit addressing gives 128 slots, of which 112 are usable (16 are reserved). Standard speeds are 100 kHz and 400 kHz. VCC is shared only as the pull-up rail, not necessarily wired between your tool and the target.

Why it matters

The support chips on I2C are where useful state lives. A configuration EEPROM (24-series, addresses around 0x50 to 0x57) frequently stores Wi-Fi credentials, calibration constants, serial numbers, MAC addresses, and boot or feature flags. Because the bus has no authentication, anything on it can read those bytes and, on a writable EEPROM, flip them: change a region lock, enable a hidden mode, or corrupt calibration.

How to work it

  1. Tap SDA and SCL (and share GND) with a bus-pirate, an FT232H, or an i2cdriver. A logic-analyzer with an I2C decoder confirms the wiring and speed first.
  2. Scan the bus to enumerate live addresses:
i2cdetect -y 1              # list responding 7-bit addresses on bus 1
  1. Dump a device (an EEPROM at 0x50):
i2cdump -y 1 0x50           # read the whole address space
  1. Write a byte to flip a config value (know exactly what you are changing):
i2cset -y 1 0x50 0x00 0xff  # write 0xFF to register/offset 0x00
  1. For structured transactions or larger reads, use i2ctransfer to send an address pointer then read a block.

Pitfalls

  • Missing pull-ups: tapping the bus without pull-ups, or adding extra strong ones, breaks signalling. The board usually already has them; do not double up heavily.
  • Voltage levels: 3.3V and 5V I2C both exist. Driving a 3.3V bus at 5V can damage devices; use level shifting if unsure.
  • Clock stretching: some targets hold SCL LOW to buy time. A tool that ignores stretching will misread them.
  • Address ambiguity: datasheets quote 7-bit or 8-bit (shifted) addresses inconsistently. If a device will not answer, try the shift.

Further reading