Accessing I2C Devices in Linux Print


The Linux kernel provides a device driver for the I2C controller of the STM32F4, enabled in the kernel with the CONFIG_I2C_STM32 build-time option. To enable the driver in the kernel configuration, run make kmenuconfig in your project directory, go to Device Drivers and enable I2C support. Then go to I2C Hardware Bus support and enable STM32 I2C support:

Another kernel configuration option that you will require is CONFIG_I2C_CHARDEV. This option enables the kernel API that allows accessing I2C devices from user-space application code. To enable CONFIG_I2C_CHARDEV, proceed to Device Drivers, then go to I2C support and in there enable I2C device interface:

Having enabled CONFIG_I2C_STM32, go to System Type ->STM32 I/O interfaces and enable the specific I2C interfaces you require in your application:

Do not enable any I2C interfaces except for those that you plan to use in your application. For one thing, unless an I2C interface is actually required, you want to keep it in reset in order to save some power. Another consideration is that I2C signals may conflict with other I/O interfaces on the STM32F4 pins. More on that right below.

Allocation of the STM32F4 pins to specific I/O interfaces is defined in linux/arch/arm/mach-stm32/iomux.c. When you have enabled I2C interfaces that you require in your application, make sure that there is appropriate code in iomux.c that routes the I2C signals to those STM32F4 pins that you have allocated for I2C in your application. For example, for I2C1 there is the following code defined in iomux.c:

#if defined(CONFIG_STM32_I2C1)
if (platform == PLATFORM_STM32_STM_STM32F439_SOM ||
platform == PLATFORM_STM32_STM_STM32F7_SOM) {
gpio_dsc.port = 1; /* SCL */
gpio_dsc.pin = 8;
}
else {
gpio_dsc.port = 1; /* SCL */
gpio_dsc.pin = 9;
}
stm32f2_gpio_config(&gpio_dsc, STM32F2_GPIO_ROLE_I2C1);

if (platform == PLATFORM_STM32_STM_STM32F439_SOM ||
platform == PLATFORM_STM32_STM_STM32F7_SOM) {
gpio_dsc.port = 1; /* SDA */
gpio_dsc.pin = 7;
}
else {
gpio_dsc.port = 1; /* SDA */
gpio_dsc.pin = 8;
}
stm32f2_gpio_config(&gpio_dsc, STM32F2_GPIO_ROLE_I2C1);
#endif

There must be a device node in the target root file system for each I2C interface you enable to allow accessing it using standard Linux interfaces. Add the following lines into your <project>.initramfs file to create device nodes for all 3 I2C interfaces:

nod /dev/i2c-0 0666 0 0 c 89 0
nod /dev/i2c-1 0666 0 0 c 89 1
nod /dev/i2c-2 0666 0 0 c 89 2

The Emcraft uClinux distribution includes the Linux tools that can be used to access I2C devices from user space. Add the following lines to your <project>.initramfs file in order to add these tools to the target file system:

file /usr/sbin/i2cdetect ${INSTALL_ROOT}/A2F/root/usr/sbin/i2cdetect   755 0 0
file /usr/sbin/i2cdump ${INSTALL_ROOT}/A2F/root/usr/sbin/i2cdump   755 0 0
file /usr/sbin/i2cget ${INSTALL_ROOT}/A2F/root/usr/sbin/i2cget     755 0 0
file /usr/sbin/i2cset ${INSTALL_ROOT}/A2F/root/usr/sbin/i2cset     755 0 0

Having updated your project configuration as described above, build the bootable Linux image (<project>.uImage) by running make in the project directory.

When you load the uImage to the target, the kernel will register a platform device for the I2C0 controller. You should see the following line in the kernel boot messages on the target:

i2c_stm32 i2c_stm32.0: I2C Controller i2c-0 at 40005400,irq=31

Run the Linux I2C tools to examine I2C devices on your target. For instance, the following command scans the I2C0 interface and reports any devices it detects on the bus:

~ # i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- 1a -- -- 1d -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: 50 51 52 53 54 55 56 57 -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- ~ #

Refer to documentation available from the Internet for detailed manuals on the Linux I2C tools, for instance:
http://www.lm-sensors.org/wiki/i2cToolsDocumentation