Development and implementation of I2C device driver under Linux

Publisher:王大雷Latest update time:2012-03-26 Source: 计算机与信息技术 Keywords:I2C Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
1 Introduction
The I2C (Inter-Integrated Circuit) bus is a two-wire serial bus developed by PHILIPS for connecting microcontrollers and their peripherals. The main advantages of the I2C bus are its simplicity and effectiveness. Since the interface is directly on the component, the I2C bus occupies very little space, reducing the space on the circuit board and the number of chip pins, and reducing the cost of interconnection. The I2C bus was originally developed for audio and video equipment, and is now used in various service and management occasions to configure or master the functional status of components, such as power supply, system fan, system temperature and other parameters, increasing system security and facilitating management.
2 I2C Bus Overview
The I2C bus is a serial bus consisting of a data line SDA and a clock SCL. It can send and receive data, and each device has a unique address identification. The I2C protocol uses master/slave bidirectional communication. A device that sends data to the bus is defined as a transmitter, and a device that receives data is defined as a receiver. Both the master device and the slave device can work in the receiving and sending states. The bus must be controlled by a master device (usually a microcontroller). The master device generates a serial clock (SCL) to control the transmission direction of the bus and generate start and stop conditions. The data state on the SDA line can only change when SCL is low. During the period when SCL is high, the change of the SDA state is used to indicate the start and stop conditions.
There are three types of signals in the I2C bus during data transmission, namely: start signal, end signal and response signal.
Start signal: When SCL is at a high level, SDA jumps from a high level to a low level to start data transmission.
End signal: When SCL is at a low level, SDA jumps from a low level to a high level to end data transmission.
Response signal: After receiving 8-bit data, the IC receiving data sends a specific low-level pulse to the IC sending data, indicating that the data has been received. After the CPU sends a signal to the controlled unit, it waits for the controlled unit to send a response signal. After receiving the response signal, the CPU determines whether to continue transmitting the signal based on the actual situation. If no response signal is received, it is determined that the controlled unit has a fault.
3 I2C driver framework for Linux
The I2C bus driver in Linux is divided into two parts, bus driver (BUS) and device driver (DEVICE). The bus driver's responsibility is to add corresponding read and write methods for each I2C bus in the system. However, the bus driver itself does not perform any communication, it just exists there, waiting for the device driver to call its function, see Figure 1.
The device driver is a driver that communicates with specific devices on the I2C bus. Through the functions provided by the I2C bus driver, the device driver can ignore the differences between different bus controllers and communicate with hardware devices without considering their implementation details.
Figure 1 Linux kernel I2C bus driver architecture
There are three folders, algos, busses, and chips, under the i2c folder of our Linux driver, and two files, i2c-core.c and i2c-dev.c. The i2c-core.c file implements the I2C core framework, which is the core part of I2C used by the Linux kernel to maintain and manage. It maintains two static lists, which record the I2C driver structure and I2C adapter structure in the system respectively. The I2C core provides interface functions, allowing an I2C adatper, I2C driver, and I2C client to register in the I2C core during initialization, and to unregister when exiting. It also provides a general interface for I2C bus read and write access, which is mainly used in I2C device drivers.
The i2c-mpc.c file in the Busses folder implements the I2C bus adapter driver under PowerPC, defines the i2c_adapter data structure of the specific I2C bus adapter, and implements the specific method of accessing the I2C bus at a relatively low level. The I2C adapter constructs a data structure for the I2C core layer interface, and registers a controller to the I2C core through the interface function. The I2C adapter mainly implements the algorithm for accessing the I2C bus. The iic_xfer() function is the implementation of the I2C adapter's low-level read and write methods for the I2C bus. At the same time, the I2C adapter also implements the processing function for the I2C controller interrupt.
The i2c-dev.c file implements the I2C driver, provides a general I2C device driver, implements the access interface of character type devices, implements the interface to the user application layer, and provides the user program with an interface to access the I2C device, including the interface functions for implementing standard file operations such as open, release, read, write, and the most important ioctl. We can open the I2C device file through the open function, set the address of the slave device to be accessed through the ioctl function, and then complete the read and write operations on the I2C device through the read and write functions.
The general method provided by the I2C driver can access any I2C device, but the read, write and ioctl functions implemented are completely based on the implementation of general devices. All operation data are based on byte streams and have no clear format and meaning. In order to use I2C devices more conveniently and effectively, we can develop a specific I2C device driver for a specific I2C device, complete the interpretation of the specific data format and implement some special functions in the driver. [page]
4 I2C specific driver development under Linux
TMP75 is a digital temperature sensor based on I2C bus launched by TI. It has low power consumption and high digital resolution. It is widely used in power supply temperature monitoring, computer peripheral protection, notebooks and cellular phones. In developing the driver for this device, since the I2C core framework and I2C bus adapter driver have been implemented in the Linux system, and a general I2C device driver is provided through the i2c-dev.c file, our driver development is mainly focused on the TMP75 device driver layer, which is used to interpret the data format of the TMP75 device and implement some special functions.
According to the specific register address and function definition of TMP75:
#define TMP75_REG_TEMP 0x00 //Temperature register address
#define TMP75_REG_CONF 0x01 //Configuration register address
#define TMP75_REG_TEMP_LOW 0x02 // Low temperature threshold register address
#define TMP75_REG_TEMP_HIGH 0x03 //High temperature threshold register address
Define a TMP75_data structure and a series of functions to implement device detection and loading during bus initialization and data operations during device deletion.
struct TMP75_data {
struct i2c_client client;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
u16 temp_input; /* Register values ​​*/
u16 temp_max;
u16 temp_hyst;
};
static int TMP 75_attach_adapter(struct i2c_adapter *adapter);
static int TMP 75_detect(struct i2c_adapter *adapter, int address, int kind);
static void TMP 75_init_client(struct i2c_client *client);
static int TMP 75_detach_client(struct i2c_client *client);
static int TMP 75_read_value(struct i2c_client *client, u8 reg);
static int TMP 75_write_value(struct i2c_client *client, u8 reg, u16 value);
static struct TMP 75_data *tmp75_update_device(struct device *dev);
The two functions that define TMP75 register reading and writing for the specific format of TMP75 device registers are as follows:
static int TMP75_write_value(struct i2c_client *client, u8 reg, u16 value)
{
if (reg == TMP75_REG_CONF)
return i2c_smbus_write_byte_data(client, reg, value);
else
return i2c_smbus_write_word_data(client, reg, swab16(value));
}
static int TMP75_read_value(struct i2c_client *client, u8 reg)
{
if (reg == TMP 75_REG_CONF)
return i2c_smbus_read_byte_data(client, reg);
else
return swab16(i2c_smbus_read_word_data(client, reg));
}
After the specific device driver is completed, add the configuration options of the TMP75 device driver to the kconfig file in the chips folder, so that the TMP75 device driver can be added to the kernel when configuring the kernel options.
5 I2C application development under Linux
In Linux, if an application wants to use this driver to access an external I2C device, it must first open the driver using open() and then close it using close().
int fd;
fd = open("/dev/i2c/0", O_RDWR);
close(fd);
The API function provided by the I2C bus controller driver provides the ioctl() function for setting some parameters of the I2C bus controller. This application calls the ioctl function to set the I2C bus to 7-bit address mode and set the I2C slave address.
ioctl(fd, I2C_TENBIT, 0)
ioctl(fd,I2C_SLAVE,SLAVE_ADDR)
The initialization of TMP75 is achieved by calling the write() function, which is used to initialize the configuration register, high temperature threshold and low temperature threshold register.
// Initialize the configuration registers
senbuf[0]=0x01;
senbuf[1]=I2C_CONF_INITDATA;
write(fd, sendbuf, 2);
The current operating temperature of TMP75 is read by calling the write() function to first write the address of the temperature register, and then calling the read() function to read the 2-byte temperature data of the register.
write(fd, 0x0, 1);
read(fd, recbuf, 2);
6 Conclusion
The I2C bus structure is simple and easy to use. The I2C driver under the Linux system has a clear hierarchical structure. With the help of mature driver examples, users can easily develop corresponding drivers for their own products. This article analyzes the I2C driver structure under the Linux system, and implements a specific I2C device driver on this basis, and on this basis gives a user application implementation for accessing the I2C bus.
References
[1]Philips Corporation, I2C bus specification version 2.1, 2000
[2] Aless and Robin, translated by Wei Yongming et al., LINUX Device Drivers (Second Edition). Beijing: China Electric Power Press, 2004
[3]Texas Instruments, inc. USA. TMP75 Datasheet, 2004
[4] Zheng Xuyang, Li Bingbing, Huang Xinping. Research and software design of multi-master communication based on simulated I2C bus. Microcontroller and Embedded System Application, 2005
Keywords:I2C Reference address:Development and implementation of I2C device driver under Linux

Previous article:Design of SMS sending and receiving system based on embedded Linux
Next article:Serial RapidIO: High-Performance Embedded Interconnect Technology

Recommended ReadingLatest update time:2024-11-16 19:49

About I2C hardware DMA implementation of STM32
I have seen many people saying that STM32's I2C is difficult to use online, but I think it is still a problem of understanding. STM32's I2C is indeed very complicated, but as long as the foundation is solid, it is not as difficult as imagined. So let's start with the basics, only talk about the key points, and don't
[Microcontroller]
Linux UART serial port driver development documentation
1. Serial port interface and layer of Linux. Serial port is a widely used device, so the support under Linux is very complete, with a unified programming interface. The complete work of driver developers is to complete the corresponding configuration macros for different serial port ICs. These configuration macr
[Microcontroller]
Construction of embedded Linux development platform based on ARM
With the rapid development of computer technology, communication technology and the integration of 3C (computer, communication, consumer electronics), embedded systems have penetrated into various fields. In the 32-bit embedded microprocessor market, microprocessors based on the ARM (Advanced RISC Machine) core are
[Industrial Control]
Construction of embedded Linux development platform based on ARM
S3C2440 bare metal -------I2C_S3C2440 I2C controller control timing
1. Register The I2C of S3C2440 is mainly controlled by the following four registers.  2. Data transmission process  
[Microcontroller]
S3C2440 bare metal -------I2C_S3C2440 I2C controller control timing
51 MCU - I2C bus driver
To facilitate transplantation, a multi-file project approach is adopted. void Delay10us()//Delay 10us { unsigned char a,b; for(b=1;b 0;b--) for(a=2;a 0;a--);   } Start signal: When the SCL clock signal is at a high level, the SDA signal generates a falling edge. void I2cStart() //To facilitate the connection wi
[Microcontroller]
The whole process of porting SD/MMC to S3C2440 under linux-2.6.24.3
1. First download the 2.6.24.3 kernel source code. Other kernels are not guaranteed to work. I won't talk about the porting part. If you don't know how to do it, please refer to my other articles. I only tested this one. 2. Go to http://svnweb.openmoko.org/*check ... _mci.patch?rev=4096 to download the S
[Microcontroller]
OK6410A Development Board (VIII) 29 linux-5.11 OK6410A Main Kernel Thread Analysis
This blog post by kthreadd briefly describes all kernel threads created in the system. // The parent process of process 1 2 is 0 // All other kernel threads (included by ) have the same parent process as kthreadd Process ID User Status COMMAND Process name Process creation file Process creation function // User p
[Microcontroller]
Realization of CAN bus communication based on ARM9 under Linux environment
1. Introduction The CAN (Controller Area Network) bus was first proposed by the German company BOSCH to realize microcontroller communication in the automotive environment, exchange information between various electronic control units ECU on the vehicle, and form an automotive electronic control network. Due to its l
[Microcontroller]
Realization of CAN bus communication based on ARM9 under Linux environment
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号