I2C
Two-wire addressable bus (SDA/SCL). Configuration EEPROMs, sensors, and RTCs hang off it, and the EEPROM often holds the secrets.
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
- Tap SDA and SCL (and share GND) with a
bus-pirate, an FT232H, or an i2cdriver. Alogic-analyzerwith an I2C decoder confirms the wiring and speed first. - Scan the bus to enumerate live addresses:
i2cdetect -y 1 # list responding 7-bit addresses on bus 1
- Dump a device (an EEPROM at 0x50):
i2cdump -y 1 0x50 # read the whole address space
- 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
- For structured transactions or larger reads, use
i2ctransferto 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.