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  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> **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 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> **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> **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