I2C on the Gumstix

As of 2010, all Gumstix customers should be using Gumstix OpenEmbedded, not Buildroot.

The Gumstix Developer's website is www.gumstix.org

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

For legacy customers still requiring buildroot:

A tutorial to get I2C working on the Gumstix for use with things like the Robostix.

General
Note: the I2C section of the gumstix motherboard I/O page.

There are two ways to enable I2C on your gumstix. You could either: 1) use pre-compiled modules (recommanded), or 2) build the modules from source

Using the pre-compiled modules is preferred because: a) it's quick b) it works

When building the modules from source, there is a risk that the wifistix would not work.

Using precompiled modules
This method involves transferring a few packages to the gumstix from your host computer, and install the i2c modules on your gumstix. It is a clean and easy way to enable I2C on your gumstix.

The precompiled modules are specific to a version of the kernel.
 * 2.6.11 - i2c-modules-2.6.11.tar.gz
 * 2.6.15 - i2c-modules-2.6.15.tar.gz
 * 2.6.17 - i2c-modules-2.6.17.tar.gz
 * 2.6.18 - i2c-modules-2.6.18-pre-1143.tar.gz for versions of 2.6.18 prior to revision 1143. These versions used the SLOB version of kmalloc.
 * 2.6.18 - i2c-modules-2.6.18-1143.tar.gz for SVN revisions 1143 thru 1184. These versions used the SLAB version of kmalloc.
 * 2.6.18 - i2c-modules-2.6.18-1185.tar.gz for SVN versions 1185 and onwards. These versions use GCC 4.1.1

Copy the appropriate tarball to your gumstix. Let's assume you copied it into /tmp (ramdisk). Do the following to install the precompiled i2c modules: cd / tar xzf /tmp/i2c-modules-2.6.11.tar.gz cd lib/modules/2.6.11gum cp modules.symbols modules.symbols.org cp modules.dep modules.dep.org cat mod.sym >> modules.symbols cat mod.dep >> modules.dep

Now you are done! Once you're happy that everything is working you can remove mod.dep, mod.sym, modules.symbols.org and modules.dep.org files. You may now move to "Starting I2C" (see below).

Building the modules from source
An alternative way (instead of using the pre-compiled modules), is to do it the hard way (i.e. build from source).

1. Begin by getting a functional Buildroot running.

2. Enter the gumstix-buildroot/target/device/Gumstix/basix-connex (if you are using ether a basix or connex board) directory and edit linux.config (backing it up first...) Add the following lines in the appropriate place (hint: search for "I2C support"):

CONFIG_I2C=m CONFIG_I2C_CHARDEV=m
 * 1) I2C support


 * 1) I2C Algorithms
 * 2) CONFIG_I2C_ALGOBIT is not set
 * 3) CONFIG_I2C_ALGOPCF is not set
 * 4) CONFIG_I2C_ALGOPCA is not set
 * 1) CONFIG_I2C_ALGOPCF is not set
 * 2) CONFIG_I2C_ALGOPCA is not set

CONFIG_I2C_PXA=m
 * 1) I2C Hardware Bus support
 * 2) CONFIG_I2C_ISA is not set
 * 3) CONFIG_I2C_PARPORT_LIGHT is not set
 * 4) CONFIG_I2C_STUB is not set
 * 5) CONFIG_I2C_PCA_ISA is not set
 * 1) CONFIG_I2C_STUB is not set
 * 2) CONFIG_I2C_PCA_ISA is not set

or at your own risk use this linux-2.6.11.config or linux-2.6.15.config. You can also setup the i2c stuff through menuconfig: cd gumstix-buildroot/build_arm_nofpu/linux-* make ARCH=arm menuconfig

For the 2.6.11 kernel, under 'I2C Support -->' set 'I2C Support' to . Set 'I2C device interface' to . Under 'I2C Hardware Bus support --->' set 'I2C interface in Intel PXA2x0' to <M></tt>. Exit from menuconfig, saving your changes. The .config file will now contain the appropriate settings. You may want to copy this to gumstix-buildroot/sources/linux.config.

For the 2.6.15 and newer kernels, under 'Device Drivers -->'</tt> goto 'I2C Support -->'</tt> and set 'I2C support'</tt> to <M></tt>. Set 'I2C device interface'</tt> to <M></tt>. Goto 'I2C Hardware Bus support'</tt> and set 'Intel PXA2XX I2C adapter (EXPERIMENTAL)'</tt> to <M></tt>. Exit from menuconfig, saving your changes. The .config file will now contain the appropriate settings. You may want to copy this to gumstix-buildroot/target/device/Gumstix/basix-connex/linux.config.

3. If your buildroot is earlier than revision 767 (your < 767) (note: revision 767 is fairly old - Jan 25, 2006, so this only applies if you're using a really old buildroot), then you'll need to grab the 999-gumstix-i2c-bugfix.patch file and copy it into gumstix-buildroot/sources/kernel-patches</tt>. For newer versions of buildroot, the patch is either incorporated, or not required.

4. Remove the old kernel (while you're still in the linux directory). This will trigger the top-level buildroot to actually rebuild linux. rm arch/arm/boot/compressed/vmlinux

5. Run "make" at the gumstix-buildroot directory again to build the new kernel.

6. Copy the kernel and modules across or replace the filesystem image.

Note: I couldn't get the wifistix to work properly once I've gone through all the above procedure (i.e. building from source) and replacing the filesystem image. I therefore recommand using the pre-compiled modules. BTW, I don't see why the filesystem image should be replaced anyway.

Configuring the kernel for master/slave
If you are building from source, be sure CONFIG_I2C_PXA_SLAVE is set correctly in your buildroot's linux.config (set to 'n' if your Gumstix will be the master). If this changes, you will need to rebuild the kernel.

Starting i2c
Boot the gumstix and then "modprobe i2c-pxa"</tt> and "modprobe i2c-dev"</tt>. Under 2.6.15, you should see some output like this: i2c /dev entries driver I2C: i2c-0: PXA I2C adapter{CODE}
 * 1) modprobe i2c-dev
 * 1) modprobe i2c-pxa

Under 2.6.11, you should see some output like the following: i2c /dev entries driver insmod: cannot insert `/lib/modules/2.6.11gum/kernel/drivers/i2c/i2c-core.ko': File exists (-1): File exists i2c_adapter i2c-0: found device 0x20 i2c_adapter i2c-0: found device 0x7e
 * 1) modprobe i2c-dev
 * 1) modprobe i2c-pxa

The warning about i2c-core.ko is really just saying that it can't load i2c-core for a second time (since it was already loaded when i2c-dev was loaded).

You can automate this step at boot time, by adding the following lines to your /etc/modules file on the gumstix: i2c-dev i2c-pxa
 * 1) I2C

The I2C bus should now be active.

When you do the modprobe of i2c-pxa it will report all devices that are detected on the i2c bus (2.6.11 only). The device at entry 0x20 is an LTC1663 D/A that is used to bias the feedback voltage to the core voltage generator (LTC1878) (i.e. don't mess with it). I haven't yet determined whether the 0x7e entry corresponds to a real device or not.

Connecting to the i2c bus
The i2c bus uses 3 signals, SDA, SCL, and ground, all of which are present on the 60 pin hirose connector. Some daughter cards allow the i2c signals to be accessed.

Note that some versions of the Breakout board have pins labeled incorrectly. See the breakout page for more details.

On the back of the waysmall board, amongst the set of 20 pads, the pad closest to the edge of the board and the power connector is the SDA signal, and the one next to it (also by the edge of the board) is the SCL signal. These are both 3.3v signals and don't have any pullup resistors. The waysmall board has a 3.3v regulator on it, just to the left of the power connector. It has LW33 stamped on it. The pin below the 3 (in LW33) is the 3.3v output (see the JTAG connector page which identifies the Vcc pin on the same type of regulator used on the Tweener).

On the robostix board, pin 12 on the UARTS connector is SDA, and pin 16 is SCL. These are both 5v signals and have pullup resistors.

On the Tweener, pin 19 on the hirose connector is SDA, and pin 20 is SCL. The JTAG connector page has a photo of the hirose connector. The TDO pin shown in the photo is pin 22. The via to the left under the T is pin 21, the one under the O is pin 20, and the one under the D is 19. These are all 3.3v signals and don't have any pullup resistors.

Pullup resistors
The I2C bus requires pullup resistors on the SDA and SCL lines. The I2C specification gives some charts for min and max values (see page 39 and 40). For a 5v or 3.3v bus, the minimum pullup resistance should be around 2k ohms. A typical value to use would be 4.7k ohms.

All of the current daughter cards (except the robostix), need to have pullup resistors added, which pullup the SDA and SCL lines to 3.3v levels.

If you use a robostix, the 3.3v pullup resistors are already included. The SDA and SCL lines on the UARTS connector are at 5v levels, and also have pullup resistors on the robostix board.

Various devices connected to the I2C bus
The I2C Max518 example shows how to connect the Maxim MAX518, which is a dual, i2c, digital to analog converter.

The I2C DS1307 example shows how to connect the DS1307, which is an i2c real time clock and nvram chip.

Program for interacting with I2C devices
The i2c program is a simple program which allows reading and writing individual bytes to and from an i2c device. This is sufficient for controlling a large number of i2c devices. The source code for the i2c program can be found in SVN (login "gumstix", password "gumstix"). A precompiled version for 2.6.15 can be found in i2c-2.6.15.tar.gz and for 2.6.11 here.

There are currently four commands which are supported: ReadByte (which can be shortened to rb), WriteByte (wb), RecvByte (vb), and SendByte (sb). For example, to read register 0x2E from a Cypress CY8C9520 you would use the command: 0x20 The 0x21 is the 7-bit address of it and 0x2e is the location of the data we are reading in the EEPROM memory.
 * 1) i2c 0x21 readbyte 0x2e

To write the value 0xAA to GPIO port 0 (which requires a write to register 8) we would use
 * 1) i2c 0x21 writebyte 0x08 0xAA

The readbyte command can use the --count=N option (where N is a number between 1 and 32). For convenience there are 2 and 4 byte version of the readbyte and writebyte commands. There are readbyte2, readbyte4, writebyte2 and writebyte4, which can be shortened to rb2, rb4, wb2, and wb4 respetively.

An example using readbyte to read the RTC from a DS1307: 0x3006000203030600 (which decodes to Mar 30, 2006 00:06:30)
 * 1) i2c --count=8 0x68 readbyte 0

An example using the multibyte write to write 8 bytes to the EEPROM in the DS1307:
 * 1) i2c 0x68 wb 8 0x123456789abcdef0

Trouble-shooting
Note: When it is working, it should respond nearly instantaneously.

Note: The ReadByte and WriteByte do not support all EEPROM's such as the Microchip 24XX512. However, you can use the SendByte and ReceiveByte commands to do everything the ReadByte and WriteByte commands do.

Error 1
ERROR: I2cTransfer: ioctl failed: Remote I/O error (121) ERROR: I2cWriteBytes failed: -1 If you get this error instantly then you are sending to the wrong address.

If you get the above error after a few seconds with stuff on dmesg then you may need to re-probe the i2c-pxa module
 * 1) modprobe -r i2c-pxa
 * 2) modprobe i2c-pxa
 * Also make sure VCC and GND are plugged in.

Note: if you remove VCC and GND and then plug them in again you may need to re-probe i2c-pxa