Development of I2C Device Driver in Embedded Linux

Source: Internet
Author: User
【Abstract】i2c bus is a common bus with simple and efficient features. It is widely used in various consumer electronic products and audio and video devices, it is also frequently used in the development of embedded systems. This article analyzes the structure of the I2C driver in the embedded Linux system, and describes the general process of developing the I2C device driver in the embedded Linux system based on a specific I2C clock chip ds1307.
[Keyword] I2C bus embedded Linux driver development

1. I2CBus Overview
The I2C (Inter-Integrated Circuit) bus is a two-line serial bus developed by Philips to connect the microcontroller and its peripheral devices. The main advantage of I2C bus is its simplicity and effectiveness.
1.1 I2CHow the bus works
The I2C bus is a serial bus consisting of the SDA data line and the clock SCL. Various controllers are connected in parallel to this bus, and each device has a unique address recognition, it can be used as a sending device or receiver on the bus (determined by the device's function) [1]. The interface circuit structure 1 of I2C bus is shown in.


Figure 1 I2C bus interface circuit [1]
1.2 I2CBus Signal Status[1]
1. Idle status: SDA and SCL are both high.
2. Start condition (s): In high-power mode, SDA changes from high level to low level and starts to transmit data.
3. End condition (P): the SCL is low-frequency, SDA
The data is transferred from low to high.
4. valid data: SDA remains stable and valid during the high-level period of the SCL. SDA changes can only occur at the bottom level of the SCL.
5. Ack signal: During data transmission, each byte of data received by the receiver generates an ACK signal, which sends a specific low-level pulse to the sending device, indicating that the data has been received.
1.3 I2CBasic bus operations
The I2C bus must be controlled by the master device (usually a microcontroller). The master device generates a serial clock (SCL), controls the transmission direction of the bus, and generates Start and Stop conditions.
In data transmission, the primary device generates the initial condition, followed by the control byte of the device (the first seven digits are the address of the device, and the last one is the read/write bit ). The next step is to read and write the data and the ACK response signal. When data transmission ends, the master device generates a stop condition [1]. The specific process 2 is shown.


Figure 2 complete I2C data transmission process [1]
2. LinuxLowerI2CDriver Analysis
2.1 LinuxSystemI2CDriver hierarchy
Linux has good support for I2C devices. The I2C driver in Linux can be logically divided into three parts:
1. I2C Core Driver: Manages I2C bus, I2C adapter, and I2C driver.
2. I2C Adapter Driver for I2C controllers: specific methods for I2C bus access for different types of I2C controllers.
3. I2C driver Driver for I2C devices: provides specific functions for specific I2C devices, including read, write, and IOCTL interfaces for user-layer operations.
The three layers are shown in figure 3 and figure 4.

2.2 I2CBus driverI2C Core
I2C core is the core component of I2C used for maintenance and management in Linux kernel. It maintains two static lists, respectively recording the I2C driver structure and I2C adapter structure in the system. I2C core provides interface functions that allow an I2C adatper, I2C driver, and I2C client to be registered in I2C core during initialization and deregister upon exit. At the same time, it also provides general interfaces for I2C bus read/write access (the specific implementation is implemented in I2C adapter related to I2C Controller) and is mainly used in I2C device drivers.
2.3 I2CController DriverI2C Adapter
I2C adapter is a specific method for accessing the I2C bus at the underlying layer for different types of I2C controller hardware. The I2C adapter constructs a data structure for the I2C core layer interface and registers a controller with the I2C core through the interface function.
The I2C adapter mainly implements the I2C bus access algorithm. The iic_xfer () function is the implementation of the I2C adapter's underlying read/write method on the I2C bus. At the same time, I2C adpter also implements the handler for I2C controller interruption.
2.4 I2CDevice DriverI2C driver
I2C Driver provides a general I2C device driver, which implements the access interface for character devices. The specific access to devices is implemented through I2C adapter. I2C driver constructs a data structure for the I2C core layer interface, and registers an I2C Device Driver with I2C core through the interface function. At the same time, I2C driver constructs a Data Structure for user-layer interfaces, and registers it with the kernel as a character-type device with the main device Number of 89 through interface functions.
I2C driver allows users to access I2C devices, including open, read, write, ioctl, and release. You can use the open function to open I2C device files, the ioctl function is used to set the address for accessing the slave device. Then, the read and write operations on the I2C device can be performed through the Read and Write Functions.
The general method provided by I2C driver can access any I2C device. However, the read, write, ioctl, and other functions are fully implemented based on general devices, all operation data is based on byte streams and has no clear format or meaning. To facilitate and effectively use I2C devices, we can develop specific I2C device drivers for a specific I2C device, complete the interpretation of specific data formats and implement some special functions in the driver.
3.A specificI2CDevelopment of Device Drivers
Ds1307 is a small real-time clock chip with I2C interfaces. It features low power consumption, full BCD code clock and calendar output, 12/24-hour working mode, hour, minute, second, week, year, month, and day time data, auto-compensation for runner-up, valid until January 1, 2100, plus 56 bytes of nv ram (non-volatile RAM) and other features [3]. The following uses ds1307 as an example to describe the design points of a specific I2C device driver.
3.1 I2CGeneral Structure of Device Drivers
A specific I2C Device Driver requires two interfaces. One is an interface for the I2C core layer, which is mounted to the I2C adapter layer to implement access to the I2C bus and I2C devices, including the implementation of attach_adapter, detach_client, command and other interface functions. The other is the interface at the user application layer, which provides interfaces for user programs to access I2C devices, including interfaces for implementing open, release, read, write, and most important IOCTL and other standard file operations.
The interface functions of I2C core layer are described as follows:
Attach_adapter: When the I2C driver calls i2c_add_driver () for registration, it calls this function for every I2C adapter (corresponding to an I2C bus) found, check whether the I2C adapter meets the specified I2C driver conditions. If yes, connect the I2C adapter and use the I2C adapter to access the I2C bus and I2C devices.
Detach_client: the I2C driver calls this function when deleting an I2C device and clears the data structure describing this I2C device. In this way, the device cannot be accessed later.
Command: implements a series of sub-functions based on the features of the device. It is the underlying implementation of the ioctl function in the user interface.
3.2 ds1307Driver implementationI2CCoreLayer interface
A struct i2c_driver data structure must be implemented in the driver, and an I2C driver must be registered with I2C core during driver module initialization, and related operations on I2C adapter must be completed.
Struct i2c_driver ds1307_driver =
{
Name: "ds1307 ",
ID: i2c_driverid_ds1307,
Flags: i2c_df_notify,
Attach_adapter: ds1307_probe,
Detach_client: ds1307_detach,
Command: ds1307_command
};
Name: "ds1307", ID: i2c_driverid_ds1307 in ds1307_driver is used to identify the ds1307 driver. Flags: i2c_df_notify indicates that the driver is notified when the I2C bus changes.
Ds1307_probe corresponds to the attach_adapter in the i2c_driver data structure. The main function is to call the i2c_probe function provided by the I2C core layer to find an I2C bus and check whether a ds1307 device exists. If ds1307 exists, then, the corresponding I2C adapter and ds1307 device are mounted together, And the I2C adapter is used to access ds1307. Ds1307 is enabled at the same time, and the i2c_attach_client () is called to register ds1307 with the I2C core layer.
Ds1307_detach corresponds to the detach_client in the i2c_driver data structure. The main function is to call i2c_detach_client () to log out ds1307 from the I2C core layer and disable ds1307. In this way, the I2C driver cannot access ds1307.
Ds1307_command corresponds to the command in the i2c_driver data structure. The main function is to implement a series of sub-functions, such as ds1307_gettime, ds1307_settime, ds1307_getdatetime, expires, and ds1307_mem_write, based on the characteristics, is the underlying implementation of the ioctl function in the user interface.
The above three interface functions enable the ds1307 driver to connect the I2C bus and I2C adpater. Therefore, the I2C core can provide a general interface for reading and writing the I2C bus, to develop and implement ds1037 driver interface functions for the user application layer.
3.3 ds1307The driver implements the interface to the user application layer.
The driver must implement a struct file_operations data structure and register it with the kernel as a character-type device (identified by a separate master device number ), or register as a miscdevice device (all miscdevice devices share the same master device number, different sub-device numbers, and all miscdevice devices form a linked list, when accessing a device, find the corresponding miscdevice device based on the next device number, and then call the application layer interface registered in its struct file_operations for operations ).
Struct file_operations rtc_fops =
{
Owner: this_module,
IOCTL: ds1307_rtc_ioctl,
Read: ds1307_rtc_read,
Write: ds1307_rtc_read,
Open: ds1307_rtc_open,
Release: ds1307_rtc_release
};
In the data structure rtc_fops, ds1307_rtc_open and ds1307_rtc_release correspond to open and release in file_operations, which are used to open and close ds1307 respectively.
Ds1307_rtc_ioctl corresponds to IOCTL in file_operations. The specific command for a user to control the clock chip: rtc_get_time: reads the real-time clock time in a fixed data format. Rtc_set_time: Set the real-time clock time in a fixed data format. Rtc_sync_time: time synchronization between the system clock and the real-time clock.
Ds1307_rtc_read corresponds to the read in file_operations, implements the same function as the sub-function rtc_get_time of ds1307_rtc_ioctl, and reads data from NV Ram.
Ds1307_rtc_write corresponds to the write in file_operations, implements the same function as the sub-function rtc_set_time of ds1307_rtc_ioctl, and writes data to NV Ram.
3.4 ds1307Driver loading and Testing
In the ds1307 driver initialization function ds1307_init (), first register an I2C device driver with the I2C core layer through i2c_add_driver (& ds1307_driver), and then use misc_register (& ds1307_rtc_miscdev) register ds1307 as a miscdevice device, so that the user program can access ds1307 through the device node/dev/RTC of the master device number 135 10 times.
Compile the ds1307 driver into a module, load it into the kernel using the insmod command, and test the code. All the functions implemented in the ds1307 driver have achieved the expected results.
Because the ds1307 driver implements interpretation and conversion of ds1307 clock chip data at the underlying layer, what is obtained in the user program is data with a fixed format and meaning, this facilitates the access of user programs and improves the efficiency of application development.
4. Summary
I2C bus is a small-sized bus with simple protocols. It is widely used and easy to access. In Linux, I2C drivers have a clear hierarchy and can easily develop drivers for a specific I2C device. This article analyzes the I2C driver in Linux and the driver structure of a ds1307 clock chip, which shows the development process of an I2C device driver. The key to implementation is divided into two parts: 1. Several specific function functions in the struct i2c_drvier data structure must be implemented for the I2C core interface. These functions are the basis for communication between I2C drivers and I2C bus physical layer (I2C Controller) and I2C device devices. 2. for user application layer interfaces, you must implement some specific functions in the struct file_operation data structure, such as open, release, read, write, and lseek functions. Among the above two types of interfaces, the interface for I2C core is the basis for access to I2C devices, to achieve specific access to the I2C bus; the interface for the user's application layer is convenient for application development, an essential part of implementing specific device functions.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.