• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# I2C<a name="EN-US_TOPIC_0000001052778273"></a>
2
3-   [Overview](#section5361140416)
4    -   [Available APIs](#section459052019177)
5
6-   [Usage Guidelines](#section1695201514281)
7    -   [How to Use](#section1338373417288)
8    -   [Opening an I2C Controller](#section13751110132914)
9    -   [Performing I2C Communication](#section9202183372916)
10    -   [Closing an I2C Controller](#section19481164133018)
11
12-   [Usage Example](#section5302202015300)
13
14## Overview<a name="section5361140416"></a>
15
16-   The Inter-Integrated Circuit \(I2C\) is a simple, bidirectional, and synchronous serial bus that uses merely two wires.
17-   In 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).
18
19-   I2C 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.
20-   Each 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.
21
22-   The I2C APIs define a set of common functions for I2C data transfer, including:
23
24    -   I2C controller management: opening or closing an I2C controller
25    -   I2C message transfer: custom transfer by using a message array
26
27    **Figure  1**  Physical connection diagram for I2C<a name="fig1135561232714"></a>
28    ![](figure/physical-connection-diagram-for-i2c.png "physical-connection-diagram-for-i2c")
29
30
31### Available APIs<a name="section459052019177"></a>
32
33**Table  1**  APIs available for the I2C driver
34
35<a name="table1731550155318"></a>
36<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>
37</th>
38<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>
39</th>
40<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>
41</th>
42</tr>
43</thead>
44<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>
45</td>
46<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>
47</td>
48<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>
49</td>
50</tr>
51<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>
52</td>
53<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>
54</td>
55</tr>
56<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>
57</td>
58<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>
59</td>
60<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>
61</td>
62</tr>
63</tbody>
64</table>
65
66>![](../public_sys-resources/icon-note.gif) **NOTE:**
67>All functions provided in this document can be called only in kernel mode.
68
69## Usage Guidelines<a name="section1695201514281"></a>
70
71### How to Use<a name="section1338373417288"></a>
72
73[Figure 2](#fig166181128151112)  illustrates the process of an I2C device.
74
75**Figure  2**  Process of using an I2C device<a name="fig166181128151112"></a>
76
77
78![](figure/en-us_image_0000001123509750.png)
79
80### Opening an I2C Controller<a name="section13751110132914"></a>
81
82Call the following function to open an I2C controller:
83
84DevHandle I2cOpen\(int16\_t number\);
85
86**Table  2**  Description of I2cOpen
87
88<a name="table7603619123820"></a>
89<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>
90</th>
91<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>
92</th>
93</tr>
94</thead>
95<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>
96</td>
97<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>
98</td>
99</tr>
100<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>
101</td>
102<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>
103</td>
104</tr>
105<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>
106</td>
107<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>
108</td>
109</tr>
110<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>
111</td>
112<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>
113</td>
114</tr>
115</tbody>
116</table>
117
118This example assumes that the system has eight I2C controllers \(numbered from 0 to 7\) and I2C controller 3 is to open.
119
120```
121DevHandle i2cHandle = NULL; /* I2C controller handle */
122
123/* Open an I2C controller. */
124i2cHandle = I2cOpen(3);
125if (i2cHandle == NULL) {
126    HDF_LOGE("I2cOpen: failed\n");
127    return;
128}
129```
130
131### Performing I2C Communication<a name="section9202183372916"></a>
132
133Use the following function for message transfer:
134
135int32\_t I2cTransfer\(DevHandle handle, struct I2cMsg \*msgs, int16\_t count\);
136
137**Table  3**  Description of I2cTransfer
138
139<a name="table1934414174212"></a>
140<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>
141</th>
142<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>
143</th>
144</tr>
145</thead>
146<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>
147</td>
148<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>
149</td>
150</tr>
151<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>
152</td>
153<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>
154</td>
155</tr>
156<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>
157</td>
158<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>
159</td>
160</tr>
161<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>
162</td>
163<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>
164</td>
165</tr>
166<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>
167</td>
168<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>
169</td>
170</tr>
171<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>
172</td>
173<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>
174</td>
175</tr>
176</tbody>
177</table>
178
179The 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.
180
181```
182int32_t ret;
183uint8_t wbuff[2] = { 0x12, 0x13 };
184uint8_t rbuff[2] = { 0 };
185struct I2cMsg msgs[2]; /* Custom message array for transfer */
186msgs[0].buf = wbuff;    /* Data to write */
187msgs[0].len = 2;        /* The length of the data to write is 2. */
188msgs[0].addr = 0x5A;    /* The address of the device to write the data is 0x5A. */
189msgs[0].flags = 0;      /* The flag is 0, indicating the write operation. */
190msgs[1].buf = rbuff;    /* Data to read */
191msgs[1].len = 2;        /* The length of the data to read is 2. */
192msgs[1].addr = 0x5A;    /* The address of the device to read is 0x5A. */
193msgs[1].flags = I2C_FLAG_READ /* I2C_FLAG_READ is configured, indicating the read operation. */
194/* Perform a custom transfer to transfer two messages. */
195ret = I2cTransfer(i2cHandle, msgs, 2);
196if (ret != 2) {
197    HDF_LOGE("I2cTransfer: failed, ret %d\n", ret);
198    return;
199}
200```
201
202>![](../public_sys-resources/icon-caution.gif) **CAUTION:**
203>-   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**.
204>-   The  **I2cTransfer**  function does not limit the number of message structures, which is determined by the I2C controller.
205>-   The  **I2cTransfer**  function does not limit the data length of each message structure, which is determined by the I2C controller.
206>-   The  **I2cTransfer**  function may cause the system to sleep and therefore cannot be called in the interrupt context.
207
208### Closing an I2C Controller<a name="section19481164133018"></a>
209
210Call the following function to close the I2C controller after the communication is complete:
211
212void I2cClose\(DevHandle \*handle\);
213
214**Table  4**  Description of I2cClose
215
216<a name="table72517953115"></a>
217<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>
218</th>
219<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>
220</th>
221</tr>
222</thead>
223<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>
224</td>
225<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 an I2C controller.</p>
226</td>
227</tr>
228</tbody>
229</table>
230
231```
232I2cClose(i2cHandle); /* Close the I2C controller. */
233```
234
235## Usage Example<a name="section5302202015300"></a>
236
237This example describes how to use I2C APIs with an I2C device on a development board.
238
239This example shows a simple register read/write operation on TouchPad on a Hi3516D V300 development board. The basic hardware information is as follows:
240
241-   SoC: hi3516dv300
242
243-   Touch IC: The I2C address is 0x38, and the bit width of Touch IC's internal register is 1 byte.
244
245-   Schematic diagram: TouchPad is mounted to I2C controller 3. The reset pin of Touch IC is GPIO3.
246
247In 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.
248
249>![](../public_sys-resources/icon-note.gif) **NOTE:**
250>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.
251
252Example:
253
254```
255#include "i2c_if.h"          /* Header file of I2C APIs */
256#include "gpio_if.h"         /* Header file of GPIO APIs */
257#include "hdf_log.h"         /* Header file for log APIs */
258#include "osal_io.h"         /* Header file of I/O read and write APIs */
259#include "osal_time.h"       /* Header file of delay and sleep APIs */
260
261/* Define a TP device structure to store I2C and GPIO hardware information. */
262struct TpI2cDevice {
263    uint16_t rstGpio;             /* Reset pin */
264    uint16_t busId;               /* I2C bus ID */
265    uint16_t addr;                /* I2C device address */
266    uint16_t regLen;              /* Register bit width */
267    DevHandle i2cHandle;  /* I2C controller handle */
268};
269
270/* I2C pin I/O configuration. For details, see the SoC register manual. */
271#define I2C3_DATA_REG_ADDR 0x112f008c /* Address of the SDA pin configuration register of I2C controller 3
272#define I2C3_CLK_REG_ADDR 0x112f0090 /* Address of the SCL pin configuration register of I2C controller 3
273#define I2C_REG_CFG 0x5f1             /* Configuration values of SDA and SCL pins of I2C controller 3
274
275static void TpSocIoCfg(void)
276{
277    /* Set the I/O function of the two pins corresponding to I2C controller 3 to I2C. */
278    OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR));
279    OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR));
280}
281
282/* 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. */
283static int32_t TestCaseGpioInit(struct TpI2cDevice *tpDevice)
284{
285    int32_t ret;
286
287    /* Set the output direction for the reset pin. */
288    ret = GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT);
289    if (ret != HDF_SUCCESS) {
290        HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret);
291        return ret;
292    }
293
294    ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
295    if (ret != HDF_SUCCESS) {
296        HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret);
297        return ret;
298    }
299    OsalMSleep(20);
300
301    ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW);
302    if (ret != HDF_SUCCESS) {
303        HDF_LOGE("%s: set rst low fail!:%d", __func__, ret);
304        return ret;
305    }
306    OsalMSleep(50);
307
308    ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
309    if (ret != HDF_SUCCESS) {
310        HDF_LOGE("%s: set rst high fail!:%d", __func__, ret);
311        return ret;
312    }
313    OsalMSleep(20);
314
315    return HDF_SUCCESS;
316}
317
318/* Use I2cTransfer to encapsulate a register read/write auxiliary function. Use flag to indicate the read or write operation. */
319static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, unsigned int regAddr,
320    unsigned char *regData, unsigned int dataLen, uint8_t flag)
321{
322    int index = 0;
323    unsigned char regBuf[4] = {0};
324    struct I2cMsg msgs[2] = {0};
325
326    /* Perform length adaptation for the single- or dual-byte register. */
327    if (tpDevice->regLen == 1) {
328        regBuf[index++] = regAddr & 0xFF;
329    } else {
330        regBuf[index++] = (regAddr >> 8) & 0xFF;
331        regBuf[index++] = regAddr & 0xFF;
332    }
333
334    /* Fill in the I2cMsg message structure. */
335    msgs[0].addr = tpDevice->addr;
336    msgs[0].flags = 0; /* The flag is 0, indicating the write operation. */
337    msgs[0].len = tpDevice->regLen;
338    msgs[0].buf = regBuf;
339
340    msgs[1].addr = tpDevice->addr;
341    msgs[1].flags = (flag == 1)? I2C_FLAG_READ: 0; /* Add the read flag. */
342    msgs[1].len = dataLen;
343    msgs[1].buf = regData;
344
345    if (I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2) {
346        HDF_LOGE("%s: i2c read err", __func__);
347        return HDF_FAILURE;
348    }
349    return HDF_SUCCESS;
350}
351
352/* TP register read function */
353static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, unsigned int regAddr,
354    unsigned char *regData, unsigned int dataLen)
355{
356    return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 1);
357}
358
359/* TP register write function */
360static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, unsigned int regAddr,
361    unsigned char *regData, unsigned int dataLen)
362{
363    return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 0);
364}
365
366/* Main entry of I2C */
367static int32_t TestCaseI2c(void)
368{
369    int32_t i;
370    int32_t ret;
371    unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC };
372    unsigned char bufRead[7] = {0};
373    static struct TpI2cDevice tpDevice;
374
375    /* I/O pin function configuration */
376    TpSocIoCfg();
377
378    /* Initialize TP device information. */
379    tpDevice.rstGpio = 3;
380    tpDevice.busId = 3;
381    tpDevice.addr = 0x38;
382    tpDevice.regLen = 1;
383    tpDevice.i2cHandle = NULL;
384
385    /* Initialize the GPIO pin. */
386    ret = TestCaseGpioInit(&tpDevice);
387    if (ret != HDF_SUCCESS) {
388        HDF_LOGE("%s: gpio init fail!:%d", __func__, ret);
389        return ret;
390    }
391
392    /* Open an I2C controller. */
393    tpDevice.i2cHandle = I2cOpen(tpDevice.busId);
394    if (tpDevice.i2cHandle == NULL) {
395        HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId);
396        return -1;
397    }
398
399    /* Continuously write 7-byte data to register 0xD5 of TP-IC. */
400    ret = TpI2cWriteReg(&tpDevice, 0xD5, bufWrite, 7);
401    if (ret != HDF_SUCCESS) {
402        HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret);
403        I2cClose(tpDevice.i2cHandle);
404        return -1;
405    }
406    OsalMSleep(10);
407
408    /* Continuously read 7-byte data from register 0xDO of TP-IC. */
409    ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7);
410    if (ret != HDF_SUCCESS) {
411        HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret);
412        I2cClose(tpDevice.i2cHandle);
413        return -1;
414    }
415
416    HDF_LOGE("%s: tp i2c write&read reg success!", __func__);
417    for (i = 0; i < 7; i++) {
418        HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]);
419    }
420
421    /* Close the I2C controller. */
422    I2cClose(tpDevice.i2cHandle);
423    return ret;
424}
425```
426
427