I2C and the Raspberry Pi

Well I2C was the obvious next candidate for a driver. Another active Raspberry Pi coder, Frank Buss, wrote some nice driver code but sadly didn’t integrate it with Linux’s own i2c driver framework. It worked, though not as I wanted it. He did the hard work. I then took his code (with his permission of course) and wrote a Linux i2c driver for it today. It works! You can grab it at:

https://github.com/bootc/linux/tree/rpi-i2cspi

This tree contains the latest SPI and I2C code. Here’s how to use it:

  1. Build a kernel from my tree with CONFIG_I2C_BCM2708=m.
  2. Boot your new kernel. The module should automatically load.
  3. Bind some I2C devices to the bus (see below).

When your kernel boots, you should see something like this in dmesg:

[   61.322300] i2c i2c-0: adapter [bcm2708_i2c.0] registered
[   61.329530] bcm2708_i2c bcm2708_i2c.0: BSC0 Controller at 0x20205000 (irq 79)
[   61.341100] i2c i2c-1: adapter [bcm2708_i2c.1] registered
[   61.347581] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79)

At this point you can modprobe i2c-dev to play with /dev/i2c-0 from userspace (look for i2cdetect in i2c-tools for example), or use some kernel drivers.

I have a TI TMP102 attached to my Raspberry Pi, so I used it like this:

raspberrypi bootc # echo tmp102 0x48 > /sys/class/i2c-adapter/i2c-0/new_device
raspberrypi bootc # sensors
tmp102-i2c-0-48
Adapter: bcm2708_i2c.0
temp1:        +21.6°C  (high = +160.0°C, hyst = +150.0°C)

And again with a Maxim DS1307 RTC:

raspberrypi bootc # echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device
raspberrypi bootc # hwclock -r
Sat 19 May 2012 23:15:24 BST  -0.525475 seconds

You may have noticed the driver registers two I2C busses. One is the the BSC0 bus that has pins on the GPIO connector, the other is BSC1 which has pins on the camera connector.

Enjoy!

45 thoughts on “I2C and the Raspberry Pi

  1. I’ve compiled your kernel, but it says “mmc0: problem reading SD Status register” and “error -110 whilst initialising SD card” when booting. When I copy the old kernel on the SD card FAT partition and it is working again, so looks like the SD card is ok. My working kernel was forked from https://github.com/raspberrypi/linux , looks like you forked a different version. How is the kernel development concept for the Raspberry Pi? I guess your modifications will be merged in the mainline kernel someday, and then it could be pulled to the Raspberry Pi kernel again, but maybe would be better to test it first all in the Raspberry Pi image, which looks like it is the “official” Raspberry Pi kernel at the moment. But maybe I’m all wrong, I’m new to Git.

    • Frank, there have evidently been some changes to the MMC code in 3.2 that cause breakage for certain SD cards when used on the Raspberry Pi. My code is a straight forward-port to 3.2 plus the addition of my I2C and SPI patches. Other people have indeed been having exactly the same trouble with SD cards, but it goes away when trying a different card.

      I’d try to chase down what change made SD cards less reliable, but we’re going to have to rewrite the eMMC driver before it can go into mainline anyway so it seems there is little point. You should be able to backport my drivers into the official 3.1.9 based kernel without much effort though!

      HTH, Chris

    • I’ve just posted an updated kernel with all the latest patches from Dom’s tree added on. You might want to give that a go too to see if it helps! – Chris

  2. Thank you both for your work on this, I’ve got it working with an MCP23017 I/O expander now having first tried Frank’s bitbanging version on Saturday.

    I too ran into the SD problems with the card I was originally using but switched card and all working fine now.

    Thanks,
    Nathan

  3. Chris, your rpi-3.2.17 branch had the same problem with my SD card. I don’t know the reason, but if I use the first version (9ffcbeda1f8125de65d8325b6afa7d75439d7db9) of drivers/mmc/host/sdhci-bcm2708.c, then it works without problems. The next version, 84045e4d40677ec9322357bdb0fbeaa16c6d25fa, has the problem. I think the comment is a bit misleading, the patch does more, but I don’t have the time to analyze it at the moment, maybe you have an idea. My SD card is an Intenso SDHC 4 GB card. If parts of the same code are used for a rewrite, the problem would persist. But with the first version of the SD card driver, the I2C driver works, thanks! I’ve measured a very clean 100 kHz clock.

    • Just so I get this straight, if you revert 84045e4 your SD card works fine? How odd; that was added to fix problems for people… :-/

  4. Right, version 9ffcbeda1f8125de65d8325b6afa7d75439d7db9 works. But I had a file system error some time after testing it (some kernel inode messages and broken files), I guess it is not the best SD card.

  5. Pingback: RaspberryPi birdfeeder webcam « Random Hacks

  6. Although I am a long time Linux user, building kernels is a new experience for me. I have a couple of RPI’s and need I2C to work so I am watching these posts with interest. I have downloaded the whole source of you tree from https://github.com/bootc/linux.

    My first question is what do I build it on? I have virtualbox so expect I need a Debian system set-up to cross compile.

    My second question is how do I load the new kernel onto an SD card to boot on the RPI? Do I just copy it over and patch the boot loader to use it?

    I have lots of I2C devices to hand and an analyser so I can test the drivers quite thoroughly.

    Keep up the good work!

    • You should be able to use any Linux (possibly also Mac OS X) system to build your kernels on – just follow my cross-compiler building guide to get a working cross-compiler you can use. A VirtualBox VM should work fine too.

      Once you’ve built a kernel, make sure you have the latest firmware files on your SD card, then just copy arch/arm/boot/zImage to kernel.img on your SD card and boot.

  7. I have successfully installed your i2c driver. modeprobed i2c-dev . I can see /dev/i2c-0 and -1. But if if try to
    echo ds3232 0xd0 > /sys/class/i2c-adapter/i2c-0/new_device i get the message that it’s write protected. I’ve logged in with root.
    Did chmod 777 new_device. Same result.
    What’s wrong ?
    Thanks,
    Stefan

    • Have you checked dmesg or /var/log/kern.log to see if there are any useful log messages coming from the kernel? It sounds suspicious to me that the devices and control files exist but you’re getting permission errors.

  8. I have my i2c driver up and running. I have a rtc1307 connected.
    How can I make the loading of the rtc driver/module permanent?
    I created an entry rtc-ds1307 in /etc/modules, but I have to
    echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device
    manually. Only after the echo, I can read the clock with hwclock -r

    Stefan

  9. Pingback: GPIO Port on the Raspberry Pi | Chris's Tech Journal

  10. I would also like to know how to create patch from your fork and apply it to official tree

  11. Hi

    Great work! Exactly what I was looking for.
    Since I see no chance to successfully compile my own kernel, would it be possible to put a ready kernel image file somewhere, based on the official 04/12 release, which could simply be copied to the SD Card?
    Would save an incredible amount of time for interested users and prevents from uncounted unsuccesful tries 🙂

  12. Any chance you can build a version of your patched kernel expecting a ds1307 RTC at 0x68 so time gets set on boot? I have a ChronoDot attached to the I2C bus but have to run `hwclock -s` on boot to pull the time.

    • Sorry, this is something specific to your setup so really needs to be something you would do in a custom kernel of your own.

  13. Hi, I have successfully installed DS1307 RTC (DS1307 module is included in the kernel). RTC works fine.

    However, after reboot the RTC is not detected. I have to issue command
    echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device

    How can I configure Pi to detect and read DS1307 RTC at boot time?

    Thanks, Igor

    • The best way to do this is to edit the architecture setup code to wire up the ds1307 to the I2C buses with platform init data. This would mean compiling your own kernel.

      • Thanks Chris,

        I’m already using my own kernel. The DS1307 module is included in the kernel, as well “Set system time from RTC on startup and resume”.

        Can you please be more specific? What exactly needs to be modified/added?

        Actually I don’t understand the point in having a RTC which needs manual intervention after each boot.

  14. I have successfully installed your i2c driver,based on the “wheezy-mini-2012-06-23.img.gz”.
    I modeprobed i2c-dev and modeprobed rtc-ds1307. But if try to
    “echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device” ,i get the this message
    “rtc-ds1307: probe of 0-0068 failed with error -5”,What’s wrong ?Thanks

    this is my logs:

    root@raspberrypi:~# modprobe i2c-dev
    [ 51.014642] i2c /dev entries driver
    root@raspberrypi:~# modprobe rtc-ds1307
    root@raspberrypi:~# echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device
    [ 125.531307] rtc-ds1307: probe of 0-0068 failed with error -5
    [ 125.537185] i2c i2c-0: new_device: Instantiated device ds1307 at 0x68
    root@raspberrypi:~# hwclock -r
    hwclock: Cannot access the Hardware Clock via any known method.
    hwclock: Use the –debug option to see the details of our search for an access method.

    • Have a look in your kernel logs, that may tell you more about what is going on. Look in /var/log/kern.log to start with. I personally suspect a wiring fault as -5 is EIO (Input/output error).

    • Other unsuccessful logs:

      root@raspberrypi:~# modprobe i2c-dev
      root@raspberrypi:~# echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device
      root@raspberrypi:~# hwclock -r
      hwclock: Cannot access the Hardware Clock via any known method.
      hwclock: Use the –debug option to see the details of our search for an access method.
      root@raspberrypi:~# hwclock -r –debug
      hwclock from util-linux 2.20.1
      hwclock: Open of /dev/rtc failed: No such file or directory
      No usable clock interface found.
      hwclock: Cannot access the Hardware Clock via any known method.

  15. hi all
    can anybody put here the compiled wheezy kernel.img? thx for the support

  16. Hi,

    I’m using your i2c driver very successfully with several different chips. But I have a MAX-6Q GPS chip from u-blox, which can communicate also on i2c interface.
    But If I’m accessing this chip, to get it’s GPS Information (ASCII NEMA protocol), I get crippled NEMA protocol sentences. It looks like that the i2c driver looses several ASCII characters, or the chip can’t keep up with the bus speed. I’ve contacted u-blox support and they mentioned, that the chip needs clock stretching. How can I use this feature, is it implemented in yor i2c driver, or is there a driver parameter to enable it?
    Thanx,
    Stefan

    • Sorry, the Raspberry Pi I2C hardware doesn’t support clock stretching at all, so it can’t work with your GPS module. 🙁

      • is it possible to lower the bus speed?
        the chip delivers already ascii nema information. but it’s crippled. with lower bus speed, i believe the chip will work.

        stefan

        • Yes, but you would need to rebuild the kernel to do this. Just change I2C_CLOCK_HZ towards the top of drivers/i2c/busses/i2c-bcm2708.c to the value you desire.

          • Hi Chris,
            is it possible to implement clock stretching into the driver or is it a hw functionality, which the raspberry hw has to supply.

            If on yl the sw driver is able to reduce the speed, it would be nice to have a parameter, instead of building a new kernel.

            Stefan

  17. Pingback: Adafruit introduces customized Debian distro for Raspberry Pi » Foomatic Blogs

  18. Pingback: Adafruit introduces customized Debian distro for Raspberry Pi (review) – #piday #raspberrypi @Raspberry_Pi « adafruit industries blog

  19. I am a highly competent high-level programmer but know nothing of Linux. I am getting frustrated by the uber-nerd cryptic comments on all the Pi sites which seem to assume everyone knows Linux inside out. I genuinely fear this is going to damage the Pi’s success – it is after all supposed to repeat the BBC’s success in getting new users, especially kids, into programming.

    Look, I want to run a quiz system using the Pi. I can write beautiful Python code to implement it and I have SK Pang’s nice Pi case with attached breadboard etc. But getting it to work with the supplied MCP23017 is proving a nightmare. I followed the instructions line-by-line to download and install Nathan’s driver and it doesn’t work. The instructions here are not that clear and I don’t understand the Linux for what is needed. So I got my son-in-law, who is a professional IT team leader at a major British university, to do it for me. That didn’t work either, Linux says it can’t find the file.

    Furthermore I cannot easily transfer from PC downloads because my powered USB hub won’t work with the Pi, another insane design fault because, for God’s sake, even Windows can work with USB nine times out of ten! So I can’t use a plug-in drive AND keyboard AND mouse at the same time.

    PLEASE could someone just provide a nice, clear set of instructions for downloading a driver, installing it and getting it to talk to the outside world. Improperly-documented software is bad software, even if it ticks lots of ‘I’m clever’ boxes within a fraternity.

    I wait in hope
    Chris

  20. Could you show some electronic scheme describing how you connected DS1307 to raspberry?

Comments are closed.