I2C

I2C is a two wire bus developed by Phillips originally for the inside of a TV. It is low performance, low distances but simple and very cheap. This has been discovered by the PC industry and got used to hold plug and play info, read temperature and so on. I2C has a master host interface and various sensors. On the motherboard there can be more than one host, resulting in having more than one bus. Usually the host is the master and the other devices are slaves, however be aware, also slave devices can act as masters.

SMbus (System Management bus) is derived from the I2C bus with additional specifications and rules for PC applications.

Different implementations

Many evolutionary steps have been made to I2C and this causes some incompatibilities. I2C is meant for device internal communications where the configurations is known. Therefore using it as plug and play might cause some misinterpretations, confusions and failures.

The simples way is using I2C to send or receive a stream of bits into a device (usually memory devices). Such chips can be read and written as files, whereas the file is /dev/i2c-<nn> and the chip I2C address is set by the files ioctl function call.

Since devices behaving this way are limited, a new approach got introduced to address registers in a device. Devices supporting registers can be used with the command i2cset and i2cget. There is a pointer register that can be written as usual. To read it or read/write to other registers the device considers the content of this pointer register as the register address. On write access, the bytes following the pointer register end in the register selected by the pointer register. To read, two accesses are necessary write to pointer register, then read from what is selected by the pointer register.

Note

Be aware that there are mainly two I2C bus behaviors, devices that use a pointer registers and devices that don't.

Note

Register access commands can cause disastrous effects on devices that do not follow this registers approach as eeproms. When not taking care eeproms can loose their contents, and if this happens on the eeprom on a DIMM, a PC might even permanently refuse to boot afterwards.

Linux implementations

Linux offers two ways of accessing the devices on the I2C bus:

  • Using a kernel driver as /usr/src/linux/drivers/hwmon/LM75.ko that matches the chip. This driver needs to be added to the ic2-core device driver and see /usr/src/linux/Documentation/i2c/instantiating-driver access is then done via /sys/devices see /usr/src/linux/Documentation/hwmon

  • Use the dev-interface to get the routines to access the chip that can be used in a C program /usr/src/linux/Documentation/i2c/dev-interface . The i2c-dev driver will access the i2c-core driver.

See http://venkateshabbarapu.blogspot.de/2012/11/i2c-driver-in-linux.html for a good overview

To see what's up create a kernel with hardware monitoring cat /usr/src/linux/.config | grep CONFIG_HWMON set and select all kinds of sensors as modules, including Miscellaneous i2c chip support, since you probably don't know yet what you have.

There are two packages the lm_sensors that is mainly targeted to i2c chips on the motherboard and i2c-tools to get the command line tools.

A lot of device drivers are involved when it comes to i2c. The i2c-core driver communicates to the i2c host hardware via other kernel drivers. In case of a parallel port i2c adapter i2c-core communicates to i2c-algo-bit that actually does bit banging. i2c-algo-bit then might call i2c-philips-par the device driver that philips proposed and this then calls the device driver parport a abstraction layer of all parports and finally on a PC the device driver parport_pc is called that then accesses the hardware. Finally ther is either i2c-dev to access the devices using i2c commands or a device driver as LM75 that creates the data under /sys

To see what adapters you have:

cat /sys/class/i2c-adapter/i2c-*/name

If i2c-dev is not build into the kernel run modprobe i2c-dev to have the files under /dev created since they are the interface to many programs.

The program i2cdetect -l lets you see what you have.

If there are problems check with ls -l /dev/i2c* if device files are there. To check the functionality of an i2c host i2cdetect -F 0

See: http://www.lm-sensors.org/ to know what host module you have to load for your motherboard: e.g. modprobe i2c-nforce2, modprobe i2c-viapro, modprobe i2c-i801.

Run sensors-detect, it creates as output /etc/conf.d/lm_sensors that holds all stuff detected. Just the modules for the chips found and listed there have to be built with the kernel, others should be disabled now to have faster kernel compilation time and less code produced. Then /etc/init.d/lm_sensors start starts a daemon and reads from the above. Or/and rc-update add lm_sensors default so it will be started at each boot. And to make it visible emerge -pv sensors-applet or something similar that matches your desktop environment.

Or type sensors

External I2C adapters

Parallel port I2C adapter

For the hardware hackers, the parallel port can be used as I2C host. So you can extend the I2C bus so it leaves the PC. Build a kernel to:

modprobe i2c-parport type=3

for the ELV adapter. The ELV adapter is the only well documented and identified adapter in /usr/src/linux/Documentation/i2c/busses/i2c-parport. Check dmesg if the driver could grant access to the parallel port.

You might have a conflict with the driver lp for the printer, so compile the kernel with lp as module. This driver is poor on the hardware side but supports all modes as i2cdetect -F<adapter no> shows.

USB I2C Adapter

To not risk a conflict with the parallel port check the simple USB adapter http://www.harbaum.org/till/i2c_tiny_usb/index.shtml.

Note

Be aware it is just a USB 1 device so it will not run on USB 2.0

Load its driver by

modprobe i2c-tiny-usb comes with the Linux sources and gets compiled when CONFIG_I2C_TINY_USB is set. cat /usr/src/linux/.config | grep TINY shows if you have it. i2cdetect -l should show it including its I2C bus number i2c-4 i2c i2c-tiny-usb at bus 001 device 013 I2C adapter. On this example it is I2C bus number 4 attached to USB bus number 1 where it is device number 13.

Unfortunately this driver does not support all functions as i2cdetect -F<adapter no> shows.

VGA connector I2C Adapter

An even more easy way is using a spare VGA (or monitor) socket of your PC. On a analog VGA connector Pin 10 is ground, pin 12 SDA and pin 15 SCL. To get power the +5V from pin 9 can be used carefully as long not too much current is requested.

Note

Too high current or a short to ground might damage something on the motherboard. A Acer Aspire One note book motherboard has a small SMD diode in the range of 100mA that supplies the required 5V. Larger current will blow this diode.

The graphic cards i2c driver as modprobe i2c-nforce2 or modprobe i2c-i801 can then be used.

Access rights of I2C host adapters

The system should be configured in a way that just root has access to the i2c adapters, since most of them are used for the system and as mentioned i2c is not plug and play so i2c chips could be confused and this even permanently. However if you build an external i2c adapter with some sensor chips it is highly recommended not running as your application as root. The way out is writing a udev rule /etc/udev/rules.d/10-local.rules as for the i2c-tiny-usb adapter. The rule allows the uucp group that is also used for serial connections to access this i2c adapter:

SUBSYSTEMS=="usb", ATTRS{product}=="i2c-tiny-usb", GROUP="uucp"

A way to find the i2c-tiny-usb is trying to open sequentially all /dev/i2c-* until the desired chip attached to the i2c-tiny-usb host adapter is found. The software doing this should distinguish between having access to the i2c adapter or if open fails due to not existing host adapter.

Observing an external LM75 chip

Using the dev interface

The LM75 is a temperature sensor chip using the dev-interface the chip data sheet must be known. The access works then using the i2c calls.

To see how many i2c bus master you have

i2cdetect -l

The i2c tiny adapter has been detected as i2c bus number 0.

i2c-0 i2c i2c-tiny-usb at bus 004 device 003 I2C adapter

Check what is attached to i2c bus number 0 by scanning through the addresses

i2cdetect 0

Check if something is found. If UU appears the device might be there but busy, so unload the driver (e.g rmmod lm75) and redo the scanning. Under 0x47 a chip is found. The address of the LM75 chip can be 0x48 for the fist chip (chip no 1) to 0x4f for the last chip (chip no 8). If all address pins of the chip are wired to Vcc the address is 0x4f. Check the registers of the device found

i2cdump 0 0x4f

A device can have 256 registers that are selected by the 8 bit wide pointer register.

Knowing that is a LM75 chip and looking at its data sheet, shows the chip has in its 8bit wide pointer register just 3 bits implemented. This explains why the bytes read by i2cdump 0 0x4f repeat every 8Bytes.

Instead of dumping everything individual registers can be read:

i2cget<bus> <chip> <register>

The temperature is inside register 0x00

i2cget 0 0x4f 0x00

When sure what to do, avoid the question and confirmation

i2cget -y 0 0x4f 0x00

Just 8 bits are read, but the temperature register contains 16 bit. Therefore the i2cget program needs to be called as follows:

i2cget -y 0 0x4f 0x00 w

0x801c

or using Packet Error Checking (PEC) check if it is supported by your adapter i2cdetect -F 0

i2cget -y 0 0x4f 0x00 w p

hold the finger on the chip to heat it up and you get

0x8025

Or to have it hands-free

watch i2cget -y 0 0x4f 0x00 w

Just the upper 9 bits contain the two's complement temperature where the least significant bit represents a step of 0.5°C and when set, the most significant indicates below 0°C. The i2cget puts low byte first. It is actually better to read just 8 bits since the result is exactly the temperature in °C (but hex)

The chip has other registers to control a temperature alarm output. Those registers can be read. The alarm off register:

i2cget -y 0 0x4f 0x02 w

0x004b

= 75°C = 0x4b and the default value after reset

The alarm on register:

i2cget -y 0 0x4f 0x03 w

0x0050

= 80°C 0 0x50 and the default value after reset

Using a kernel device driver

There is the kernel device driver lm75 documented /usr/src/linux-*-gentoo/Documentation/hwmon/lm75.txt that creates the interface. modprobe lm75 and lsmod and to see where it appears in /sys do tree /sys/bus/i2c/ or more direct tree /sys/module/lm75 this is the driver and not the chip. To access the chip the bus number used on the adapter as found with i2cdetect -l (in the example 10) and chip address as found with i2cdetect 10 (in the example 4f) need to be known. To see the temperature in m°C

cat /sys/module/lm75/drivers/i2c\:lm75/10-004f/temp1_input

The max temperature register can be set as

echo 60000 > /sys/module/lm75/drivers/i2c\:lm75/10-004f/temp1_max

MLX90614 Infra Red Thermometer

The MLX90614 chip from Melexis is a Infra Red Thermometer in TO-39 case with 4 pins that can be directly connected to an external i2c bus.

Check what i2c buses you have i2cdetect -l

Check if the chip is there under its default address 0x5a i2cdetect <bus number>

Other chips having the same i2c address might be there. To be sure this is not the case a the internal EEPROM where the bus address is configured can be read (writing to this address is also possible to program a chips with different addresses to be used on the same i2c bus) i2cget -y <bus number> 0x5a 0x2e. If the response is 0x5a then the chances are high that the chip has been found and is identified. In the datasheet the address for this i2c is on address 0x0e and not 0x2e, this is correct since the chip has a RAM inside starting at address 0x00 and the EEPROM has an offset of 0x20.

Operating the chip gets easy i2cget -y <bus number> 0x5a 0x06 gets the hex value for the ambient temperature and i2cget -y <bus number> 0x5a 0x07 gets the hex value for the object temperature, this is the infrared radiation passing through the chips window. To get the temperatures in Kelvin those two hex values need to be multiplied with 0.02K. 273.15 need then to be subtracted to get °C. The sensor is able to measure temperatures from -70.01°C to + 382.19°C with a resolution of 0.02°C.

Observing a memory chip

The 256Byte 24LC02 contains also pins that look as to set the I2C bus address, but those pins are fake and internally not connected. Other devices as the 24C01and the 24C02 use all those pins, the 24C04 uses just the upper two, the and 24C08 just the upper most and finally the 24C16 uses none of them. The device can be addressed using the range 0x50..05f. To read from the device the internal address counter has to be set. This is done by a write without data. (If possible wire the WP pin high to have the chip write protected, so accidentally writes to not damage the data inside). After that it can be read from the device, and with every read the address counters increases and the next byte appears.

First check witch of the many i2c buses that you have has the memory chip attached:

i2cdetect -l

Note

i2cset and i2cget are not suited to read from the memory device since they assume that there is a pointer register, however memory devices use an pointer register free way of accessing them.

Memory devices can be read more direct and faster. However this require a different behavior and bring also danger, in case i2c sensor software accidentally write to a eeprom. The program eeprog from http://www.codesink.org/eeprog.html can be used to read and write i2c devices.

eeprog -xf /dev/i2c-0 0x50 -r 0:256

and to write, as example what data returns goes into the device at address 0.

date | eeprog -f /dev/i2c-0 0x50 -w 0

The package i2c-tools from version 3.1.0 comes also with tools to program eeproms

I2c bit banging

Some small SMD I2C memory devices come in a 5pin package and illustrating therefore how simple and cheap a I2C interface is. Data transfer is done using a data line SDA and a clock line SCL.

Getting even rid of the SCL would be possible, but would increase complexity of the timing that would probably end up with a crystal oscillator or a PLL with preamble and this might even cause more than one additional pin.

To avoid bus contention when two devices want to drive the two lines SDA and SCL (I2C allows more than one bus master) the devices can just sink current and the sourcing of the high level is done using pull up resistors. Watch out I2C might use different voltages 3V or 5V.

Bit transfer

To transmit a single bit on the SDA line i2c uses the following definitions:

  1. When SCL is high SDA is stable and can be read.

  2. When SCL is low SDA can change.

Start, Stop condition

To transmit single bits is not enough, a framing is required to tell when a Byte begins and it even has to tell when a frame (combination of many Byte transfers) terminates.

The framing is done by violating the regular bit transfer rules, where SDA is not allowed to change when SCL is high. Therefore the following conditions are possible:

  1. Changing SDA to low when SCL is high resulting as start

  2. Changing SDA to high when SCL is high resulting as stop

This results that the idle bus has both lines high (SDA and SCL). An un-powered bus has therefore both lines low.

Byte transfer

From the idle condition with both signals high, the i2c master sets the SDA line to low and indicates that a transfer continuous. Now SCL goes low and the master can put the first data bit (most significant) on the bus and continuously transmit the bits. After the last bit has been transferred SCL goes low and the device having received the data has to acknowledge the transfer by putting a zero to SDA.

When the receiving node does not acknowledge the byte transfer, the SDA line stays high. After rising SCL, no stop condition can occur since the SDA line is already high. Therefore the master has to react, it can generate either a stop condition (violating the rule that data must be stable while clock is high) to abort the transfer, or a repeated start condition to start a new transfer.

Clock stretching

Slaves can slow down the master by additionally pulling down the SCL, after a low SCL is detected.

Timeout

It can happen, that communication stops in the middle of a transfer. To not block the bus forever, after a timeout a master can re-initiate the communication. This puts some minimum clock speed to the devices.

Bus arbitration

Since I2C allows more than one master on the bus and both lines have pull up resistor, it may happen that when a master want to put 1 on the bus, a 0 remains, since some other devices are active. This can be other masters, but also slaves can slow down the clock signals like that. Therefore a master must read back what he has sent.

Data transfer

Since I2C is a multi device bidirectional bus frames containing multiple Bytes are necessary.

Frames start with a start condition and stop with a stop condition, therefore between start and stop condition multiple bytes can be sent.

Addressing is necessary to select the destination devices. The most significant 7bits of first byte put on the bus indicate therefore the address of the chip. The last significant bit indicates:

  1. When zero a write access

  2. When one a read access

This limits the i2c to maximum 127 devices.

Usually the address is fixed assigned to the chip, but to allow more than one chip of the same type to be used on the same i2C bus, some lower address bits are often fed to pins to add an offset to the address.

Obviously every bus device needs it own address. The http://www.smbus.org/ defines how those addresses have to be used and Phillips the inventor of I2C has also such a list.

There is even a address resolution protocol defined when addressing gets complicated.

Send and Receive bits

This is straight forward, after the address the second byte holds the data. Depending on the read/write bit in the first byte the master provides it and makes a write or it comes from the slave to be read by the master. Basically the read write bit says who has to put the data to the bus. Write means the master read means the slave.

Write/Read byte/word

Write/Read byte is not the same as Send/Receive bits.

Send/Receive bits goes to or comes from the device, but usually a device is not just a pipe where bits can be stuffed in or taken from.

The write/read byte has therefore as second byte a command code, and the third byte is the data. The write/read word command has a forth byte containing the high byte of the word.

Process call

Often something is sent to a device and then a response is requested. The process call combines a write word command with a read word command less version and without a stop condition between them. The slave address is sent twice but the command just once.

Block read/write

When more than a word needs to be written, the third bytes holds the number of bytes, and then the data bytes follow. However the block read sequence is different. After the command code and other start bit is set followed by the slave address and then the count byte and data.

Block write-block read process call

Similar to the process call, this transfer deals with blocks.

SMBus host notify protocol

I2C frames usually hold just the destination address, but in some cases also the source address is required, so the receiving device knows who wants something from him.

Therefore the first byte holds the SMBus host address and a write bit. The second is the master address followed by two data bytes holding a 16 bit status. Whit this message SMBus devices can become masters and the SMBus host acts as slave.

Packet Error Code (PEC)

Optionally a Packet Error Code (PEC) Byte can be put at the end of a frame. It is a CRC-8 checksum calculated on all the message bytes (including addresses and

read/write bits) and sent by the device that has sent the byte before the PEC byte.


Linurs Servernest startpage