I2C Driver Programming Interface

Source: Internet
Author: User

1. Communication Interface

The data sent or received by I2C is encapsulated by the packet struct i2c_msg.

Struct i2c_msg {_ 2010addr; // slave address _ 2010flags; // flag # define i2c_m_ten 0x0010 // ten address flag # define i2c_m_rd 0x0001 // receives the data flag _ Len; // Data Length _ u8 * Buf; // Data Pointer };

ADDR indicates the slave address, flags indicates the communication, 0 indicates the sent data, and i2c_m_rd indicates the received data. Len indicates the number of data bytes for the communication; buf is the pointer to send or receive data. In device drivers, we usually call the i2c_master_send and i2c_master_recv interfaces defined by the i2c-core to send or receive data once.

Int i2c_master_send (struct i2c_client * client, const char * Buf, int count) {int ret; struct i2c_adapter * ADAP = client-> adapter; // obtain the adapter information struct i2c_msg; // define a temporary data packet MSG. ADDR = client-> ADDR; // write the data packet from the host address to MSG. flags = client-> flags & i2c_m_ten; // merges the slave sign into the packet MSG. len = count; // write the number of data bytes sent this time into the packet MSG. buf = (char *) BUF; // write the sent data pointer to the data packet ret = i2c_transfer (ADAP, & MSG, 1); // call the platform interface to send data/* If EV Erything went OK (I. e. 1 MSG transmitted), return # bytes transmitted, else error code. */Return (ret = 1 )? Count: ret; // The number of bytes returned if the message is sent successfully} export_symbol (i2c_master_send );

The i2c_master_send interface has three parameters: the client is the slave machine that communicates with the host, the Buf is the Data Pointer sent, and the count is the number of bytes sent data.

Int i2c_master_recv (struct i2c_client * client, char * Buf, int count) {struct i2c_adapter * ADAP = client-> adapter; // obtain the adapter information struct i2c_msg MSG; // define a temporary data packet int ret; MSG. ADDR = client-> ADDR; // write the data packet from the host address to MSG. flags = client-> flags & i2c_m_ten; // merges the slave sign into the packet MSG. flags | = i2c_m_rd; // the flag of the communication is incorporated into the packet MSG. len = count; // write the number of data bytes received this time into the packet MSG. buf = Buf; ret = i2c_transfer (ADAP, & MSG, 1); // call the platform interface to receive Data/* if everything went OK (I. e. 1 MSG transmitted), return # bytes transmitted, else error code. */Return (ret = 1 )? Count: ret; // The number of bytes returned if the message is received successfully} export_symbol (i2c_master_recv );

The i2c_master_recv interface has three parameters: the client is the slave that communicates with the host, the Buf is the Data Pointer received, and the count is the number of bytes of received data. Let's take a look at the i2c_transfer interface parameter descriptions:

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); 

Among them, ADAP is the adapter for communication between the host and the slave; msgs is the communication data packet, which can be one or more data packets; num
This parameter is used to specify the number of data packets. If it is greater than 1, more than once communication is performed. One communication requires addressing once. If multiple communications are required, multiple addressing is required. The first two interfaces communicate once, so num is 1; in some cases, to read the value of a register, you must first send a register address to the slave machine before receiving data, in this way, if you want to encapsulate an interface, you need to set num to 2. The Return Value of the interface is negative if it fails. If it succeeds, the number of transmitted packets is returned. For example, the interface for reading a register can be encapsulated as follows:

Static int read_reg (struct i2c_client * client, unsigned char Reg, unsigned char * Data) {int ret; struct i2c_msg msgs [] = {{. ADDR = client-> ADDR ,. flags = 0 ,. len = 1 ,. buf = & reg, // Register address },{. ADDR = client-> ADDR ,. flags = i2c_m_rd ,. len = 1 ,. buf = data, // register value },}; ret = i2c_transfer (client-> adapter, msgs, 2); // num = 2, successfully communicating ret = 2 if (Ret <0) tp_err ("% s error: % d \ n", _ FUNC __, RET); return ret ;}

You can also encapsulate the interface described earlier:

Static unsigned char read_reg (struct i2c_client * client, unsigned char REG) {unsigned char Buf; i2c_master_send (client, & reg, 1); // send Register address i2c_master_recv (client, & Buf, 1); // The value of the receiving register return Buf ;}

2. Reset
Recently, the interface is often deadlocked because of the I2C bus of the platform. It is found that both SDA and SCL are pulled low by the logic analyzer, so the reset mechanism is added to the i2c-core, the general idea is as follows: (1) In I2C. driver and I2C. the reset interface is added to the structure of the adapter, that is, each I2C device can register a reset function, and each I2C bus has a corresponding reset interface (2) When a deadlock occurs, first, obtain the device address and bus number of the current communication according to the information of the i2c-timeout, and then execute the reset function of all I2C devices under the current bus in turn, and then try to send the success; if the bus is still deadlocked, I2C is executed. reset function of the adapter; restart the machine if the bus is still in a deadlock; a total of three layers of Reset Mechanism (3) I2C. the reset function of the driver generally operates on the reset of the device.
Pin Or power supply (required according to the hardware design) (4) I2C. the reset function of the adapter is preferred to simulate and unlock the SCL, and then to operate the power of the device on the entire bus (the operation should be performed according to the hardware design) (5) restart is the last layer of the mechanism. In this case, the device can only be restarted because I2C. the adapter layer needs to be added to the i2c-core to traverse all the current bus devices and execute the device reset function interface i2c_reset_device:

/** * i2c_reset_device - reset I2C device when bus dead * @adapter: the adapter being reset * @addr: the device address */ static int __i2c_reset_device(struct device *dev, void *addrp) {     struct i2c_client *client = to_i2c_client(dev);     int addr = *(int *)addrp;      if (client && client->driver && client->driver->reset)         return client->driver->reset();      return 0; }  int i2c_reset_device(struct i2c_adapter *adapter, int addr) {     return device_for_each_child(&adapter->dev, &addr, __i2c_reset_device); } EXPORT_SYMBOL(i2c_reset_device); 

Note that the returned value of the reset function of I2C. Driver must be 0. Otherwise, device_for_each_child will not continue the subsequent traversal. The following is a reference code used to simulate the activation of an SCL using gpio:

 static int i2c_reset_adapter(void) {     int counter = 0;      gpio_request(I2C_BUS_DATA, "gpioxx");     gpio_request(I2C_BUS_CLK, "gpioxx");     /* try to recover I2C bus */     gpio_direction_input(I2C_BUS_DATA);      if (!__gpio_get_value(I2C_BUS_DATA)) {         while((!__gpio_get_value(I2C_BUS_DATA)) && ++counter < 10)         {             udelay(5);             gpio_direction_output(I2C_BUS_CLK, 1);             udelay(5);             gpio_direction_output(I2C_BUS_CLK, 0);         }         i2c_err("try to recover i2c bus, retry times are %d\n",counter);         if (counter < 10) {             udelay(5);             gpio_direction_output(I2C_BUS_DATA, 0);             udelay(5);             gpio_direction_output(I2C_BUS_CLK, 1);             udelay(5);             gpio_direction_output(I2C_BUS_DATA, 1);             msleep(10);         } else {             i2c_err("try to recover i2c bus failed!\n");         }     }      gpio_free(I2C_BUS_DATA);     gpio_free(I2C_BUS_CLK);      return 0; } 

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.