0

I see codes to make i2c device (e.g. i2c sensors) work in user space, just need kernel to support /dev/i2c-0 or /dev/i2c-1. But whether do we need to put the codes into Linux kernel? For example, if i2c interrupt is applied, how to know when should we read the i2c device in user space?

I am confusing. Like display driver, it is totally put into kernel space. Then for i2c driver, why some part is in kernel (i2c bus code) while some part is in user space? Which part is the real driver?

More: Give an example below. I find that Linux kernel contains driver for sht21, it is here below:

linux-rpi-3.18.y/drivers/hwmon$ ls -al sht21.c 
-rw-rw-r-- 1 tomxue tomxue 6454 Jan  2 00:07 sht21.c

In fact, we could find a lot of drivers in kernel source code.

And also I find that someone makes user space driver for sht21, like this: http://www.emsystech.de/raspi-sht21/ I tried the code, and it works in user space.

My question is that which one is better? To put the driver into kernel or just call the GPIO/i2c bus API to communicate with the sensor in user space?

Thanks!

2 Answers 2

2

The i2c driver code is entirely in kernelspace; linux does not use userspace drivers except to the extent that they are built on top of some kernel one1 -- for example, you can write userspace drivers for i2c devices by using the smbus API.

The functions in that API are system calls; they invoke kernel code (presumably, from the i2c driver, although there may be more to it).

Similarly, the plain GPIO driver is in kernelspace, but it exposes a userland interface in /sys/class/gpio also documented in the kernel source tree.

However, in both cases you could write your own kernel module and create a pure kernelspace driver to accomplish much the same thing. This may be necessary if you need to do something that the existing API's don't allow for (e.g., remapping pins or manipulating the pi's resistors).

In short, there are three broad approaches to writing i2c oriented drivers on the pi:

  1. Using the smbus API.
  2. Using the kernel API, i.e., writing a kernel module.
  3. Using an architecture specific library such as those mentioned in the footnote. I believe these all have bindings to higher level languages such as python.

The second one is probably the most labour intensive. The first one is the most portable, meaning you can use it to write things that will work on other linux based devices (but this should be possible using the second method as well). However, the smbus API has some limitations, as mentioned; I needed to use the bcm2835 lib in order to enable the second i2c bus on a model B. So, if you needed portability and such features, your best option would be the labour intensive second choice -- personally, I would only opt for that if I had to, but on the other hand, it also gives you the opportunity to learn more about what goes on inside the kernel.


1. A exception to this would be, e.g., pi-specific stuff that mmap()s kernelspace in order to directly manipulate hardware. WiringPi, pigpio, and the bcm2835 library do this, allowing you to write a more or less pure userspace driver.

1

I2C is a bus. There may be many devices connected to the bus. The Linux kernel driver controls access to the bus ensuring that only one device is talking at any one time.

For higher bus speeds the timing becomes very tight (say at 400 kbps and more). There is no way a user land driver could guarantee to meet the tight timings needed. So the Linux kernel driver handles the bit timings.

Also the Linux kernel driver provides the standard I2C/SMBus byte interface.

From userland you just send/receive byte streams to/from I2C devices, i.e. I2C looks like every other *nix byte stream orientated device.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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