1# GPIO 2 3## Overview 4 5### Function 6 7A general-purpose input/output (GPIO) controller manages all GPIO pins by group. Each group of GPIO pins is associated with one or more registers. The GPIO controller manages the pins by reading data from and writing data to the registers. 8 9The GPIO module provides APIs for performing operations on GPIO pins, including: 10 11- Setting the pin direction, which can be input or output (high impedance is not supported currently) 12- Reading and writing the pin level, which can be low or high 13- Setting an interrupt service routine (ISR) function and interrupt trigger mode for a pin 14- Enabling or disabling interrupts for a pin 15 16### Basic Concepts 17 18A GPIO can be used as an input, an output, or both, and is controllable by software. 19 20- GPIO input 21 22 When a GPIO is used as an input, it reads the level state (high or low) of each pin. Common input modes include analog input, floating input, pull-up input, and pull-down input. 23 24- GPIO output 25 26 When a GPIO is used as an output, it sets the pin level. Common output modes include open-drain output, push-pull output, multiplexed open-drain output, and multiplexed push-pull output. 27 28### Working Principles 29 30In the Hardware Driver Foundation (HDF), the GPIO module uses the unified service mode for API adaptation. In this mode, a device service is used as the GPIO manager to handle access requests from the devices of the same type in a unified manner. The unified service mode applies to the scenario where there are many device objects of the same type. If the independent service mode is used in this case, more device nodes need to be configured and more memory resources will be consumed. The following figure shows the unified service mode. 31 32In the unified service mode, the core layer manages all controllers in a unified manner and publishes a service for the interface layer. That is, the driver does not need to publish a service for each controller. 33 34The GPIO module is divided into the following layers: 35 36- Interface layer: provides APIs for operating GPIO pins. 37- Core layer: provides the capabilities of adding and removing the GPIO controller and managing GPIO pins. This layer interacts with the adaptation layer through hook functions to allow the GPIO chip drivers of different vendors to quickly access the HDF. 38- Adaptation layer: instantiates hook functions to implement specific features. 39 40**Figure 1** Unified service mode 41 42![](figures/unified-service-mode.png) 43 44## Usage Guidelines 45 46### When to Use 47 48As a concept at the software layer, GPIO is used to manage GPIO pin resources. You can use the GPIO APIs to control pins. 49 50### Available APIs 51 52The following table describes the APIs provided by the GPIO module. 53 54**Table 1** GPIO driver APIs 55 56| API | Description | 57| ------------------------------------------------------------ | ------------------------------ | 58| GpioGetByName(const char *gpioName) | Obtains the GPIO pin number. | 59| int32_t GpioRead(uint16_t gpio, uint16_t *val) | Reads the level of a GPIO pin. | 60| int32_t GpioWrite(uint16_t gpio, uint16_t val) | Writes the level of a GPIO pin. | 61| int32_t GpioGetDir(uint16_t gpio, uint16_t *dir) | Obtains the direction of a GPIO pin. | 62| int32_t GpioSetDir(uint16_t gpio, uint16_t dir) | Sets the direction for a GPIO pin. | 63| int32_t GpioUnsetIrq(uint16_t gpio, void *arg); | Cancels the ISR function for a GPIO pin. | 64| int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg) | Sets an ISR function for a GPIO pin. | 65| int32_t GpioEnableIrq(uint16_t gpio) | Enables interrupts for a GPIO pin. | 66| int32_t GpioDisableIrq(uint16_t gpio) | Disables interrupts for a GPIO pin. | 67 68>![](../public_sys-resources/icon-note.gif) **NOTE** 69> 70>All GPIO APIs described in this document can be used in kernel mode and user mode. 71 72### How to Develop 73 74The fillowing figure shows how to use the GPIO APIs to manage pins. In the APIs, a GPIO pin is identified by the pin number. 75 76**Figure 2** Using GPIO driver APIs 77 78![](figures/using-GPIO-process.png) 79 80#### Determining the GPIO Pin Number 81 82You can determine the GPIO pin number in either of the following ways: 83 84- Calculating the pin number based on the system on chip (SoC) 85 86 The method for determining the GPIO pin number varies depending on the GPIO controller model, parameters, and controller driver of the SoC. 87 88 - Hi3516D V300 89 90 A controller manages 12 groups of GPIO pins. Each group contains 8 GPIO pins. The group number ranges from 0 to 11. 91 92 GPIO pin number = GPIO group number x Number of GPIO pins in each group + Offset in the group 93 94 Example: 95 96 GPIO pin number of GPIO10_3 = 10 x 8 + 3 = 83 97 98 - Hi3518E V300 99 100 A controller manages 10 groups of GPIO pins. Each group contains 10 GPIO pins. The group number ranges from 0 to 9. 101 102 GPIO pin number = GPIO group number x Number of GPIO pins in each group + Offset in the group 103 104 Example: 105 106 GPIO pin number of GPIO7_3 = 7 x 10 + 3 = 73 107 108- Obtaining the pin number based on the pin alias 109 110 Use **GpioGetByName()** to obtain the pin number based on the pin alias. The global pin number is returned. 111 112 ```c 113 GpioGetByName(const char *gpioName); 114 ``` 115 116#### Setting the GPIO Pin Direction 117 118Before performing read/write operations on a GPIO pin, use **GpioSetDir()** to set the pin direction. 119 120```c 121int32_t GpioSetDir(uint16_t gpio, uint16_t dir); 122``` 123 124**Table 2** Description of GpioSetDir 125 126| **Parameter** | **Description** | 127| ---------- | ------------------ | 128| gpio | GPIO pin number.| 129| dir | Direction to set. | 130| **Return Value**| **Description** | 131| 0 | The operation is successful. | 132| Negative value | The operation failed. | 133 134Example: Set the direction of GPIO pin 3 to output. 135 136```c 137int32_t ret; 138 139ret = GpioSetDir(3, GPIO_DIR_OUT); // Set GPIO pin 3 as an output. 140if (ret != 0) { 141 HDF_LOGE("GpioSetDir: failed, ret %d\n", ret); 142 return ret; 143} 144``` 145 146#### Obtaining the GPIO Pin Direction 147 148Use **GpioGetDir()** to obtain the GPIO pin direction. 149 150```c 151int32_t GpioGetDir(uint16_t gpio, uint16_t *dir); 152``` 153 154**Table 3** Description of GpioGetDir 155 156| **Parameter** | **Description** | 157| ---------- | ------------------ | 158| gpio | GPIO pin number.| 159| dir | Pointer to the direction value obtained. | 160| **Return Value**| **Description** | 161| 0 | The operation is successful. | 162| Negative value | The operation failed. | 163 164Example: Obtain the direction of GPIO pin 3. 165 166```c 167int32_t ret; 168uin16_t dir; 169 170ret = GpioGetDir(3, &dir); // Obtain the direction of GPIO pin 3. 171if (ret != 0) { 172 HDF_LOGE("GpioGetDir: failed, ret %d\n", ret); 173 return ret; 174} 175``` 176 177#### Reading the GPIO Pin Level 178 179Use **GpioRead()** to read the level of a GPIO pin. 180 181```c 182int32_t GpioRead(uint16_t gpio, uint16_t *val); 183``` 184 185**Table 4** Description of GpioRead 186 187| **Parameter** | **Description** | 188| ---------- | -------------------- | 189| gpio | GPIO pin number. | 190| val | Pointer to the level value read. | 191| **Return Value**| **Description** | 192| 0 | The operation is successful. | 193| Negative value | The operation failed. | 194 195Example: Read the level of GPIO pin 3. 196 197```c 198int32_t ret; 199uint16_t val; 200 201ret = GpioRead(3, &val); // Read the level of GPIO pin 3. 202if (ret != 0) { 203 HDF_LOGE("GpioRead: failed, ret %d\n", ret); 204 return ret; 205} 206``` 207 208#### Writing the GPIO Pin Level 209 210Use **GpioWrite()** to write the level for a GPIO pin. 211 212```c 213int32_t GpioWrite(uint16_t gpio, uint16_t val); 214``` 215 216**Table 5** Description of GpioWrite 217 218| **Parameter** | **Description** | 219| ---------- | ------------------ | 220| gpio | GPIO pin number.| 221| val | Level to write. | 222| **Return Value**| **Description** | 223| 0 | The operation is successful. | 224| Negative value | The operation failed. | 225 226Example: Write a low level value to the register of GPIO pin 3. 227 228```c 229int32_t ret; 230 231ret = GpioWrite(3, GPIO_VAL_LOW); // Write a low level value to the register of GPIO pin 3. 232if (ret != 0) { 233 HDF_LOGE("GpioRead: failed, ret %d\n", ret); 234 return ret; 235} 236``` 237 238#### Setting an ISR Function for a GPIO Pin 239 240Use **GpioSetIrq()** to set an ISR function for a GPIO pin. 241 242```c 243int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg); 244``` 245 246**Table 6** Description of GpioSetIrq 247 248| **Parameter** | **Description** | 249| ---------- | ------------------------ | 250| gpio | GPIO pin number. | 251| mode | Interrupt trigger mode. | 252| func | ISR function to set. | 253| arg | Pointer to the parameters passed to the ISR function.| 254| **Return Value**| **Description** | 255| 0 | The operation is successful. | 256| Negative value | The operation failed. | 257 258> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**<br/> 259> Only one ISR function can be set for a GPIO pin. If **GpioSetIrq** is called repeatedly, the previous IRS function will be replaced. 260 261#### Canceling the ISR Function for a GPIO Pin 262 263If the ISR function is no longer required, call **GpioUnsetIrq()** to cancel it. 264 265```c 266int32_t GpioUnsetIrq(uint16_t gpio, void *arg); 267``` 268 269**Table 7** Description of GpioUnsetIrq 270 271| **Parameter** | **Description** | 272| ---------- | -------------- | 273| gpio | GPIO pin number. | 274| arg | Pointer to the GPIO interrupt parameters. | 275| **Return Value**| **Description**| 276| 0 | The operation is successful. | 277| Negative value | The operation failed. | 278 279#### Enabling Interrupts for a GPIO Pin 280 281After the ISR function is set, call **GpioEnableIrq()** to enable interrupts for the GPIO pin. 282 283```c 284int32_t GpioEnableIrq(uint16_t gpio); 285``` 286 287**Table 8** Description of GpioEnableIrq 288 289| **Parameter** | **Description** | 290| ---------- | -------------- | 291| gpio | GPIO pin number. | 292| **Return Value**| **Description**| 293| 0 | The operation is successful. | 294| Negative value | The operation failed. | 295 296> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**<br/> 297> The configured ISR function can be responded only after interrupts are enabled for the GPIO pin. 298 299#### Disabling Interrupts for a GPIO Pin 300 301Use **GpioDisableIrq()** to disable interrupts for a pin. 302 303```c 304int32_t GpioDisableIrq(uint16_t gpio); 305``` 306**Table 9** Description of GpioDisableIrq 307 308| **Parameter** | **Description** | 309| ---------- | -------------- | 310| gpio | GPIO pin number. | 311| **Return Value**| **Description**| 312| 0 | The operation is successful. | 313| Negative value | The operation failed. | 314 315Example: 316 317```c 318/* Set an ISR function. */ 319int32_t MyCallBackFunc(uint16_t gpio, void *data) 320{ 321 HDF_LOGI("%s: gpio:%u interrupt service in data\n", __func__, gpio); 322 return 0; 323} 324 325int32_t ret; 326/* Set the ISR function to MyCallBackFunc, with input parameter of NULL and the interrupt trigger mode of rising edge. */ 327ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL); 328if (ret != 0) { 329 HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret); 330 return ret; 331} 332 333/* Enable interrupts for GPIO pin 3. */ 334ret = GpioEnableIrq(3); 335if (ret != 0) { 336 HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret); 337 return ret; 338} 339 340/* Disable interrupts for GPIO pin 3. */ 341ret = GpioDisableIrq(3); 342if (ret != 0) { 343 HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret); 344 return ret; 345} 346 347/* Cancel the ISR function for GPIO pin 3. */ 348ret = GpioUnsetIrq(3, NULL); 349if (ret != 0) { 350 HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret); 351 return ret; 352} 353``` 354 355## Example 356 357The following example shows how to trigger an interrupt for a GPIO pin. The procedure is as follows: 358 3591. Select an idle GPIO pin, for example, pin GPIO10_3 on a Hi3516D V300 development board. The pin number of GPIO10_3 is 83. You can select an idle GPIO pin as required. 3602. Set an ISR function for the pin, with the interrupt trigger mode of rising edge and falling edge. 3613. Write high and low levels to the pin alternately, and observe the execution of the ISR function. 362 363Sample code: 364 365```c 366#include "gpio_if.h" 367#include "hdf_log.h" 368#include "osal_irq.h" 369#include "osal_time.h" 370 371static uint32_t g_irqCnt; 372 373/* ISR function */ 374static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data) 375{ 376 HDF_LOGE("%s: irq triggered! on gpio:%u, in data", __func__, gpio); 377 g_irqCnt++; /* If the ISR function is triggered, the global interrupt counter is incremented by 1. */ 378 return GpioDisableIrq(gpio); 379} 380 381/* Test case function */ 382static int32_t TestCaseGpioIrqEdge(void) 383{ 384 int32_t ret; 385 uint16_t valRead; 386 uint16_t mode; 387 uint16_t gpio = 83; /* Number of the GPIO pin to test */ 388 uint32_t timeout; 389 390 /* Set the pin direction to output. */ 391 ret = GpioSetDir(gpio, GPIO_DIR_OUT); 392 if (ret != HDF_SUCCESS) { 393 HDF_LOGE("%s: set dir fail! ret:%d\n", __func__, ret); 394 return ret; 395 } 396 397 /* Disable interrupts of the pin. */ 398 ret = GpioDisableIrq(gpio); 399 if (ret != HDF_SUCCESS) { 400 HDF_LOGE("%s: disable irq fail! ret:%d\n", __func__, ret); 401 return ret; 402 } 403 404 /* Set the ISR function for the pin. The trigger mode is both rising edge and falling edge. */ 405 mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING; 406 HDF_LOGE("%s: mode:%0x\n", __func__, mode); 407 ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL); 408 if (ret != HDF_SUCCESS) { 409 HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret); 410 return ret; 411 } 412 413 /* Enable interrupts for the pin. */ 414 ret = GpioEnableIrq(gpio); 415 if (ret != HDF_SUCCESS) { 416 HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret); 417 (void)GpioUnsetIrq(gpio, NULL); 418 return ret; 419 } 420 421 g_irqCnt = 0; /* Reset the global interrupt counter. */ 422 timeout = 0; /* Clear the waiting time. */ 423 /* Wait for the ISR function to trigger for this pin. The timeout duration is 1000 ms. */ 424 while (g_irqCnt <= 0 && timeout < 1000) { 425 (void)GpioRead(gpio, &valRead); 426 (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW); 427 HDF_LOGE("%s: wait irq timeout:%u\n", __func__, timeout); 428 OsalMDelay(200); /* wait for irq trigger */ 429 timeout += 200; 430 } 431 (void)GpioUnsetIrq(gpio, NULL); 432 return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; 433} 434``` 435