• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# I2C<a name="EN-US_TOPIC_0000001206171515"></a>
2
3## Overview<a name="section5361140416"></a>
4
5The Inter-Integrated Circuit \(I2C\) is a simple, bidirectional, and synchronous serial bus that uses merely two wires.
6
7In an I2C communication, one controller communicates with one or more devices through the serial data line \(SDA\) and serial clock line \(SCL\), as shown in  [Figure 1](#fig1135561232714).
8
9I2C data transfer must begin with a  **START**  condition and end with a  **STOP**  condition. Data is transmitted byte-by-byte from the most significant bit to the least significant bit.
10
11Each I2C node is recognized by a unique address and can serve as either a controller or a device. When the controller needs to communicate with a device, it writes the device address to the bus through broadcast. A device matching this address sends a response to set up a data transfer channel.
12
13The I2C APIs define a set of common functions for I2C data transfer, including:
14
15-   I2C controller management: opening or closing an I2C controller
16-   I2C message transfer: custom transfer by using a message array
17
18**Figure  1**  Physical connection diagram for I2C<br/>![](figures/physical-connection-diagram-for-i2c.png "physical-connection-diagram-for-i2c")
19
20
21## Available APIs<a name="section545869122317"></a>
22
23**Table  1**  APIs available for the I2C driver
24
25<a name="table1731550155318"></a>
26<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" valign="top" width="18.63%" id="mcps1.2.4.1.1"><p id="p641050105320"><a name="p641050105320"></a><a name="p641050105320"></a>Capability</p>
27</th>
28<th class="cellrowborder" valign="top" width="28.03%" id="mcps1.2.4.1.2"><p id="p54150165315"><a name="p54150165315"></a><a name="p54150165315"></a>Function</p>
29</th>
30<th class="cellrowborder" valign="top" width="53.339999999999996%" id="mcps1.2.4.1.3"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>Description</p>
31</th>
32</tr>
33</thead>
34<tbody><tr id="row34145016535"><td class="cellrowborder" rowspan="2" valign="top" width="18.63%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>I2C controller management</p>
35</td>
36<td class="cellrowborder" valign="top" width="28.03%" headers="mcps1.2.4.1.2 "><p id="p19389143041518"><a name="p19389143041518"></a><a name="p19389143041518"></a>I2cOpen</p>
37</td>
38<td class="cellrowborder" valign="top" width="53.339999999999996%" headers="mcps1.2.4.1.3 "><p id="p8738101941716"><a name="p8738101941716"></a><a name="p8738101941716"></a>Opens an I2C controller.</p>
39</td>
40</tr>
41<tr id="row5632152611414"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p143890309153"><a name="p143890309153"></a><a name="p143890309153"></a>I2cClose</p>
42</td>
43<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p573815197171"><a name="p573815197171"></a><a name="p573815197171"></a>Closes an I2C controller.</p>
44</td>
45</tr>
46<tr id="row15108165391412"><td class="cellrowborder" valign="top" width="18.63%" headers="mcps1.2.4.1.1 "><p id="p91084533141"><a name="p91084533141"></a><a name="p91084533141"></a>I2C message transfer</p>
47</td>
48<td class="cellrowborder" valign="top" width="28.03%" headers="mcps1.2.4.1.2 "><p id="p13901730101511"><a name="p13901730101511"></a><a name="p13901730101511"></a>I2cTransfer</p>
49</td>
50<td class="cellrowborder" valign="top" width="53.339999999999996%" headers="mcps1.2.4.1.3 "><p id="p12738111912171"><a name="p12738111912171"></a><a name="p12738111912171"></a>Performs a custom transfer.</p>
51</td>
52</tr>
53</tbody>
54</table>
55
56>![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
57>All functions provided in this document can be called only in kernel mode.
58
59## Usage Guidelines<a name="section1695201514281"></a>
60
61### How to Use<a name="section1338373417288"></a>
62
63The figure below illustrates how to use the APIs.
64
65**Figure  2**  Using I2C driver APIs
66
67![](figures/using-i2c-process.png "process-of-using-an-i2c-device")
68
69### Opening an I2C Controller<a name="section13751110132914"></a>
70
71Call the **I2cOpen()** function to open an I2C controller.
72
73DevHandle I2cOpen\(int16\_t number\);
74
75**Table  2**  Description of I2cOpen
76
77<a name="table7603619123820"></a>
78<table><thead align="left"><tr id="row1060351914386"><th class="cellrowborder" valign="top" width="20.66%" id="mcps1.2.3.1.1"><p id="p14603181917382"><a name="p14603181917382"></a><a name="p14603181917382"></a><strong id="b72871132125714"><a name="b72871132125714"></a><a name="b72871132125714"></a>Parameter</strong></p>
79</th>
80<th class="cellrowborder" valign="top" width="79.34%" id="mcps1.2.3.1.2"><p id="p36031519183819"><a name="p36031519183819"></a><a name="p36031519183819"></a><strong id="b1721203713577"><a name="b1721203713577"></a><a name="b1721203713577"></a>Description</strong></p>
81</th>
82</tr>
83</thead>
84<tbody><tr id="row1960431983813"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p3604719123817"><a name="p3604719123817"></a><a name="p3604719123817"></a>number</p>
85</td>
86<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p221392414442"><a name="p221392414442"></a><a name="p221392414442"></a>I2C controller ID.</p>
87</td>
88</tr>
89<tr id="row11410612183019"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p460381915385"><a name="p460381915385"></a><a name="p460381915385"></a><strong id="b14182113945714"><a name="b14182113945714"></a><a name="b14182113945714"></a>Return Value</strong></p>
90</td>
91<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p96031619153812"><a name="p96031619153812"></a><a name="p96031619153812"></a><strong id="b92161640145714"><a name="b92161640145714"></a><a name="b92161640145714"></a>Description</strong></p>
92</td>
93</tr>
94<tr id="row15410111273017"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p1060418195389"><a name="p1060418195389"></a><a name="p1060418195389"></a>NULL</p>
95</td>
96<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p760471912388"><a name="p760471912388"></a><a name="p760471912388"></a>Failed to open the I2C controller.</p>
97</td>
98</tr>
99<tr id="row1241081213303"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p5604719133811"><a name="p5604719133811"></a><a name="p5604719133811"></a>Device handle</p>
100</td>
101<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p3604181933818"><a name="p3604181933818"></a><a name="p3604181933818"></a>Handle of the I2C controller.</p>
102</td>
103</tr>
104</tbody>
105</table>
106
107This example assumes that the system has eight I2C controllers \(numbered from 0 to 7\) and I2C controller 3 is to open.
108
109```
110DevHandle i2cHandle = NULL; /* I2C controller handle */
111
112/* Open an I2C controller. */
113i2cHandle = I2cOpen(3);
114if (i2cHandle == NULL) {
115    HDF_LOGE("I2cOpen: failed\n");
116    return;
117}
118```
119
120### Performing I2C Communication<a name="section9202183372916"></a>
121
122Call the **I2cTransfer()** function to transfer messages.
123
124int32\_t I2cTransfer\(DevHandle handle, struct I2cMsg \*msgs, int16\_t count\);
125
126**Table  3**  Description of I2cTransfer
127
128<a name="table1934414174212"></a>
129<table><thead align="left"><tr id="row1134415176216"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p13295152320217"><a name="p13295152320217"></a><a name="p13295152320217"></a><strong id="b16680203655712"><a name="b16680203655712"></a><a name="b16680203655712"></a>Parameter</strong></p>
130</th>
131<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p1295112352115"><a name="p1295112352115"></a><a name="p1295112352115"></a><strong id="b183651837145710"><a name="b183651837145710"></a><a name="b183651837145710"></a>Description</strong></p>
132</th>
133</tr>
134</thead>
135<tbody><tr id="row5344101702113"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19295132382111"><a name="p19295132382111"></a><a name="p19295132382111"></a>handle</p>
136</td>
137<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1051172572919"><a name="p1051172572919"></a><a name="p1051172572919"></a>Handle of an I2C controller.</p>
138</td>
139</tr>
140<tr id="row17344171722117"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p9295122332113"><a name="p9295122332113"></a><a name="p9295122332113"></a>msgs</p>
141</td>
142<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p202951238218"><a name="p202951238218"></a><a name="p202951238218"></a>Message array of the data to transfer.</p>
143</td>
144</tr>
145<tr id="row45812466213"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1659246112117"><a name="p1659246112117"></a><a name="p1659246112117"></a>count</p>
146</td>
147<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p259124622119"><a name="p259124622119"></a><a name="p259124622119"></a>Length of the message array.</p>
148</td>
149</tr>
150<tr id="row04701426105110"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17295142322113"><a name="p17295142322113"></a><a name="p17295142322113"></a><strong id="b9681123965720"><a name="b9681123965720"></a><a name="b9681123965720"></a>Return Value</strong></p>
151</td>
152<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p142959232211"><a name="p142959232211"></a><a name="p142959232211"></a><strong id="b1159414403579"><a name="b1159414403579"></a><a name="b1159414403579"></a>Description</strong></p>
153</td>
154</tr>
155<tr id="row74701226125110"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p929532313211"><a name="p929532313211"></a><a name="p929532313211"></a>Positive integer</p>
156</td>
157<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p829512237217"><a name="p829512237217"></a><a name="p829512237217"></a>Number of message structures that are successfully transmitted.</p>
158</td>
159</tr>
160<tr id="row204701126195115"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p12958234217"><a name="p12958234217"></a><a name="p12958234217"></a>Negative value</p>
161</td>
162<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1295192312112"><a name="p1295192312112"></a><a name="p1295192312112"></a>Failed to perform the message transfer.</p>
163</td>
164</tr>
165</tbody>
166</table>
167
168The type of an I2C message transfer is defined by  **I2cMsg**. Each message structure indicates a read or write operation. Multiple read or write operations can be performed by using a message array.
169
170```
171int32_t ret;
172uint8_t wbuff[2] = { 0x12, 0x13 };
173uint8_t rbuff[2] = { 0 };
174struct I2cMsg msgs[2]; /* Custom message array for transfer */
175msgs[0].buf = wbuff;    /* Data to write */
176msgs[0].len = 2;        /* The length of the data to write is 2. */
177msgs[0].addr = 0x5A;    /* The address of the device to write the data is 0x5A. */
178msgs[0].flags = 0;      /* The flag is 0, indicating the write operation. */
179msgs[1].buf = rbuff;    /* Data to read */
180msgs[1].len = 2;        /* The length of the data to read is 2. */
181msgs[1].addr = 0x5A;    /* The address of the device to read is 0x5A. */
182msgs[1].flags = I2C_FLAG_READ /* I2C_FLAG_READ is configured, indicating the read operation. */
183/* Perform a custom transfer to transfer two messages. */
184ret = I2cTransfer(i2cHandle, msgs, 2);
185if (ret != 2) {
186    HDF_LOGE("I2cTransfer: failed, ret %d\n", ret);
187    return;
188}
189```
190
191>![](../public_sys-resources/icon-caution.gif) **CAUTION**<br/>
192>-   The device address in the  **I2cMsg**  structure does not contain the read/write flag bit. The read/write information is transferred by the read/write control bit in the member variable  **flags**.
193>-   The  **I2cTransfer**  function does not limit the number of message structures and the data length of each message structure, which are determined by the I2C controller.
194>-   The  **I2cTransfer**  function may cause the system to sleep and therefore cannot be called in the interrupt context.
195
196### Closing an I2C Controller<a name="section19481164133018"></a>
197
198Call the **I2cClose()** function to close the I2C controller after the communication is complete.
199
200void I2cClose\(DevHandle \*handle\);
201
202**Table  4**  Description of I2cClose
203
204<a name="table72517953115"></a>
205<table><thead align="left"><tr id="row1525793312"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p115402031153111"><a name="p115402031153111"></a><a name="p115402031153111"></a>Parameter</p>
206</th>
207<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p65406313319"><a name="p65406313319"></a><a name="p65406313319"></a>Description</p>
208</th>
209</tr>
210</thead>
211<tbody><tr id="row1926109193116"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p105419317318"><a name="p105419317318"></a><a name="p105419317318"></a>handle</p>
212</td>
213<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1213245577"><a name="p1213245577"></a><a name="p1213245577"></a>Handle of the I2C controller to close.</p>
214</td>
215</tr>
216</tbody>
217</table>
218
219
220```
221I2cClose(i2cHandle); /* Close the I2C controller. */
222```
223
224## Usage Example<a name="section5302202015300"></a>
225
226This example describes how to use I2C APIs with an I2C device on a development board.
227
228This example shows a simple register read/write operation on TouchPad on a Hi3516D V300 development board. The basic hardware information is as follows:
229
230-   SoC: hi3516dv300
231
232-   Touch IC: The I2C address is 0x38, and the bit width of Touch IC's internal register is 1 byte.
233
234-   Schematic diagram: TouchPad is mounted to I2C controller 3. The reset pin of Touch IC is GPIO3.
235
236In this example, first we reset Touch IC. \(The development board supplies power to Touch IC by default after being powered on, and this use case does not consider the power supply\). Then, we perform a read/write operation on an internal register to test whether the I2C channel is normal.
237
238>![](../public_sys-resources/icon-note.gif) **NOTE** <br/>
239>The example focuses on I2C device access and verifies the I2C channel. The read and write values of the device register are not concerned. The behavior caused by the read and write operations on the register is determined by the device itself.
240
241Example:
242
243```
244#include "i2c_if.h"          /* Header file of I2C APIs */
245#include "gpio_if.h"         /* Header file of GPIO APIs */
246#include "hdf_log.h"         /* Header file for log APIs */
247#include "osal_io.h"         /* Header file of I/O read and write APIs */
248#include "osal_time.h"       /* Header file of delay and sleep APIs */
249
250/* Define a TP device structure to store I2C and GPIO hardware information. */
251struct TpI2cDevice {
252    uint16_t rstGpio;             /* Reset pin */
253    uint16_t busId;               /* I2C bus ID */
254    uint16_t addr;                /* I2C device address */
255    uint16_t regLen;              /* Register bit width */
256    DevHandle i2cHandle;  /* I2C controller handle */
257};
258
259/* I2C pin I/O configuration. For details, see the SoC register manual. */
260#define I2C3_DATA_REG_ADDR 0x112f008c /* Address of the SDA pin configuration register of I2C controller 3
261#define I2C3_CLK_REG_ADDR 0x112f0090 /* Address of the SCL pin configuration register of I2C controller 3
262#define I2C_REG_CFG 0x5f1             /* Configuration values of SDA and SCL pins of I2C controller 3
263
264static void TpSocIoCfg(void)
265{
266    /* Set the I/O function of the two pins corresponding to I2C controller 3 to I2C. */
267    OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR));
268    OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR));
269}
270
271/* Initialize the reset pin of the TP. Pull up the pin for 20 ms, pull down the pin for 50 ms, and then pull up the pin for 20 ms to complete the resetting. */
272static int32_t TestCaseGpioInit(struct TpI2cDevice *tpDevice)
273{
274    int32_t ret;
275
276    /* Set the output direction for the reset pin. */
277    ret = GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT);
278    if (ret != HDF_SUCCESS) {
279        HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret);
280        return ret;
281    }
282
283    ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
284    if (ret != HDF_SUCCESS) {
285        HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret);
286        return ret;
287    }
288    OsalMSleep(20);
289
290    ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW);
291    if (ret != HDF_SUCCESS) {
292        HDF_LOGE("%s: set rst low fail!:%d", __func__, ret);
293        return ret;
294    }
295    OsalMSleep(50);
296
297    ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
298    if (ret != HDF_SUCCESS) {
299        HDF_LOGE("%s: set rst high fail!:%d", __func__, ret);
300        return ret;
301    }
302    OsalMSleep(20);
303
304    return HDF_SUCCESS;
305}
306
307/* Use I2cTransfer to encapsulate a register read/write auxiliary function. Use flag to indicate the read or write operation. */
308static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, unsigned int regAddr,
309    unsigned char *regData, unsigned int dataLen, uint8_t flag)
310{
311    int index = 0;
312    unsigned char regBuf[4] = {0};
313    struct I2cMsg msgs[2] = {0};
314
315    /* Perform length adaptation for the single- or dual-byte register. */
316    if (tpDevice->regLen == 1) {
317        regBuf[index++] = regAddr & 0xFF;
318    } else {
319        regBuf[index++] = (regAddr >> 8) & 0xFF;
320        regBuf[index++] = regAddr & 0xFF;
321    }
322
323    /* Fill in the I2cMsg message structure. */
324    msgs[0].addr = tpDevice->addr;
325    msgs[0].flags = 0; /* The flag is 0, indicating the write operation. */
326    msgs[0].len = tpDevice->regLen;
327    msgs[0].buf = regBuf;
328
329    msgs[1].addr = tpDevice->addr;
330    msgs[1].flags = (flag == 1)? I2C_FLAG_READ: 0; /* Add the read flag. */
331    msgs[1].len = dataLen;
332    msgs[1].buf = regData;
333
334    if (I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2) {
335        HDF_LOGE("%s: i2c read err", __func__);
336        return HDF_FAILURE;
337    }
338    return HDF_SUCCESS;
339}
340
341/* TP register read function */
342static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, unsigned int regAddr,
343    unsigned char *regData, unsigned int dataLen)
344{
345    return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 1);
346}
347
348/* TP register write function */
349static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, unsigned int regAddr,
350    unsigned char *regData, unsigned int dataLen)
351{
352    return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 0);
353}
354
355/* Main entry of I2C */
356static int32_t TestCaseI2c(void)
357{
358    int32_t i;
359    int32_t ret;
360    unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC };
361    unsigned char bufRead[7] = {0};
362    static struct TpI2cDevice tpDevice;
363
364    /* I/O pin function configuration */
365    TpSocIoCfg();
366
367    /* Initialize TP device information. */
368    tpDevice.rstGpio = 3;
369    tpDevice.busId = 3;
370    tpDevice.addr = 0x38;
371    tpDevice.regLen = 1;
372    tpDevice.i2cHandle = NULL;
373
374    /* Initialize the GPIO pin. */
375    ret = TestCaseGpioInit(&tpDevice);
376    if (ret != HDF_SUCCESS) {
377        HDF_LOGE("%s: gpio init fail!:%d", __func__, ret);
378        return ret;
379    }
380
381    /* Open an I2C controller. */
382    tpDevice.i2cHandle = I2cOpen(tpDevice.busId);
383    if (tpDevice.i2cHandle == NULL) {
384        HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId);
385        return -1;
386    }
387
388    /* Continuously write 7-byte data to register 0xD5 of TP-IC. */
389    ret = TpI2cWriteReg(&tpDevice, 0xD5, bufWrite, 7);
390    if (ret != HDF_SUCCESS) {
391        HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret);
392        I2cClose(tpDevice.i2cHandle);
393        return -1;
394    }
395    OsalMSleep(10);
396
397    /* Continuously read 7-byte data from register 0xD5 of TP-IC. */
398    ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7);
399    if (ret != HDF_SUCCESS) {
400        HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret);
401        I2cClose(tpDevice.i2cHandle);
402        return -1;
403    }
404
405    HDF_LOGE("%s: tp i2c write&read reg success!", __func__);
406    for (i = 0; i < 7; i++) {
407        HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]);
408    }
409
410    /* Close the I2C controller. */
411    I2cClose(tpDevice.i2cHandle);
412    return ret;
413}
414```
415
416