• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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