3

What are advantages and disadvantages in accessing I2C and other interfaces directly with /dev/mem (as in this code) instead of using /dev/i2c-1 (as in most examples like this)?

6

Disadvantages using /dev/mem for accessing the I²C hardware of the Raspberry Pi directly:

  • It's not portable to other hardware platforms. It's not portable to additional USB I²C adapters. It's not portable to additional bitbanged I²C.
  • You limit yourself to one-application at a time which may use the I²C, while the kernel serializes requests on /dev/i2c-nnn from multiple applications.
  • Likewise, you will run into problems when the user wants to use a kernel driver on the same I²C, for example for the handling of an RTC.
  • You have to take care of I²C bus expanders in your application code.

Advantages:

  • ~--~--~--~ insert tumbleweed ~--~--~--~

In addition, I recommend to use the I2C_RDWR ioctl() instead of read() and write() as you can do multiple transfers in one transaction this way. This is neccessary if multiple applications are accessing the same I²C slave concurrently.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include <linux/i2c-dev.h>

int main(int argc, char* argv[]) {
    struct i2c_msg i2c_msgs[2];
    struct i2c_rdwr_ioctl_data i2c_transfer;
    unsigned int address;
    uint8_t rdata[2];
    int fd;

    /* Parse arguments. */
    if (argc != 3) {
        fprintf(stderr, "USAGE: ds7505-readtemp <i2c-dev> <i2c slave address>\n");
        return 127;
    }   
    sscanf(argv[2], "0x%x", &address);
    if (address < 0x08 || address > 0x77) {
        fprintf(stderr, "ds7505-readtemp: i2c slave address has to be in the range 0x08..0x77.\n");
        return 127;
    }

    /* Open I2C device. */
    fd = open(argv[1], O_RDWR);
    if (fd < 0) {
        perror("ds7505-readtemp: i2c device open");
        return 2;
    }

    /* Select temperature register. */
    i2c_msgs[0].addr   = address;
    i2c_msgs[0].flags  = 0;
    i2c_msgs[0].len    = 1;
    i2c_msgs[0].buf    = "\x00";

    i2c_msgs[1].addr   = address;
    i2c_msgs[1].flags  = I2C_M_RD;
    i2c_msgs[1].len    = 2;
    i2c_msgs[1].buf    = (char*)&rdata;

    i2c_transfer.msgs  = i2c_msgs;
    i2c_transfer.nmsgs = 2;

    if (ioctl(fd, I2C_RDWR, &i2c_transfer) < 0) {
        perror("ds7505-readtemp: i2c temperature read");
        return 2;
    };

    /* Print result. */
    printf("%.4f\n", ((float)((int16_t) (rdata[0] << 8 | rdata[1]))) / 256);

    /* Finish. */
    close(fd);
    return 0;
}
4

In addition to @Janka's answer, more disadvantages:

  • No useful interrupt or DMA processing with /dev/mem
  • Whatever utility has the permission to interact with /dev/mem, can pretty much have complete control over the system. /dev/i2c would allow access only to I2C bus.

Advantage of /dev/mem is that it can be used for very quick proof of concept, or as help for debugging. I'd advise against using it for anything else.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.