- The city I miss is dusk
- Why do I always passionately devoted to you
- Once gave me happiness also gave me trauma
- Once gave me hope and gave me despair
- I'm in a strange crowd in a faraway city
- Feel your Distant sorrow
- My fantasies.
Your sorrow, like my despair, so long,,,, this is today's melody, straight into the bottom of my heart ~~~~~~~~~~~~~~~~
In the Linux system, the I²c drive consists of 3 parts, namely, the I²c core, the I²c bus drive and the I²C device driver, the I²C bus uses only SCL, SDA these two signal lines to realize the data interaction between the devices, greatly simplifies the use of hardware resources and PCB board cabling space
1 Linux's I²c architecture
1.1 Components
1) I²c Core
I²c Core provides i²c bus driver and device driver registration, logoff method, I²c communication method, etc.
2) I²c bus driver
The I²C bus driver mainly contains the I²C adapter data structure I2c_adapter, the algorithm data structure of the I²C adapter I2c_algorithm and the function of controlling the I²C adapter to generate the communication signal. is the implementation of the adapter side of the I²C hardware architecture The adapter can be controlled by the CPU and can even be integrated directly inside the CPU.
3) i²c device driver
I²c device driver mainly includes the data structure I2c_driver and i2c_client, we need to implement the member function according to the specific device. is the implementation of the device-side in the hardware architecture of I²C, the device is generally hooked up to the CPU-controlled i²c adapter, and the data is exchanged with the CPU via the I²C adapter.
1.2 I²c Equipment
All the I C devices are displayed in the Sysfs file system, stored in the/sys/bus/i2c/directory, listed as adapter address and chip address, I entered the command on Linux to obtain:
1.3 I2C.h Header File
The i2c.h header in the kernel defines the 4 data structures for I2c_driver, i2c_client, I2c_adapter, and I2c_algorithm. Understanding the role of these 4 structures is critical. The following analysis of the relationship between these 4 data structures and the role. As for the individual structure of the specific code to find in this file is OK.
1) I2c_adapter and I2c_algorithm.
The i2c_adapter corresponds to a physical adapter, while the i2c_algorithm corresponds to a set of communication methods. An I-C adapter requires a communication function provided in I2c_algorithm to control the adapter to generate a specific access cycle. A i2c_adapter that lacks i2c_algorithm can do nothing, so i2c_adapter contains a pointer to the I2c_algorithm it uses. the key function in I2c_algorithm Master_xfer () is used to generate the signals required for the I²c access cycle, in i2c_msg (that is, the I²C message) unit
2) I2c_driver and i2c_client.
The i2c_driver corresponds to a set of drive methods, which are purely auxiliary data structures that do not correspond to any physical entities. I2c_client corresponds to a real physical device, each I-C device needs a i2c_client to describe. I2c_client is generally included in the private information structure of the I-C character device. I2c_driver is associated with i2c_client at the moment when the I2c_driver Attach_adapter () function is run. Attach_adapter () detects the physical device and, when determining the presence of a client, points the adapter pointer of the I2c_client data structure used by the client to the corresponding I2c_adapter,driver pointer to the I2C_ Driver, and calls the I2c_adapter's Client_register () function. The opposite process occurs when the I2c_driver detach_client () function is called.
3) I2c_adpater and I2c_client
The relationship between I2c_adpater and I2c_client is consistent with the adapter and device in the I-C hardware system, that is, i2c_client is attached to I2c_adpater. Because a single adapter can connect multiple i²c devices, a i2c_adpater can also be Multiple i2c_client are attached, and the i2c_adpater includes a linked list of i2c_client attached to it.
2 Linux I²c Core
2.1 Add/Remove I2c_adapter.
int I²c Add Adapter (struct I²C adapter *adap); int i²c del adapter (struct-I²c adapter *adap);
2.2 Add/Remove I2c_driver.
int i²c Register driver (struct module *owner, struct-i²c driver *driver); int i²c del driver (struct-i²c driver *driver); inline int i²c Add driver (struct-i²c driver *driver);
2.3 I2c_client Attachment/Detachment
int i²c Attach Client (struct I²C client *client); int i²c detach Client (struct I²C client *client)
2.4 I²c transmit, send and receive
2.5 i²c Control Command Assignment
The following function is useful for assigning commands to the I-C adapter device file ioctl to the Algo_control () function of the algorithm of the Ching adapter or to the command () function of I2c_driver, as follows:
int i²c control (struct I²C client *client, unsigned int cmd, unsigned long arg), void i²c clients command (struct-i²c adapt ER *adap, unsigned int cmd,void *arg);
3 Linux i²c Bus driver
3.1 I²c Adapter driver loading and unloading
The module load and unload function template for the I²C bus driver is as follows code static int init i²c adapter XXX init (void) { xxx adpater HW init (); I²c Add Adapter (&xxx adapter); } static void exit I²c adapter XXX exit (void) { xxx adpater hw free (); I²c del adapter (&xxx adapter);
Implementations of the Xxx_adpater_hw_init () and Xxx_adpater_hw_free () functions are directly related to the specific CPU and I²C device hardware
3.2 I²c Bus Communication method
The
method of communication mainly implements the Master_xfer () function and the functionality () function of the i2c_algorithm. The functionality () function is very simple to return the communication protocol supported by algorithm, and the Master_xfer () function completes each i²c message in the number of i2c_msg passed to it on the I²c adapter, as shown in the following code, XXX The Master_xfer () function template for the device.
static int i²c adapter XXX xfer (struct i²c adapter *adap, struct i²c msg *msgs, int num) {... f or (i = 0; i < num; i++) {i²c adapter xxx start ();/* Generate start bit *///Read message */ if (msgs[i]->flags &i2c M RD) {i²c adapter xxx setaddr ((msg->addr << 1) | 1); /* Send from Device read address */i²c adapter XXX wait ack (); /* Get ack*/i²c adapter xxx readbytes (msgs[i]->buf, Msgs[i]->len) from the device; /* Read Msgs[i]->len Long data to msgs[i]->buf*/} else/* is write message */{ I²c Adapter xxx setaddr (msg->addr << 1); /* Send from Device write address */i²c adapter XXX wait ack (); /* Get ack*/i²c adapter xxx writebytes (msgs[i]->buf, Msgs[i]->len) from the device; /* Read Msgs[i]->len Long data to msgs[i]->buf*/}} i²c adapter xxx Stop (); /* Generate Stop bit */}
3.3 XXX_I2C Structural Body
Most i²c bus drivers define a XXX_I2C structure as the algo_data of the I2c_adapter (like "private Data"), which contains the I-C message pointer, the number index, and the I-C adapter algorithm access control spin lock, wait queue, etc., and mast The processing of messages in the Er_xfer () function completion message can also be controlled by access to the members of the XXX_I2C struct, defined by the XXX_I2C structure as follows:
struct XXX i²c { spinlock t lock; Wait Queue head T wait; struct-i²c msg *msg; unsigned int msg num; unsigned int msg idx; unsigned int msg ptr; ... struct-I²c adapter ADAP;
4 Linux i²c Device driver
I²c device driver to use i2c_driver and i2c_client data structures and populate them with member functions
4.1 Module loading and unloading
The load and unload function template code for the I²C device driver is as follows:
static int init YYY init (void) { int res; /* Register character device */ res = Register Chrdev (YYY MAJOR, "YYY", &yyy fops),//////Old Kernel interface//description register "YYY" This character device when using the file_operations structure The Yyy_fops description registers "yyy" for this character device, the file_operations structure used is yyy_fops if (res) goto out ; /* Add I²c driver*/ res = i²c Add driver (&yyy driver); if (res) goto out Unreg class; return 0; Out Unreg chrdev:unregister Chrdev (i²c MAJOR, "i²c"); OUT:PRINTK (KERN ERR "%s:driver initialisation failed\n", FILE); return res; } static void exit YYY exit (void) { i²c del driver (&i2cdev driver); Unregister Chrdev (YYY MAJOR, "YYY"); }
4.2 I2c_driver member functions
The execution of the i2c_add_driver will cause the execution of the Yyy_attach_adapter () function in the i2c_driver struct, and we can probe the physical device in the Yyy_attach_adapter () function. In order to implement the probe, the Yyy_attach_adapter () function simply calls the I2c_probe () function of the i²c core, and the I2c_attach_adapter function code of the I²C device driver is as follows:
static int yyy Attach adapter (struct I²C adapter *adapter) {
The 1th parameter is the I2c_adapter pointer, the 2nd parameter is the address data to be probed, and the 3rd parameter is the specific probe function
The I2c_probe () function throws a call to the Yyy_detect () function, and you can initialize the I2C_CLIENT,I2C device-driven detect function code in the Yyy_detect () function as follows:
static int yyy Detect (struct-I²c adapter *adapter, int address, int kind) {struct-i²c clien T *new client; struct YYY data *data; int err = 0; if (!I2C check functionality (adapter, i²c FUNC XXX) goto exit; if (! ( data = kzalloc (sizeof (struct yyy data), GFP KERNEL))//Allocates the memory of the private information structure, I2c_client is also created {err =-enomem; Goto exit; } New client = &data->client; New client->addr = address; New Client->adapter = adapter; New client->driver = &yyy driver; New client->flags = 0; /* The new client will be attached to adapter */if ((Err = i²c Attach client))//Call the kernel's i2c_attach_client () I C core system contains a A new I-C device goto exit Kfree; YYY Init client (new client); Initialize the i2c_client corresponding to the I²C device return 0; EXIT kfree:kfree (data); Exit:return err; }
When an I²C device-driven unload function makes a i2c_del_driver call, each i2c_client associated with Yyy_driver is thrown, and the code for the function Yyy_detach_client () is designed as follows:
static int yyy Detach client (struct I²C client *client) { int err; struct YYY Data *data = I²c get Clientdata (client); The I2c_get_clientdata () function is used to obtain the Yyy_data pointer from the i2c_client pointer in the Yyy_data private information structure ( err = i²c Detach Client ( Client))//Call the I-C core function i2c_detach_client (), this function will raise the I2c_adapter Client_unregister () function to be called return err; Kfree (data); Frees the Yyy_data memory. return 0;
implementation of 4.3 Yyy_command ()
It implements the control commands for the device. The specific control commands are device-dependent, assuming that the YYY device accepts two classes of command yyy_cmd1 and YYY_CMD2, while the functions that handle the two commands yyy_cmd1 () and YYY_CMD2 (), the I²C device-driven command function code is as follows:
static int yyy command (struct i²c client *client, unsigned int cmd, void *arg) { switch (cmd) { case YYY CMD1: return YYY cmd1 (client, arg); Case YYY CMD2: return YYY cmd2 (client, arg); Default: return -EINVAL; }
The implementation of the specific command is through the number of pieces of I2C_MSG messages, and call the core of the transmission, sending and receiving functions, I c core transmission, sending and receiving functions called I C adapter corresponding to the algorithm correlation function to complete.
4.4 File Operation interface
As a character class device, the Linux I C device-driven file operation interface is fully consistent with the normal device driver, but in which the i2c_client, I2c_driver, I2c_adapter, and i2c_algorithm structures and the i²c core are used, and the device read and write and control needs to take advantage of the architecture of the various components of the collaboration, the following is an I²C device file interface Write function Example:
Static Ssize t yyy write (struct file *file, char *buf, size t count, Loff t off) { struct i²c client *cli ent = (struct i²c client*) file->private data; I²c msg msg[1]; char *tmp; int ret; TMP = Kmalloc (count, GFP KERNEL); if (tmp = = NULL) return -Enomem; if (Copy from user (TMP, BUF, count)) { kfree (TMP); return -efault; } MSG[0].ADDR = client->addr;//address msg[0].flags = 0; 0 for write Msg[0].len = count; Number of bytes to write msg[0].buf = tmp; Data to be written ret = i²c transfer (Client->adapter, MSG, 1); Transfer i C message return (ret = = 1)? Count:ret;
The write operation of the I²C device has undergone several steps as follows:
- From user space to character device driver write function interface, write function constructs the number of I²C messages.
- The Write function passes the number of constructed I-C messages to the transfer function I2c_transfer () of the i²c core.
- I2 C Core transfer function I2c_tr Ansfer () find the corresponding adapter algorithm communication method function Master_xfer () to finalize the processing of the I²C message.
4.5 i2c-dev.c File Analysis
The I2cdev_read (), I2cdev_write () functions are provided in i2c-dev.c to correspond to the read () and write () file operation interfaces to be used by the user space, which invoke the I2c_master_recv () and i2c_ of the I C core, respectively The Master_send () function constructs an I²C message and raises the call of the adapter algorithm communication function to complete the transmission of the message. But i2c-dev.c the I2cdev_read () and I2cdev_write () functions are not too versatile, There is not much practical value, only applicable to non-repstart mode situations. For reads and writes of more than two messages, the I2C_MSG message array needs to be woven into the user space and the I2c_rdwr IOCTL command is called.
All rights reserved, reprint please specify reprint address: http://www.cnblogs.com/lihuidashen/p/4511469.html
Oneness ~linux device-driven i²c core, bus, and device driver