提交 1b9b66bc 编写于 作者: A Annie_wang

update docs

Signed-off-by: NAnnie_wang <annie.wangli@huawei.com>
上级 136a6a3f
# GPIO<a name="EN-US_TOPIC_0000001206171135"></a>
# GPIO
## Overview<a name="section1635911016188"></a>
## Overview
Generally, a 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 pins are operated by reading data from and writing data to the registers.
A 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.
The GPIO APIs define a set of standard functions for performing operations on GPIO pins, including:
- Setting the pin direction, which can be input or output \(high impedance is not supported currently\)
- Reading and writing level values, which can be low or high
- Setting an interrupt service routine \(ISR\) function and interrupt trigger mode for a pin
- Enabling or disabling interrupts for a pin
## Available APIs<a name="section589913442203"></a>
**Table 1** APIs available for the GPIO driver
<a name="table89681075215"></a>
<table><thead align="left"><tr id="row996807162115"><th class="cellrowborder" valign="top" width="19.74%" id="mcps1.2.4.1.1"><p id="p296817716212"><a name="p296817716212"></a><a name="p296817716212"></a>Capability</p>
</th>
<th class="cellrowborder" valign="top" width="32.36%" id="mcps1.2.4.1.2"><p id="p596897172119"><a name="p596897172119"></a><a name="p596897172119"></a>Function</p>
</th>
<th class="cellrowborder" valign="top" width="47.9%" id="mcps1.2.4.1.3"><p id="p39681677213"><a name="p39681677213"></a><a name="p39681677213"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row896847202113"><td class="cellrowborder" rowspan="2" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p1796814719210"><a name="p1796814719210"></a><a name="p1796814719210"></a>GPIO read/write</p>
</td>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p39683732112"><a name="p39683732112"></a><a name="p39683732112"></a>GpioRead</p>
</td>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p59687710219"><a name="p59687710219"></a><a name="p59687710219"></a>Reads the level value of a GPIO pin.</p>
</td>
</tr>
<tr id="row17968872212"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p396812722116"><a name="p396812722116"></a><a name="p396812722116"></a>GpioWrite</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p396814715219"><a name="p396814715219"></a><a name="p396814715219"></a>Writes the level value of a GPIO pin.</p>
</td>
</tr>
<tr id="row129681576218"><td class="cellrowborder" rowspan="2" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p1496813782116"><a name="p1496813782116"></a><a name="p1496813782116"></a>GPIO settings</p>
</td>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p29688742119"><a name="p29688742119"></a><a name="p29688742119"></a>GpioSetDir</p>
</td>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p179682792111"><a name="p179682792111"></a><a name="p179682792111"></a>Sets the direction for a GPIO pin.</p>
</td>
</tr>
<tr id="row1196817715217"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p896827182120"><a name="p896827182120"></a><a name="p896827182120"></a>GpioGetDir</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p39689792111"><a name="p39689792111"></a><a name="p39689792111"></a>Obtains the direction for a GPIO pin.</p>
</td>
</tr>
<tr id="row69682071217"><td class="cellrowborder" rowspan="4" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p296818714213"><a name="p296818714213"></a><a name="p296818714213"></a>GPIO interrupt settings</p>
</td>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p1396916710216"><a name="p1396916710216"></a><a name="p1396916710216"></a>GpioSetIrq</p>
</td>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p99693712113"><a name="p99693712113"></a><a name="p99693712113"></a>Sets the ISR function for a GPIO pin.</p>
</td>
</tr>
<tr id="row4969117172110"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p119692079215"><a name="p119692079215"></a><a name="p119692079215"></a>GpioUnSetIrq</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1996916792114"><a name="p1996916792114"></a><a name="p1996916792114"></a>Cancels the setting of the ISR function for a GPIO pin.</p>
</td>
</tr>
<tr id="row396907112117"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p109694717216"><a name="p109694717216"></a><a name="p109694717216"></a>GpioEnableIrq</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p2969473216"><a name="p2969473216"></a><a name="p2969473216"></a>Enables GPIO interrupts for a pin.</p>
</td>
</tr>
<tr id="row14969117152113"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p18969157182116"><a name="p18969157182116"></a><a name="p18969157182116"></a>GpioDisableIrq</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p19690710214"><a name="p19690710214"></a><a name="p19690710214"></a>Disables GPIO interrupts for a pin.</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **NOTE**<br>
>All functions provided in this document can be called only in kernel mode.
## Usage Guidelines<a name="section259614242196"></a>
### How to Use<a name="section103477714216"></a>
The GPIO APIs use the GPIO pin number to specify a pin. The figure below illustrates how to use the APIs.
- Setting the pin direction, which can be input or output (high impedance is not supported currently)
- Reading and writing the pin level, which can be low or high
- Setting the interrupt service routine (ISR) function and interrupt trigger mode for a pin
- Enabling or disabling interrupts for a pin
## Available APIs
**Table 1** GPIO driver APIs
| Category| Description|
| -------- | -------- |
| GPIO read/write| -&nbsp;**GpioRead**: reads the pin level.<br>-&nbsp;**GpioWrite**: writes the pin level.|
| GPIO settings| -&nbsp;**GpioSetDir**: sets the pin direction.<br>-&nbsp;**GpioGetDir**: obtains the pin direction.|
| GPIO interrupt settings| -&nbsp;**GpioSetIrq**: sets the ISR function for a GPIO pin.<br>-&nbsp;**GpioUnsetIrq**: cancels the ISR function setting for a GPIO pin.<br>-&nbsp;**GpioEnableIrq**: enables interrupts for a pin.<br>-&nbsp;**GpioDisableIrq**: disables interrupts for a pin.|
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/>
> All APIs described in this document can be called only in kernel mode.
## Usage Guidelines
### How to Use
The figure below shows the general GPIO development process. In the APIs, a GPIO pin is specified by the pin number.
**Figure 1** Using GPIO driver APIs
![](figures/using-gpio-process.png "using-gpio-process.png")
### Determining the GPIO Pin Number<a name="section370083272117"></a>
![](figures/using-gpio-process.png "using-gpio-process.png")
The method for converting GPIO pin numbers varies depending on the GPIO controller model, parameters, and controller driver of different system on chips \(SoCs\).
- Hi3516DV300
### Determining the GPIO Pin Number
A controller manages 12 groups of GPIO pins. Each group contains 8 GPIO pins.
The method for determining the GPIO pin number varies depending on the GPIO controller model, parameters, and controller driver of the system on chip (SoC).
GPIO pin number = GPIO group index x Number of GPIO pins in each group + Offset in the group
- Hi3516D V300
A controller manages 12 groups of GPIO pins. Each group contains 8 GPIO pins. The group number ranges from 0 to 11.
The group index ranges from 0 to 11.
GPIO pin number = GPIO group number x Number of GPIO pins in each group + Offset in the group
Example:
GPIO pin number of GPIO10\_3 = 10 x 8 + 3 = 83
- Hi3518EV300
A controller manages 10 groups of GPIO pins. Each group contains 10 GPIO pins.
GPIO pin number = GPIO group index \(0–9\) x Number of GPIO pins in each group \(10\) + Offset in the group
The group index ranges from 0 to 9.
Example:
GPIO pin number of GPIO7\_3 = 7 x 10 + 3 = 73
### Using APIs to Operate GPIO Pins<a name="section13604050132118"></a>
- Set the direction for a GPIO pin.
Before performing read/write operations on a GPIO pin, call **GpioSetDir**() to set the direction.
int32\_t GpioSetDir\(uint16\_t gpio, uint16\_t dir\);
**Table 2** Description of GpioSetDir
<a name="table63111557616"></a>
<table><tbody><tr id="row17311165469"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p53110515616"><a name="p53110515616"></a><a name="p53110515616"></a><strong id="b1142022718160"><a name="b1142022718160"></a><a name="b1142022718160"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p5311454616"><a name="p5311454616"></a><a name="p5311454616"></a><strong id="b93161228141614"><a name="b93161228141614"></a><a name="b93161228141614"></a>Description</strong></p>
</td>
</tr>
<tr id="row0312151666"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p1431265763"><a name="p1431265763"></a><a name="p1431265763"></a>gpio</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p83121553613"><a name="p83121553613"></a><a name="p83121553613"></a>GPIO pin number.</p>
</td>
</tr>
<tr id="row11312151619"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p173121451664"><a name="p173121451664"></a><a name="p173121451664"></a>dir</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p153122520615"><a name="p153122520615"></a><a name="p153122520615"></a>Direction to set.</p>
</td>
</tr>
<tr id="row165937126386"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p83111453613"><a name="p83111453613"></a><a name="p83111453613"></a><strong id="b42491732121614"><a name="b42491732121614"></a><a name="b42491732121614"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p83111151165"><a name="p83111151165"></a><a name="p83111151165"></a><strong id="b1116336166"><a name="b1116336166"></a><a name="b1116336166"></a>Description</strong></p>
</td>
</tr>
<tr id="row205931212123817"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p18312151463"><a name="p18312151463"></a><a name="p18312151463"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p103124517618"><a name="p103124517618"></a><a name="p103124517618"></a>The operation is successful.</p>
</td>
</tr>
<tr id="row75931212153818"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p23121951261"><a name="p23121951261"></a><a name="p23121951261"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p153121553610"><a name="p153121553610"></a><a name="p153121553610"></a>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
- Read or write the level value for a GPIO pin.
Call **GpioRead**() to read the level value of a GPIO pin.
int32\_t GpioRead\(uint16\_t gpio, uint16\_t \*val\);
**Table 3** Description of GpioRead
<a name="table20347743174816"></a>
<table><tbody><tr id="row17348144394816"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p19348164313481"><a name="p19348164313481"></a><a name="p19348164313481"></a><strong id="b4862227121610"><a name="b4862227121610"></a><a name="b4862227121610"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p134810432488"><a name="p134810432488"></a><a name="p134810432488"></a><strong id="b677332841611"><a name="b677332841611"></a><a name="b677332841611"></a>Description</strong></p>
</td>
</tr>
<tr id="row134874324814"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p183481437485"><a name="p183481437485"></a><a name="p183481437485"></a>gpio</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p43481043194819"><a name="p43481043194819"></a><a name="p43481043194819"></a>GPIO pin number.</p>
</td>
</tr>
<tr id="row20348343144815"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p1534864310480"><a name="p1534864310480"></a><a name="p1534864310480"></a>val</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p13689159154815"><a name="p13689159154815"></a><a name="p13689159154815"></a>Pointer to the level value.</p>
</td>
</tr>
<tr id="row19348043154813"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p1234812431480"><a name="p1234812431480"></a><a name="p1234812431480"></a><strong id="b10599632101619"><a name="b10599632101619"></a><a name="b10599632101619"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p434894334814"><a name="p434894334814"></a><a name="p434894334814"></a><strong id="b236513361617"><a name="b236513361617"></a><a name="b236513361617"></a>Description</strong></p>
</td>
</tr>
<tr id="row3348184311486"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p1934854315487"><a name="p1934854315487"></a><a name="p1934854315487"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p103481943114814"><a name="p103481943114814"></a><a name="p103481943114814"></a>The operation is successful.</p>
</td>
</tr>
<tr id="row23485436482"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p1134834310486"><a name="p1134834310486"></a><a name="p1134834310486"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p93491343144815"><a name="p93491343144815"></a><a name="p93491343144815"></a>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
Call **GpioWrite()** to write the level value for a GPIO pin.
int32\_t GpioWrite\(uint16\_t gpio, uint16\_t val\);
**Table 4** Description of GpioWrite
<a name="table1214911207520"></a>
<table><tbody><tr id="row6149720175218"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p18149132005216"><a name="p18149132005216"></a><a name="p18149132005216"></a><strong id="b19864427181615"><a name="b19864427181615"></a><a name="b19864427181615"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p16149220145216"><a name="p16149220145216"></a><a name="p16149220145216"></a><strong id="b4774132861616"><a name="b4774132861616"></a><a name="b4774132861616"></a>Description</strong></p>
</td>
</tr>
<tr id="row16149102014526"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p31495206527"><a name="p31495206527"></a><a name="p31495206527"></a>gpio</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p1014972085212"><a name="p1014972085212"></a><a name="p1014972085212"></a>GPIO pin number.</p>
</td>
</tr>
<tr id="row3149112095214"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p1815072011528"><a name="p1815072011528"></a><a name="p1815072011528"></a>val</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p1931618337524"><a name="p1931618337524"></a><a name="p1931618337524"></a>Level value to write.</p>
</td>
</tr>
<tr id="row1115062015220"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p10150172015218"><a name="p10150172015218"></a><a name="p10150172015218"></a><strong id="b760183221611"><a name="b760183221611"></a><a name="b760183221611"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p1150192015527"><a name="p1150192015527"></a><a name="p1150192015527"></a><strong id="b14366123310160"><a name="b14366123310160"></a><a name="b14366123310160"></a>Description</strong></p>
</td>
</tr>
<tr id="row111503202526"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p171501320205216"><a name="p171501320205216"></a><a name="p171501320205216"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p15150102017522"><a name="p15150102017522"></a><a name="p15150102017522"></a>The operation is successful.</p>
</td>
</tr>
<tr id="row1615002018528"><td class="cellrowborder" valign="top" width="48.120000000000005%"><p id="p15150182045212"><a name="p15150182045212"></a><a name="p15150182045212"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p13150320105212"><a name="p13150320105212"></a><a name="p13150320105212"></a>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
Example:
```
int32_t ret;
uint16_t val;
/* Set the output direction for GPIO3. */
ret = GpioSetDir(3, GPIO_DIR_OUT);
if (ret != 0) {
HDF_LOGE("GpioSerDir: failed, ret %d\n", ret);
return;
}
/* Write the low level GPIO_VAL_LOW for GPIO3. */
ret = GpioWrite(3, GPIO_VAL_LOW);
if (ret != 0) {
HDF_LOGE("GpioWrite: failed, ret %d\n", ret);
return;
}
/* Set the input direction for GPIO6. */
ret = GpioSetDir(6, GPIO_DIR_IN);
if (ret != 0) {
HDF_LOGE("GpioSetDir: failed, ret %d\n", ret);
return;
}
/* Read the level value of GPIO6. */
ret = GpioRead(6, &val);
```
- Set the ISR function for a GPIO pin.
Call **GpioSetIrq()** to set the ISR function for a GPIO pin.
int32\_t GpioSetIrq\(uint16\_t gpio, uint16\_t mode, GpioIrqFunc func, void \*arg\);
**Table 5** Description of GpioSetIrq
<a name="table16804111812466"></a>
<table><tbody><tr id="row880401834615"><td class="cellrowborder" valign="top" width="48.54%"><p id="p380491819469"><a name="p380491819469"></a><a name="p380491819469"></a><strong id="b0865192761614"><a name="b0865192761614"></a><a name="b0865192761614"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p48041318114619"><a name="p48041318114619"></a><a name="p48041318114619"></a><strong id="b1477520282162"><a name="b1477520282162"></a><a name="b1477520282162"></a>Description</strong></p>
</td>
</tr>
<tr id="row19805181812465"><td class="cellrowborder" valign="top" width="48.54%"><p id="p11805101874611"><a name="p11805101874611"></a><a name="p11805101874611"></a>gpio</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p6805181818461"><a name="p6805181818461"></a><a name="p6805181818461"></a>GPIO pin number.</p>
</td>
</tr>
<tr id="row1080541817469"><td class="cellrowborder" valign="top" width="48.54%"><p id="p580541864611"><a name="p580541864611"></a><a name="p580541864611"></a>mode</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p380511180463"><a name="p380511180463"></a><a name="p380511180463"></a>Interrupt trigger mode.</p>
</td>
</tr>
<tr id="row83541951134617"><td class="cellrowborder" valign="top" width="48.54%"><p id="p5355351104610"><a name="p5355351104610"></a><a name="p5355351104610"></a>func</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p11355551174619"><a name="p11355551174619"></a><a name="p11355551174619"></a>ISR function to set.</p>
</td>
</tr>
<tr id="row6593577469"><td class="cellrowborder" valign="top" width="48.54%"><p id="p165985724619"><a name="p165985724619"></a><a name="p165985724619"></a>arg</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p559185784619"><a name="p559185784619"></a><a name="p559185784619"></a>Pointer to the parameters passed to the ISR function.</p>
</td>
</tr>
<tr id="row16299193210587"><td class="cellrowborder" valign="top" width="48.54%"><p id="p7804101884614"><a name="p7804101884614"></a><a name="p7804101884614"></a><strong id="b126021932131615"><a name="b126021932131615"></a><a name="b126021932131615"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p680441818466"><a name="p680441818466"></a><a name="p680441818466"></a><strong id="b836716339162"><a name="b836716339162"></a><a name="b836716339162"></a>Description</strong></p>
</td>
</tr>
<tr id="row12299632125817"><td class="cellrowborder" valign="top" width="48.54%"><p id="p1180511189465"><a name="p1180511189465"></a><a name="p1180511189465"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p180521812465"><a name="p180521812465"></a><a name="p180521812465"></a>The operation is successful.</p>
</td>
</tr>
<tr id="row029833235815"><td class="cellrowborder" valign="top" width="48.54%"><p id="p1080591814468"><a name="p1080591814468"></a><a name="p1080591814468"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p18805141884611"><a name="p18805141884611"></a><a name="p18805141884611"></a>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-caution.gif) **CAUTION**<br/>
>Only one ISR function can be set for a GPIO pin at a time. If **GpioSetIrq** is called repeatedly, the previous IRS function will be replaced.
If the ISR function is no longer required, call **GpioUnSetIrq()** to cancel the setting.
int32\_t GpioUnSetIrq\(uint16\_t gpio\);
**Table 6** Description of GpioUnSetIrq
<a name="table1157224664316"></a>
<table><tbody><tr id="row175721546174317"><td class="cellrowborder" valign="top" width="48.54%"><p id="p16572144694311"><a name="p16572144694311"></a><a name="p16572144694311"></a><strong id="b16866132761617"><a name="b16866132761617"></a><a name="b16866132761617"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p185721461435"><a name="p185721461435"></a><a name="p185721461435"></a><strong id="b1377613282167"><a name="b1377613282167"></a><a name="b1377613282167"></a>Description</strong></p>
</td>
</tr>
<tr id="row1257284664318"><td class="cellrowborder" valign="top" width="48.54%"><p id="p95721946144317"><a name="p95721946144317"></a><a name="p95721946144317"></a>gpio</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p1557313464439"><a name="p1557313464439"></a><a name="p1557313464439"></a>GPIO pin number.</p>
</td>
</tr>
<tr id="row1857324618435"><td class="cellrowborder" valign="top" width="48.54%"><p id="p1257344624314"><a name="p1257344624314"></a><a name="p1257344624314"></a><strong id="b1160353241610"><a name="b1160353241610"></a><a name="b1160353241610"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p457384611439"><a name="p457384611439"></a><a name="p457384611439"></a><strong id="b133681833151617"><a name="b133681833151617"></a><a name="b133681833151617"></a>Description</strong></p>
</td>
</tr>
<tr id="row357318466439"><td class="cellrowborder" valign="top" width="48.54%"><p id="p1573164616438"><a name="p1573164616438"></a><a name="p1573164616438"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p857384614319"><a name="p857384614319"></a><a name="p857384614319"></a>The operation is successful.</p>
</td>
</tr>
<tr id="row18573124610433"><td class="cellrowborder" valign="top" width="48.54%"><p id="p165731146134311"><a name="p165731146134311"></a><a name="p165731146134311"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p6573164613437"><a name="p6573164613437"></a><a name="p6573164613437"></a>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
After the ISR function is set, call **GpioEnableIrq()** to enable interrupts.
int32\_t GpioEnableIrq\(uint16\_t gpio\);
**Table 7** Description of GpioEnableIrq
<a name="table26659291568"></a>
<table><tbody><tr id="row866632919566"><td class="cellrowborder" valign="top" width="50%"><p id="p066642985615"><a name="p066642985615"></a><a name="p066642985615"></a><strong id="b108661927171614"><a name="b108661927171614"></a><a name="b108661927171614"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p566613293568"><a name="p566613293568"></a><a name="p566613293568"></a><strong id="b10777228121617"><a name="b10777228121617"></a><a name="b10777228121617"></a>Description</strong></p>
</td>
</tr>
<tr id="row19666029165620"><td class="cellrowborder" valign="top" width="50%"><p id="p16660295566"><a name="p16660295566"></a><a name="p16660295566"></a>gpio</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1566632916566"><a name="p1566632916566"></a><a name="p1566632916566"></a>GPIO pin number.</p>
</td>
</tr>
<tr id="row84182176010"><td class="cellrowborder" valign="top" width="50%"><p id="p1566652915566"><a name="p1566652915566"></a><a name="p1566652915566"></a><strong id="b160443201612"><a name="b160443201612"></a><a name="b160443201612"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p966642917562"><a name="p966642917562"></a><a name="p966642917562"></a><strong id="b12369193319162"><a name="b12369193319162"></a><a name="b12369193319162"></a>Description</strong></p>
</td>
</tr>
<tr id="row154188171403"><td class="cellrowborder" valign="top" width="50%"><p id="p1866610292563"><a name="p1866610292563"></a><a name="p1866610292563"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p13666182975613"><a name="p13666182975613"></a><a name="p13666182975613"></a>The operation is successful.</p>
</td>
</tr>
<tr id="row1041891720012"><td class="cellrowborder" valign="top" width="50%"><p id="p766642911562"><a name="p766642911562"></a><a name="p766642911562"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1566652995613"><a name="p1566652995613"></a><a name="p1566652995613"></a>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-caution.gif) **CAUTION**<br/>
>The configured ISR function can be responded only after the GPIO interrupt is enabled.
Call **GpioDisableIrq()** to disable interrupts.
int32\_t GpioDisableIrq\(uint16\_t gpio\);
**Table 8** Description of GpioDisableIrq
<a name="table186682041918"></a>
<table><tbody><tr id="row186684413116"><td class="cellrowborder" valign="top" width="50%"><p id="p866844916"><a name="p866844916"></a><a name="p866844916"></a><strong id="b88678273169"><a name="b88678273169"></a><a name="b88678273169"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p46681413119"><a name="p46681413119"></a><a name="p46681413119"></a><strong id="b2077772812169"><a name="b2077772812169"></a><a name="b2077772812169"></a>Description</strong></p>
</td>
</tr>
<tr id="row4668243113"><td class="cellrowborder" valign="top" width="50%"><p id="p46681141919"><a name="p46681141919"></a><a name="p46681141919"></a>gpio</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p136681241311"><a name="p136681241311"></a><a name="p136681241311"></a>GPIO pin number.</p>
</td>
</tr>
<tr id="row066884412"><td class="cellrowborder" valign="top" width="50%"><p id="p566824015"><a name="p566824015"></a><a name="p566824015"></a><strong id="b16605123251612"><a name="b16605123251612"></a><a name="b16605123251612"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1766974515"><a name="p1766974515"></a><a name="p1766974515"></a><strong id="b1237063341617"><a name="b1237063341617"></a><a name="b1237063341617"></a>Description</strong></p>
</td>
</tr>
<tr id="row156694410112"><td class="cellrowborder" valign="top" width="50%"><p id="p14669141214"><a name="p14669141214"></a><a name="p14669141214"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1266934818"><a name="p1266934818"></a><a name="p1266934818"></a>The operation is successful.</p>
</td>
</tr>
<tr id="row176691543117"><td class="cellrowborder" valign="top" width="50%"><p id="p7669941716"><a name="p7669941716"></a><a name="p7669941716"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p4669164219"><a name="p4669164219"></a><a name="p4669164219"></a>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
Example:
```
/* ISR function */
*/
int32_t MyCallBackFunc(uint16_t gpio, void *data)
{
HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", __func__, gpio, data);
return 0;
}
int32_t ret;
/* Set the ISR function to MyCallBackFunc, the parameter to NULL, and the interrupt trigger mode to rising edge. */
ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL);
if (ret != 0) {
HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret);
return;
}
/* Enable an interrupt for GPIO3. */
ret = GpioEnableIrq(3);
if (ret != 0) {
HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret);
return;
}
/* Disable the interrupt for GPIO3. */
ret = GpioDisableIrq(3);
if (ret != 0) {
HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret);
return;
}
/* Cancel the ISR function for GPIO3. */
ret = GpioUnSetIrq(3);
if (ret != 0) {
HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret);
return;
}
```
GPIO pin number of GPIO10_3 = 10 x 8 + 3 = 83
- Hi3518E V300
A controller manages 10 groups of GPIO pins. Each group contains 10 GPIO pins. The group number ranges from 0 to 9.
GPIO pin number = GPIO group number x Number of GPIO pins in each group + Offset in the group
## Usage Example<a name="section25941262111"></a>
Example:
GPIO pin number of GPIO7_3 = 7 x 10 + 3 = 73
### Using APIs to Operate GPIO Pins
- Set the GPIO pin direction.
Before performing read/write operations on a GPIO pin, call **GpioSetDir()** to set the pin direction.
int32_t GpioSetDir(uint16_t gpio, uint16_t dir);
**Table 2** Description of GpioSetDir
| **Parameter**| **Description**|
| -------- | -------- |
| gpio | GPIO pin number.|
| dir | Direction to set.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
- Read or write the pin level.
Call **GpioRead()** to read the level of a GPIO pin.
int32_t GpioRead(uint16_t gpio, uint16_t \*val);
**Table 3** Description of GpioRead
| **Parameter**| **Description**|
| -------- | -------- |
| gpio | GPIO pin number.|
| val | Pointer to the level to read.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Call **GpioWrite()** to write the level for a GPIO pin.
int32_t GpioWrite(uint16_t gpio, uint16_t val);
**Table 4** Description of GpioWrite
| **Parameter**| **Description**|
| -------- | -------- |
| gpio | GPIO pin number.|
| val | Level to write.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Sample code:
```
int32_t ret;
uint16_t val;
/* Set the direction of GPIO pin 3 to output. */
ret = GpioSetDir(3, GPIO_DIR_OUT);
if (ret != 0) {
HDF_LOGE("GpioSerDir: failed, ret %d\n", ret);
return;
}
/* Write the low level GPIO_VAL_LOW for GPIO pin 3. */
ret = GpioWrite(3, GPIO_VAL_LOW);
if (ret != 0) {
HDF_LOGE("GpioWrite: failed, ret %d\n", ret);
return;
}
/* Set the direction of GPIO pin 6 to input. */
ret = GpioSetDir(6, GPIO_DIR_IN);
if (ret != 0) {
HDF_LOGE("GpioSetDir: failed, ret %d\n", ret);
return;
}
/* Read the level of GPIO pin 6. */
ret = GpioRead(6, &val);
```
- Set the ISR function for a GPIO pin.
Call **GpioSetIrq()** to set the ISR function for a GPIO pin.
int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void \*arg);
**Table 5** Description of GpioSetIrq
| **Parameter**| **Description**|
| -------- | -------- |
| gpio | GPIO pin number.|
| mode | Interrupt trigger mode.|
| func | ISR function to set.|
| arg | Pointer to the parameters passed to the ISR function.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
> ![icon-caution.gif](/public_sys-resources/icon-caution.gif) **CAUTION**<br/>
> Only one ISR function can be set for a GPIO pin. If **GpioSetIrq** is called repeatedly, the previous IRS function will be replaced.
If the ISR function is no longer required, call **GpioUnsetIrq()** to cancel it.
int32_t GpioUnsetIrq(uint16_t gpio, void \*arg);
**Table 6** Description of GpioUnsetIrq
| **Parameter**| **Description**|
| -------- | -------- |
| gpio | GPIO pin number.|
| arg | Pointer to the GPIO interrupt parameters.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
After the ISR function is set, call **GpioEnableIrq()** to enable interrupts for the GPIO pin.
int32_t GpioEnableIrq(uint16_t gpio);
**Table 7** Description of GpioEnableIrq
| **Parameter**| **Description**|
| -------- | -------- |
| gpio | GPIO pin number.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
> ![icon-caution.gif](/public_sys-resources/icon-caution.gif) **CAUTION**<br/>
> The configured ISR function can be responded only after interrupts are enabled for the GPIO pin.
You can call **GpioDisableIrq** to disable interrupts for the pin.
int32_t GpioDisableIrq(uint16_t gpio);
**Table 8** Description of GpioDisableIrq
| **Parameter**| **Description**|
| -------- | -------- |
| gpio | GPIO pin number.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Sample code:
```
/* Set the ISR function. */
int32_t MyCallBackFunc(uint16_t gpio, void *data)
{
HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", __func__, gpio, data);
return 0;
}
int32_t ret;
/* Set the ISR function to MyCallBackFunc, with input parameter of NULL and the interrupt trigger mode of rising edge. */
ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL);
if (ret != 0) {
HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret);
return;
}
/* Enable interrupts for GPIO pin 3. */
ret = GpioEnableIrq(3);
if (ret != 0) {
HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret);
return;
}
/* Disable interrupts for GPIO pin 3. */
ret = GpioDisableIrq(3);
if (ret != 0) {
HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret);
return;
}
/* Cancel the ISR function setting for GPIO pin 3. */
ret = GpioUnsetIrq(3, NULL);
if (ret != 0) {
HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret);
return;
}
```
## Example
The procedure is as follows:
1. Select an idle GPIO pin.
1. Select an idle GPIO pin, for example, pin GPIO10\_3 on a Hi3516D V300 development board.
This example uses pin GPIO10\_3 on a Hi3516D V300 development board as an example. The pin number is 83. You can select an idle GPIO pin as required.
The pin number is 83.
2. Set the ISR function for the pin, with the trigger mode of rising edge and failing edge.
GPIO pin number of GPIO10_3 = 10 x 8 + 3 = 83
3. Write high and low levels to the pin alternately, and observe the execution of the ISR function.
You can select an idle GPIO pin as required.
2. Set the ISR function for the pin, with the trigger mode of rising edge and failing edge.
3. Write high and low levels to the pin alternately, and observe the execution of the ISR function.
```
#include "gpio_if.h"
#include "hdf_log.h"
......@@ -503,7 +273,7 @@ static uint32_t g_irqCnt;
static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data)
{
HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data);
g_irqCnt++; /* If the ISR function is triggered, the number of global interrupts is incremented by 1. */
g_irqCnt++; /* If the ISR function is triggered, the global interrupt counter is incremented by 1. */
return GpioDisableIrq(gpio);
}
......@@ -516,14 +286,14 @@ static int32_t TestCaseGpioIrqEdge(void)
uint16_t gpio = 83; /* Number of the GPIO pin to test */
uint32_t timeout;
/* Set the output direction for the pin. */
/* Set the pin direction to output. */
ret = GpioSetDir(gpio, GPIO_DIR_OUT);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set dir fail! ret:%d\n", __func__, ret);
return ret;
}
/* Disable the interrupt of the pin. */
/* Disable interrupts of the pin. */
ret = GpioDisableIrq(gpio);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: disable irq fail! ret:%d\n", __func__, ret);
......@@ -539,17 +309,17 @@ static int32_t TestCaseGpioIrqEdge(void)
return ret;
}
/* Enable the interrupt for this pin. */
/* Enable interrupts for the pin. */
ret = GpioEnableIrq(gpio);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret);
(void)GpioUnSetIrq(gpio);
(void)GpioUnsetIrq(gpio, NULL);
return ret;
}
g_irqCnt = 0; /* Reset the global counter. */
timeout = 0; /* Reset the waiting time. */
/* Wait for the ISR function of this pin to trigger. The timeout duration is 1000 ms. */
g_irqCnt = 0; /* Reset the global interrupt counter. */
timeout = 0; /* Clear the waiting time. */
/* Wait for the ISR function to trigger for this pin. The timeout duration is 1000 ms. */
while (g_irqCnt <= 0 && timeout < 1000) {
(void)GpioRead(gpio, &valRead);
(void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
......@@ -557,7 +327,7 @@ static int32_t TestCaseGpioIrqEdge(void)
OsalMDelay(200); /* wait for irq trigger */
timeout += 200;
}
(void)GpioUnSetIrq(gpio);
(void)GpioUnsetIrq(gpio, NULL);
return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE;
}
```
\ No newline at end of file
```
# GPIO<a name="EN-US_TOPIC_0000001153555758"></a>
# GPIO
## Overview<a name="section1826197354103451"></a>
In the Hardware Driver Foundation \(HDF\) framework, the general-purpose input/output \(GPIO\) module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** \(a void pointer\) directly points to the kernel-mode address of the device object.
## Overview
**Figure 1** Service-free mode<a name="fig5511033193814"></a>
![](figures/service-free-mode.png "service-free-mode")
In the Hardware Driver Foundation (HDF), the general-purpose input/output (GPIO) module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the operating system (OS) that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** (a void pointer) directly points to the kernel-mode address of the device object.
## Available APIs<a name="section752964871810"></a>
**Figure 1** Service-free mode
![](figures/service-free-mode.png "service-free-mode")
## Available APIs
**GpioMethod**:
GpioMethod
```
struct GpioMethod {
......@@ -26,397 +30,266 @@ struct GpioMethod {
int32_t (*disableIrq)(struct GpioCntlr *cntlr, uint16_t local);
}
```
**Table 1** Callbacks for the members in the GpioMethod structure
<a name="table151341544111"></a>
<table><thead align="left"><tr id="row19514101504111"><th class="cellrowborder" align="center" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p451461513418"><a name="p451461513418"></a><a name="p451461513418"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p32641283426"><a name="p32641283426"></a><a name="p32641283426"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p55141515134111"><a name="p55141515134111"></a><a name="p55141515134111"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p5514171514114"><a name="p5514171514114"></a><a name="p5514171514114"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p155141215124113"><a name="p155141215124113"></a><a name="p155141215124113"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row195141715164110"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p145141015144110"><a name="p145141015144110"></a><a name="p145141015144110"></a>write</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p453215451206"><a name="p453215451206"></a><a name="p453215451206"></a><strong id="b1053114522014"><a name="b1053114522014"></a><a name="b1053114522014"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p116571249112015"><a name="p116571249112015"></a><a name="p116571249112015"></a><strong id="b8657144913202"><a name="b8657144913202"></a><a name="b8657144913202"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
<p id="p1351421512414"><a name="p1351421512414"></a><a name="p1351421512414"></a><strong id="b1861811201459"><a name="b1861811201459"></a><a name="b1861811201459"></a>val</strong>: input level value, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" align="left" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p8514715124111"><a name="p8514715124111"></a><a name="p8514715124111"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p14514161554118"><a name="p14514161554118"></a><a name="p14514161554118"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p155148151416"><a name="p155148151416"></a><a name="p155148151416"></a>Writes the level of a GPIO pin.</p>
</td>
</tr>
<tr id="row185141415174112"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1151520153413"><a name="p1151520153413"></a><a name="p1151520153413"></a>read</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p139611135152114"><a name="p139611135152114"></a><a name="p139611135152114"></a><strong id="b4961435162120"><a name="b4961435162120"></a><a name="b4961435162120"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p1451581512410"><a name="p1451581512410"></a><a name="p1451581512410"></a><strong id="b12610253913"><a name="b12610253913"></a><a name="b12610253913"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p19515415134113"><a name="p19515415134113"></a><a name="p19515415134113"></a><strong id="b5968229295"><a name="b5968229295"></a><a name="b5968229295"></a>val</strong>: pointer to the output level value, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1051591564115"><a name="p1051591564115"></a><a name="p1051591564115"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p185151715184112"><a name="p185151715184112"></a><a name="p185151715184112"></a>Reads the level of a GPIO pin.</p>
</td>
</tr>
<tr id="row4515111512414"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p125152152412"><a name="p125152152412"></a><a name="p125152152412"></a>setDir</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p5579168142212"><a name="p5579168142212"></a><a name="p5579168142212"></a><strong id="b357928112218"><a name="b357928112218"></a><a name="b357928112218"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p1465781110227"><a name="p1465781110227"></a><a name="p1465781110227"></a><strong id="b4657711182217"><a name="b4657711182217"></a><a name="b4657711182217"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
<p id="p1551521584114"><a name="p1551521584114"></a><a name="p1551521584114"></a><strong id="b1172125431011"><a name="b1172125431011"></a><a name="b1172125431011"></a>dir</strong>: input pin direction, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1351541517413"><a name="p1351541517413"></a><a name="p1351541517413"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p251551515419"><a name="p251551515419"></a><a name="p251551515419"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1351501516419"><a name="p1351501516419"></a><a name="p1351501516419"></a>Sets the input or output direction for a GPIO pin.</p>
</td>
</tr>
<tr id="row10515161517417"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p135151015154114"><a name="p135151015154114"></a><a name="p135151015154114"></a>getDir</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p14901244112218"><a name="p14901244112218"></a><a name="p14901244112218"></a><strong id="b1689844182212"><a name="b1689844182212"></a><a name="b1689844182212"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p1351531519411"><a name="p1351531519411"></a><a name="p1351531519411"></a><strong id="b171715420138"><a name="b171715420138"></a><a name="b171715420138"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p15515141554120"><a name="p15515141554120"></a><a name="p15515141554120"></a><strong id="b12246123210138"><a name="b12246123210138"></a><a name="b12246123210138"></a>dir</strong>: pointer to the output pin direction, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p651531574110"><a name="p651531574110"></a><a name="p651531574110"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1551620153418"><a name="p1551620153418"></a><a name="p1551620153418"></a>Obtains the input or output direction of a GPIO pin.</p>
</td>
</tr>
<tr id="row2051616153411"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p13516171517412"><a name="p13516171517412"></a><a name="p13516171517412"></a>setIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p139141552310"><a name="p139141552310"></a><a name="p139141552310"></a><strong id="b1791313562318"><a name="b1791313562318"></a><a name="b1791313562318"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p1939331118235"><a name="p1939331118235"></a><a name="p1939331118235"></a><strong id="b839319111238"><a name="b839319111238"></a><a name="b839319111238"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
<p id="p81051177235"><a name="p81051177235"></a><a name="p81051177235"></a><strong id="b6105141718231"><a name="b6105141718231"></a><a name="b6105141718231"></a>mode</strong>: triggering mode, which can be <strong id="b11105517102314"><a name="b11105517102314"></a><a name="b11105517102314"></a>edge</strong> or <strong id="b1210501711237"><a name="b1210501711237"></a><a name="b1210501711237"></a>level</strong>. The value is of the uint16_t type.</p>
<p id="p24421624172315"><a name="p24421624172315"></a><a name="p24421624172315"></a><strong id="b9442524112316"><a name="b9442524112316"></a><a name="b9442524112316"></a>func</strong>: function pointer to the interrupt service handler.</p>
<p id="p251619154417"><a name="p251619154417"></a><a name="p251619154417"></a><strong id="b33689285172"><a name="b33689285172"></a><a name="b33689285172"></a>arg</strong>: void pointer to the input parameters of the interrupt service handler.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1851631524118"><a name="p1851631524118"></a><a name="p1851631524118"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1551691512413"><a name="p1551691512413"></a><a name="p1551691512413"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p351615157411"><a name="p351615157411"></a><a name="p351615157411"></a>Sets an interrupt request (IRQ) for a GPIO pin.</p>
</td>
</tr>
<tr id="row135161157417"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p551631515418"><a name="p551631515418"></a><a name="p551631515418"></a>unsetIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p5931131516250"><a name="p5931131516250"></a><a name="p5931131516250"></a><strong id="b119311215162517"><a name="b119311215162517"></a><a name="b119311215162517"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p155164152415"><a name="p155164152415"></a><a name="p155164152415"></a><strong id="b1330123517188"><a name="b1330123517188"></a><a name="b1330123517188"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p8516161519416"><a name="p8516161519416"></a><a name="p8516161519416"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p4516415124119"><a name="p4516415124119"></a><a name="p4516415124119"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p451671594110"><a name="p451671594110"></a><a name="p451671594110"></a>Cancels the GPIO interrupt settings.</p>
</td>
</tr>
<tr id="row55161015134117"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p165161153415"><a name="p165161153415"></a><a name="p165161153415"></a>enableIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p87941124269"><a name="p87941124269"></a><a name="p87941124269"></a><strong id="b979421272616"><a name="b979421272616"></a><a name="b979421272616"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p85164158418"><a name="p85164158418"></a><a name="p85164158418"></a><strong id="b1046612112256"><a name="b1046612112256"></a><a name="b1046612112256"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p13517181584114"><a name="p13517181584114"></a><a name="p13517181584114"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1251711518412"><a name="p1251711518412"></a><a name="p1251711518412"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p65172015124114"><a name="p65172015124114"></a><a name="p65172015124114"></a>Enables an interrupt for a GPIO pin.</p>
</td>
</tr>
<tr id="row125171915154119"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p155173157418"><a name="p155173157418"></a><a name="p155173157418"></a>disableIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p352101419274"><a name="p352101419274"></a><a name="p352101419274"></a><strong id="b052141472711"><a name="b052141472711"></a><a name="b052141472711"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p16517191544119"><a name="p16517191544119"></a><a name="p16517191544119"></a><strong id="b1173395802511"><a name="b1173395802511"></a><a name="b1173395802511"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1751751544113"><a name="p1751751544113"></a><a name="p1751751544113"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p11517515164117"><a name="p11517515164117"></a><a name="p11517515164117"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p15517191534112"><a name="p15517191534112"></a><a name="p15517191534112"></a>Disables an interrupt for a GPIO pin.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section731175315103451"></a>
The GPIO controller manages all pins by group. The related parameters are described in the attribute file. Instantiating the driver entry and API functions is the core for the vendor driver to access the HDF.
The GPIO module adaptation involves the following steps:
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **gpio\_config.hcs** file.
3. Instantiate the GPIO controller object.
- Initialize **GpioCntlr**.
- Instantiate **GpioMethod** in the **GpioCntlr** object.
For details, see [Available APIs](#section752964871810).
4. \(Optional\) Debug the driver.
For new drivers, verify the basic functions, such as the GPIO control status and response to interrupts.
## Development Example<a name="section800425816103451"></a>
The following uses **gpio\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions.
1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type \(defined in **hdf\_device\_desc.h**\), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits.
- GPIO driver entry reference
```
struct HdfDriverEntry g_gpioDriverEntry = {
.moduleVersion = 1,
.Bind = Pl061GpioBind, // Bind does not need to be implemented for GPIO. In this example, the implementation is empty. Vendors can add related operations as required.
.Init = Pl061GpioInit, // See the Init function.
.Release = Pl061GpioRelease, // See the Release function.
.moduleName = "hisi_pl061_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
// Call HDF_INIT to register the driver entry with the HDF framework.
HDF_INIT(g_gpioDriverEntry);
```
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **gpio\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **GpioCntlr** members at the core layer.
In this example, there is only one GPIO controller. If there are multiple GPIO controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **gpio\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_gpio :: device {
device0 :: deviceNode {
policy = 0; // The value 0 indicates that no service needs to be published.
priority = 10; // Driver startup priority
permission = 0644; // Permission to create device nodes for the driver
moduleName = "hisi_pl061_driver"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
deviceMatchAttr = "hisilicon_hi35xx_pl061";// (Mandatory) Used to configure the private data of the controller. The value must be the same as the controller information in gpio_config.hcs.
// The controller information must be consistent. Other controller information is also contained in the file.
}
}
}
}
}
```
- **gpio\_config.hcs** configuration reference
**Table 1** Description of the callback functions in GpioMethod
```
root {
platform {
gpio_config {
controller_0x120d0000 {
match_attr = "hisilicon_hi35xx_pl061"; // (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
groupNum = 12; // (Mandatory) GPIO group index
bitNum = 8; // (Mandatory) Number of GPIO pins in each group
regBase = 0x120d0000;// (Mandatory) Physical base address
regStep = 0x1000; // (Mandatory) Register offset step
irqStart = 48; // (Mandatory) Start an IRQ.
irqShare = 0; // (Mandatory) Share the IRQ.
}
}
}
}
```
3. Initialize the **GpioCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **GpioMethod** \(used to call underlying functions of the driver\) in **GpioCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
- Custom structure reference
To the driver, the custom structure carries parameters and data. The values in the **gpio\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the index and the number of pins, are also passed to the **GpioCntlr** object at the core layer.
```
struct Pl061GpioCntlr {
struct GpioCntlr cntlr;// (Mandatory) Control object of the core layer. For details about the member definitions, see the following description.
volatile unsigned char *regBase; // (Mandatory) Base address of the register
uint32_t phyBase; // (Mandatory) Physical base address
uint32_t regStep; // (Mandatory) Register offset step
uint32_t irqStart; // (Mandatory) Start an IRQ.
uint16_t groupNum; // (Mandatory) GPIO port number
uint16_t bitNum; // (Mandatory) GPIO port number
uint8_t irqShare; // (Mandatory) Share the IRQ.
struct Pl061GpioGroup *groups; // (Optional) Set based on the vendor's requirements.
};
struct Pl061GpioGroup {// Register address, interrupt number, interrupt function, and lock
volatile unsigned char *regBase;
unsigned int index;
unsigned int irq;
OsalIRQHandle irqFunc;
OsalSpinlock lock;
};
// GpioCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct GpioCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct GpioMethod *ops;
struct DListHead list;
OsalSpinlock spin;
uint16_t start;
uint16_t count;
struct GpioInfo *ginfos;
void *priv;
};
```
- Instantiate the callback function structure **GpioMethod** in **GpioCntlr**. Other members are initialized by using the **Init** function.
```
// The members of the GpioMethod structure are all callbacks. Vendors need to implement the corresponding functions according to [Table 1](#table151341544111).
static struct GpioMethod g_method = {
.request = NULL,
.release = NULL,
.write = Pl061GpioWrite, // Write pin settings.
.read = Pl061GpioRead, // Read pin settings.
.setDir = Pl061GpioSetDir, // Set the pin direction.
.getDir = Pl061GpioGetDir, // Obtain the pin direction.
.toIrq = NULL,
.setIrq = Pl061GpioSetIrq, // Set an interrupt for the pin. If this capability is not available, skip it.
.unsetIrq = Pl061GpioUnsetIrq, // Cancel the interrupt settings for the pin. If this capability is not available, skip it.
.enableIrq = Pl061GpioEnableIrq, // Enable an interrupt for the pin. If this capability is not available, skip it.
.disableIrq = Pl061GpioDisableIrq,// Disable the interrupt for the pin. If this capability is not available, skip it.
};
```
- Init function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\)
| Function| Input Parameter| Output Parameter| Return Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| write | **cntlr**: structure pointer to the GPIO controller at the core layer.<br>**local**: GPIO port number, which is of the uint16_t type.<br>**val**: input level, which is of the uint16_t type. | – | HDF_STATUS| Writes the level of a GPIO pin.|
| read | **cntlr**: structure pointer to the GPIO controller at the core layer.<br>**local**: GPIO port number, which is of the uint16_t type. | **val**: pointer to the output level, which is of the uint16_t type.| HDF_STATUS| Reads the level of a GPIO pin.|
| setDir | **cntlr**: structure pointer to the GPIO controller at the core layer.<br>**local**: GPIO port number, which is of the uint16_t type.<br>**dir**: pin direction to set, which is of the uint16_t type. | – | HDF_STATUS| Sets the direction (input or output) for a GPIO pin.|
| getDir | **cntlr**: structure pointer to the GPIO controller at the core layer.<br>**local**: GPIO port number, which is of the uint16_t type. | **dir**: pointer to the pin direction obtained, which is of the uint16_t type.| HDF_STATUS| Obtains the input or output direction of a GPIO pin.|
| setIrq | **cntlr**: structure pointer to the GPIO controller at the core layer.<br>**local**: GPIO port number, which is of the uint16_t type.<br>**mode**: trigger mode, which can be edge or level of the uint16_t type. <br>**func**: pointer to the interrupt request (IRQ) handler.<br>**arg**: void pointer to the input parameters of the IRQ handler. | – | HDF_STATUS| Sets an IRQ for a GPIO pin.|
| unsetIrq | **cntlr**: structure pointer to the GPIO controller at the core layer.<br>**local**: GPIO port number, which is of the uint16_t type. | – | HDF_STATUS| Cancels the IRQ settings for a GPIO pin.|
| enableIrq | **cntlr**: structure pointer to the GPIO controller at the core layer.<br>**local**: GPIO port number, which is of the uint16_t type. | – | HDF_STATUS| Enables interrupts for a GPIO pin.|
| disableIrq | **cntlr**: structure pointer to the GPIO controller at the core layer.<br>**local**: GPIO port number, which is of the uint16_t type. | – | HDF_STATUS| Disables interrupts for a GPIO pin.|
**Table 2** Init function description
<a name="table165981547354"></a>
<table><thead align="left"><tr id="row8599145423516"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p959995453515"><a name="p959995453515"></a><a name="p959995453515"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p185991854163519"><a name="p185991854163519"></a><a name="p185991854163519"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row13599195483515"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p125993545359"><a name="p125993545359"></a><a name="p125993545359"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p125991454153519"><a name="p125991454153519"></a><a name="p125991454153519"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row35997541354"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19600454153511"><a name="p19600454153511"></a><a name="p19600454153511"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1600145423514"><a name="p1600145423514"></a><a name="p1600145423514"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row9600155423514"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p146001546357"><a name="p146001546357"></a><a name="p146001546357"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p10600754133512"><a name="p10600754133512"></a><a name="p10600754133512"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row146001254143516"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p66007542357"><a name="p66007542357"></a><a name="p66007542357"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p2600135416357"><a name="p2600135416357"></a><a name="p2600135416357"></a>I/O error</p>
</td>
</tr>
<tr id="row36001544351"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p660095417357"><a name="p660095417357"></a><a name="p660095417357"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17600165411353"><a name="p17600165411353"></a><a name="p17600165411353"></a>Initialization successful</p>
</td>
</tr>
<tr id="row14600154103518"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p46001544356"><a name="p46001544356"></a><a name="p46001544356"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p160035415356"><a name="p160035415356"></a><a name="p160035415356"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
## How to Develop
Function description:
The GPIO controller manages all pins by group. The related parameters are defined in attribute files. You need to instantiate the driver entry and APIs for the vendor driver to access the HDF.
Initializes the custom structure object and **GpioCntlr**, calls the **GpioCntlrAdd** function at the core layer, and connects to the VFS \(optional\).
The GPIO module adaptation involves the following steps:
```
static int32_t Pl061GpioInit(struct HdfDeviceObject *device)
{
...
struct Pl061GpioCntlr *pl061 = &g_pl061;// Use static global variables to complete initialization.
//static struct Pl061GpioCntlr g_pl061 = {
// .groups = NULL,
// .groupNum = PL061_GROUP_MAX,
// .bitNum = PL061_BIT_MAX,
//};
ret = Pl061GpioReadDrs(pl061, device->property);// Use the attribute values read from the gpio_config.HCS file to initialize the members of the custom structure object.
...
pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);// Address mapping
...
ret = Pl061GpioInitCntlrMem(pl061); // Apply for memory.
...
pl061->cntlr.count = pl061->groupNum x pl061->bitNum;// (Mandatory) Calculate the number of pins.
pl061->cntlr.priv = (void *)device->property; // (Mandatory) Store device attributes.
pl061->cntlr.ops = &g_method; // (Mandatory) Connect to the GpioMethod instance.
pl061->cntlr.device = device; // (Mandatory) Enable conversion between HdfDeviceObject and GpioCntlr.
ret = GpioCntlrAdd(&pl061->cntlr); // (Mandatory) Call this function to set the structure of the core layer. The driver accesses the platform core layer only after a success signal is returned.
...
Pl061GpioDebugCntlr(pl061);
#ifdef PL061_GPIO_USER_SUPPORT // (Optional) Access the user-level virtual file system if supported.
if (GpioAddVfs(pl061->bitNum) != HDF_SUCCESS) {
HDF_LOGE("%s: add vfs fail!", __func__);
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file.
- (Optional) Add the **gpio_config.hcs** file.
3. Instantiate the GPIO controller object.
- Initialize **GpioCntlr**.
- Instantiate **GpioMethod** in the **GpioCntlr** object.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/> For details about the callbacks in **GpioMethod**, see [Available APIs](#available_apis).
4. Debug the driver.
(Optional) For new drivers, verify the basic functions, such as the GPIO status control and response to interrupts.
## Development Example
The following uses **gpio_hi35xx.c** as an example to present the information to be provided by the vendor for implementing device functions.
1. Instantiate the driver entry.
The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf\_device\_desc.h**), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
GPIO driver entry example:
```
struct HdfDriverEntry g_gpioDriverEntry = {
.moduleVersion = 1,
.Bind = Pl061GpioBind, // Bind does not need to be implemented for GPIO. It is an empty method in this example. You can add related operations as required.
.Init = Pl061GpioInit, // See the Init function.
.Release = Pl061GpioRelease, // See the Release function.
.moduleName = "hisi_pl061_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
// Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_gpioDriverEntry);
```
2. Add the **deviceNode** information to the **device_info.hcs** file, and configure the device attributes in the **gpio_config.hcs** file.
The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **GpioCntlr** members at the core layer.
In this example, there is only one GPIO controller. If there are multiple GPIO controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **gpio_config** file for each controller.
- **device_info.hcs** configuration example
```
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_gpio :: device {
device0 :: deviceNode {
policy = 0; // No service is published.
priority = 10; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver.
moduleName = "hisi_pl061_driver"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
deviceMatchAttr = "hisilicon_hi35xx_pl061";// (Mandatory) Private data of the controller. The value must be the same as the controller information in gpio_config.hcs.
// Add private information about all controllers in this file.
}
}
}
}
#endif
...
}
```
- Release function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
Function description:
Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations.
```
static void Pl061GpioRelease(struct HdfDeviceObject *device)
{
struct GpioCntlr *cntlr = NULL;
struct Pl061GpioCntlr *pl061 = NULL;
...
cntlr = GpioCntlrFromDevice(device);// (Mandatory) Obtain the control object of the core layer through forced conversion.
//return (device == NULL) ? NULL : (struct GpioCntlr *)device->service;
...
#ifdef PL061_GPIO_USER_SUPPORT
GpioRemoveVfs();// Perform operations reverse to GpioAddVfs in Init.
#endif
GpioCntlrRemove(cntlr); // (Mandatory) Remove the device information and services from the core layer.
pl061 = ToPl061GpioCntlr(cntlr); //return (struct Pl061GpioCntlr *)cntlr;
Pl061GpioRleaseCntlrMem(pl061); // (Mandatory) Release the lock and memory.
OsalIoUnmap((void *)pl061->regBase);// (Mandatory) Remove the address mapping.
pl061->regBase = NULL;
}
```
- **gpio_config.hcs** configuration example
```
root {
platform {
gpio_config {
controller_0x120d0000 {
match_attr = "hisilicon_hi35xx_pl061"; // (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
groupNum = 12; // (Mandatory) GPIO group number.
bitNum = 8; // (Mandatory) Number of GPIO pins in each group.
regBase = 0x120d0000;// (Mandatory) Physical base address.
regStep = 0x1000; // (Mandatory) Register offset step.
irqStart = 48; // (Mandatory) Enable interrupts.
irqShare = 0; // (Mandatory) Whether to share an interrupt.
}
}
}
}
```
3. Initialize the **GpioCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Init** and **Release**) to instantiate **GpioMethod** in **GpioCntlr** (so that the underlying driver functions can be called).
- Defining a custom structure
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **gpio_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the GPIO group number and the number of pins, to the **GpioCntlr** object at the core layer.
```
struct Pl061GpioCntlr {
struct GpioCntlr cntlr;// (Mandatory) Control object at the core layer. The details are as follows:
volatile unsigned char *regBase;// (Mandatory) Register base address.
uint32_t phyBase; // (Mandatory) Physical base address.
uint32_t regStep; // (Mandatory) Register offset step.
uint32_t irqStart; // (Mandatory) Enable interrupts.
uint16_t groupNum; // (Mandatory) Parameter of the GPIO port number.
uint16_t bitNum; // (Mandatory) Parameter of the GPIO port number.
uint8_t irqShare; // (Mandatory) Whether to share an interrupt.
struct Pl061GpioGroup *groups; // (Optional) Set based on the actual requirements.
};
struct Pl061GpioGroup {// Register address, IRQ number and function, and lock.
volatile unsigned char *regBase;
unsigned int index;
unsigned int irq;
OsalIRQHandle irqFunc;
OsalSpinlock lock;
};
// GpioCntlr is the controller structure at the core layer. The Init function assigns values to the members of GpioCntlr.
struct GpioCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct GpioMethod *ops;
struct DListHead list;
OsalSpinlock spin;
uint16_t start;
uint16_t count;
struct GpioInfo *ginfos;
void *priv;
};
```
- Instantiating the **GpioMethod** structure in **GpioCntlr** (other members are initialized by **Init**)
```
// The members of the GpioMethod structure are all callbacks. You need to implement the functions listed in Table 1.
static struct GpioMethod g_method = {
.request = NULL,
.release = NULL,
.write = Pl061GpioWrite, // Write the pin level.
.read = Pl061GpioRead, // Read the pin level.
.setDir = Pl061GpioSetDir, // Set the pin direction.
.getDir = Pl061GpioGetDir, // Obtain the pin direction.
.toIrq = NULL,
.setIrq = Pl061GpioSetIrq, // Set an IRQ for a pin. Skip it if this capability is not available.
.unsetIrq = Pl061GpioUnsetIrq, // Cancel the IRQ settings for a pin. Skip it if this capability is not available.
.enableIrq = Pl061GpioEnableIrq, // Enable interrupts for a pin. Skip it if this capability is not available.
.disableIrq = Pl061GpioDisableIrq,// Disable interrupts for a pin. Skip it if this capability is not available.
};
```
- **Init** function
Input parameter:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
HDF_STATUS
The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
**Table 2** HDF_STATUS
| Status| Description|
| -------- | -------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
| HDF_ERR_INVALID_PARAM | Invalid parameter.|
| HDF_ERR_IO | I/O error.|
| HDF_SUCCESS | Initialization successful.|
| HDF_FAILURE | Initialization failed.|
Function description:
Initializes the custom structure object and **GpioCntlr**, calls the **GpioCntlrAdd** function at the core layer, and (optional) connects to the virtual file system (VFS).
```
static int32_t Pl061GpioInit(struct HdfDeviceObject *device)
{
...
struct Pl061GpioCntlr *pl061 = &g_pl061;// Use static global variables to complete initialization.
// static struct Pl061GpioCntlr g_pl061 = {
// .groups = NULL,
// .groupNum = PL061_GROUP_MAX,
// .bitNum = PL061_BIT_MAX,
//};
ret = Pl061GpioReadDrs(pl061, device->property);// Use the attribute values read from the gpio_config.hcs file to initialize the members of the custom structure object.
...
pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);// Create address mapping.
...
ret = Pl061GpioInitCntlrMem(pl061); // Allocate memory.
...
pl061->cntlr.count = pl061->groupNum x pl061->bitNum;// (Mandatory) Calculate the number of pins.
pl061->cntlr.priv = (void *)device->property; // (Mandatory) Store device attributes.
pl061->cntlr.ops = &g_method; // (Mandatory) Attach the GpioMethod instance.
pl061->cntlr.device = device; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and GpioCntlr.
ret = GpioCntlrAdd(&pl061->cntlr); // (Mandatory) Call this function to fill the structure of the core layer. The driver accesses the platform core layer only after a success signal is returned.
...
Pl061GpioDebugCntlr(pl061);
#ifdef PL061_GPIO_USER_SUPPORT // (Optional) Access the user-level VFS if it is supported.
if (GpioAddVfs(pl061->bitNum) != HDF_SUCCESS) {
HDF_LOGE("%s: add vfs fail!", __func__);
}
```
\ No newline at end of file
#endif
...
}
```
- **Release** function
Input parameter:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return value:
No value is returned.
Function description:
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the value assignment operations.
```
static void Pl061GpioRelease(struct HdfDeviceObject *device)
{
struct GpioCntlr *cntlr = NULL;
struct Pl061GpioCntlr *pl061 = NULL;
...
cntlr = GpioCntlrFromDevice(device);// (Mandatory) Obtain the control object at the core layer through forced conversion.
// return (device == NULL) ? NULL : (struct GpioCntlr *)device->service;
...
#ifdef PL061_GPIO_USER_SUPPORT
GpioRemoveVfs();// Reverse operation of GpioAddVfs in Init.
#endif
GpioCntlrRemove(cntlr); // (Mandatory) Remove the device information and services from the core layer.
pl061 = ToPl061GpioCntlr(cntlr); // return (struct Pl061GpioCntlr *)cntlr;
Pl061GpioRleaseCntlrMem(pl061); // (Mandatory) Release the lock and memory.
OsalIoUnmap((void *)pl061->regBase);// (Mandatory) Unmap the addresses.
pl061->regBase = NULL;
}
```
......@@ -6,34 +6,34 @@
### HDMI
High-definition multimedia interface (HDMI) is an interface for transmitting audio and video data from a source device, such as a DVD player or set-top box (STB), to a sink device, such as a TV or display.
HDMI works in primary/secondary mode and usually has a source and a sink.
HDMI usually has a source and a sink.
The HDMI APIs provide a set of common functions for HDMI transmission, including:
- Opening and closing an HDMI controller
- Starting and stopping HDMI transmission
- Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute
- Reading the raw Extended Display Identification Data (EDID) from a sink
- Registering and unregistering a callback for HDMI hot plug detect (HPD).
- Registering and unregistering a callback for HDMI hot plug detect (HPD)
### Basic Concepts
HDMI is an audio and video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, and Toshiba. The transmission process complies with the Transition-minimized Differential Signaling (TMDS).
- TMDS is used to transmit audio, video, and various auxiliary data.
- Display data channel (DDC) allows the TX and RX ends to obtain the sending and receiving capabilities. However, the HDMI only needs to unidirectionally obtain the capabilities of the RX end (display).
- Display data channel (DDC) allows the TX and RX ends to obtain the transmitting and receiving capabilities. However, HDMI only needs to unidirectionally obtain the capabilities of the RX end (display).
- Consumer Electronics Control (CEC) enables interaction between the HDMI TX and RX devices.
- Fixed rate link (FRL) allows the maximum TMDS bandwidth to be increased from 18 Gbit/s to 48 Gbit/s.
- High-bandwidth Digital Content Protection (HDCP) prevents copying of digital audio and video content being transmitted across devices.
- Extended Display Identification Data (EDID), usually stored in the display firmware, provides the vendor information, EDID version, maximum image size, color settings, vendor pre-settings, frequency range limit, display name, and serial number.
- EDID, usually stored in the display firmware, provides the vendor information, EDID version, maximum image size, color settings, vendor pre-settings, frequency range limit, display name, and serial number.
### Working Principles
The HDMI source end provides +5 V and GND for DDC and CEC communication. Through the DDC, the source end obtains the sink end parameters, such as the RX capabilities. The CEC is optional. It is used to synchronize the control signals between the source and sink ends to improve user experience. There are four TMDS channels between the HDMI source and sink ends. The TMDS clock channel provides clock signals for TMDS, and the other three channels transmit audio, video, and auxiliary data. HPD is the hot plug detect port. When the sink end is connected, the source end responds by using an interrupt program.
The HDMI source provides +5 V and GND for DDC and CEC communication. Through the DDC, the source obtains the sink parameters, such as the RX capabilities. The CEC provides an optional channel to synchronize control signals between the source and sink for better user experience. There are four TMDS channels between the HDMI source and sink. The TMDS clock channel provides clock signals for TMDS, and the other three channels transmit audio, video, and auxiliary data. HDP is the hot plug detect port. When the sink is connected, the source responds by using an interrupt service routine (ISR).
The figure below shows the HDMI physical connection.
**Figure 1** HDMI physical connection
![](figures/HDMI_physical_connection.png "HDMI_physical_connection")
### Constraints
......@@ -69,15 +69,15 @@ HDMI features high transmission rate, wide transmission bandwidth, high compatib
### How to Develop
The figure below illustrates the process of using an HDMI device.
The figure below illustrates the general HDMI development process.
**Figure 2** Process of using an HDMI device
![](figures/HDMI_usage_flowchart.png "HDMI_usage_flowchart")
**Figure 2** Using HDMI driver APIs
![](figures/using-HDMI-process.png "using-HDMI-process")
#### Opening an HDMI Controller
Before HDMI communication, call **HdmiOpen** to open an HDMI controller.
Before HDMI communication, call **HdmiOpen()** to open an HDMI controller.
```c
DevHandle HdmiOpen(int16_t number);
......@@ -88,11 +88,11 @@ DevHandle HdmiOpen(int16_t number);
| Parameter | Description |
| ---------- | -------------------- |
| number | HDMI controller ID. |
| **Return Value**| **Description** |
| NULL | Failed to open the HDMI controller. |
| **Return Value**| **Description** |
| NULL | The operation failed. |
| Controller handle| Handle of the opened HDMI controller.|
Example: Open controller 0 of the two HDMI controllers (numbered 0 and 1) in the system.
For example, open controller 0 of the two HDMI controllers (numbered 0 and 1) in the system:
```c
DevHandle hdmiHandle = NULL; /* HDMI controller handle /
......@@ -117,7 +117,7 @@ int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo
| ---------- | ------------------ |
| handle | HDMI controller handle. |
| callback | Pointer to the callback to be invoked to return the HPD result.|
| **Return Value**| **Description** |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation failed. |
......@@ -165,7 +165,7 @@ int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);
| handle | HDMI controller handle. |
| buffer | Pointer to the data buffer. |
| len | Data length. |
| **Return Value**| **Description** |
| **Return Value**| **Description** |
| Positive integer | Raw EDID read.|
| Negative number or 0 | Failed to read the EDID. |
......@@ -194,7 +194,7 @@ int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr);
| ------ | -------------- |
| handle | HDMI controller handle.|
| attr | Pointer to the audio attributes. |
| **Return Value**| **Description** |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation failed. |
......@@ -260,7 +260,7 @@ int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr);
| Parameter | Description |
| ---------- | -------------- |
| handle | HDMI controller handle.|
| attr | Pinter to the HDR attributes. |
| attr | Pinter to the HDR attributes |
| **Return Value**| **Description**|
| 0 | The operation is successful. |
| Negative value | The operation failed. |
......@@ -295,7 +295,7 @@ int32_t HdmiAvmuteSet(DevHandle handle, bool enable);
| ---------- | ----------------- |
| handle | HDMI controller handle. |
| enable | Whether to enable the AV mute feature.|
| **Return Value**| **Description** |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation failed. |
......@@ -615,4 +615,4 @@ static int32_t TestCaseHdmi(void)
return 0;
}
```
\ No newline at end of file
```
......@@ -5,15 +5,13 @@
### HDMI
High-definition multimedia interface (HDMI) is an interface for transmitting audio and video data from a source device, such as a DVD player or set-top box (STB), to a sink device, such as a TV or display.
High Definition Multimedia Interface (HDMI) is an audio and video transmission protocol jointly released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson and Toshiba. It is used to transmit audio and video data from a source device, such as a DVD player or set-top box (STB), to a sink device, such as a TV or display. The transmission process complies with the Transition-minimized Differential Signaling (TMDS).
### Basic Concepts
HDMI is an audio and video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, and Toshiba. The transmission process complies with the Transition Minimized Differential Signaling (TMDS) protocol.
- TMDS is used to transmit audio, video, and various auxiliary data.
- Display data channel (DDC) allows the TX and RX ends to obtain the sending and receiving capabilities. However, the HDMI only needs to unidirectionally obtain the capabilities of the RX end (display).
- Display data channel (DDC) allows the TX and RX ends to obtain the transmitting and receiving capabilities. However, HDMI only needs to unidirectionally obtain the capabilities of the RX end (display).
- Consumer Electronics Control (CEC) enables interaction between the HDMI TX and RX devices.
......@@ -23,7 +21,7 @@ HDMI is an audio and video transmission protocol released by Hitachi, Panasonic,
### Working Principles
In the HDF, the HDMI module uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to process external access requests. After receiving an access request, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDFDeviceManager can be directly used. However, you need to configure a node for each device, which increases the memory usage.
In the HDF, the HDMI module uses the independent service mode for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device to increase memory resources.
**Figure 1** Independent service mode
......@@ -35,13 +33,13 @@ Currently, the HDMI module supports only the kernels (LiteOS) of mini and small
## Development Guidelines
### Use Cases
### When to Use
HDMI features high transmission rate, wide transmission bandwidth, high compatibility, and can transmit uncompressed audio and video signals. Compared with the traditional full analog interface, HDMI simplifies connection between devices and provides HDMI-specific intelligent features, which are ideal for high-quality audio and video transmission of small-sized devices.
### Available APIs
**HdmiCntlrOps**:
**HdmiCntlrOps**:
```c
struct HdmiCntlrOps {
void (*hardWareInit)(struct HdmiCntlr *cntlr);
......@@ -81,42 +79,42 @@ struct HdmiCntlrOps {
};
```
**Table 1** Description of the HdmiCntlrOps structure
**Table 1** Description of the callback functions in HdmiCntlrOps
| Function | Input Parameter | Output Parameter | Return Value | Description |
| ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------ | -------------------------------------------------- |
| hardWareInit | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| –| Initializes the HDMI hardware.|
| hardWareStatusGet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>| **status**: pointer to the HDMI hardware status.| –| Obtains the HDMI hardware status. |
| controllerReset | **cntlr**: structure pointer to an HDMI controller at the core layer.| – | –| Resets an HDMI controller. |
| hotPlugStateGet | **cntlr**: structure pointer to an HDMI controller at the core layer. | – | **bool**: HDMI hot-plug status.| Obtains the HDMI hot-plug status. |
| hotPlugInterruptStateGet | **cntlr**: structure pointer to an HDMI controller at the core layer. | – | **bool**: HDMI hot-plug interrupt status.| Obtains the HDMI hot-plug interrupt status. |
| lowPowerSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable low power consumption.| – | –| Enables or disables low power consumption.|
| tmdsModeSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**mode**: TMDS mode.| – | –| Sets the TMDS mode. |
|tmdsConfigSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**mode**: TMDS parameters.|–|HDF_STATUS|Sets TMDS parameters.|
|infoFrameEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**infoFrameType**: packet type.<br>**enable**: whether to enable infoFrame.|–|–|Enables or disables infoFrame.|
|infoFrameSend|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**infoFrameType**: packet type.<br>**data**: pointer to infoFrame data.<br>**len**: data length.|–|HDF_STATUS|Sends an infoFrame.|
| hardWareStatusGet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>| **status**: pointer to the HDMI hardware status.| –| Obtains the HDMI hardware status.|
| controllerReset | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| –| Resets an HDMI controller.|
| hotPlugStateGet | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| **bool**: HDMI hot-plug status.| Obtains the HDMI hot-plug status.|
| hotPlugInterruptStateGet | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| **bool**: HDMI hot-plug interrupt status.| Obtains the HDMI hot-plug interrupt status.|
| lowPowerSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable low power consumption.| –| –| Enables or disables low power consumption.|
| tmdsModeSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**mode**: TMDS mode.| –| –| Sets the TMDS mode.|
| tmdsConfigSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**mode**: TMDS parameters.| –| HDF_STATUS| Sets TMDS parameters.|
| infoFrameEnable | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**infoFrameType**: packet type.<br>**enable**: whether to enable infoFrame.| –| –| Enables or disables infoFrame.|
| infoFrameSend | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**infoFrameType**: packet type.<br>**data**: pointer to infoFrame data.<br>**len**: data length.| –| HDF_STATUS| Sends an infoFrame.|
|cecMsgSend|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**msg**: pointer to the CEC message|–|HDF_STATUS|Sends a CEC message.|
|audioPathEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the audio path.|–|–|Enables or disables the audio path.|
|audioPathSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**config**: pointer to the audio path configuration.|–|–|Sets the audio path.|
| audioPathSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**config**: pointer to the audio path configuration.| –| –| Sets the audio path.|
|phyOutputEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the physical layer output.|–|–|Enables or disables the physical layer output.|
|phyOutputSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**cfg**: pointer to the physical layer configuration.|–|–|Sets the physical layer information.|
| phyOutputSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**cfg**: pointer to the physical layer configuration.| –| –| Sets the physical layer information.|
|blackDataSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the black screen.|–|–|Sets the black screen.|
|videoMuteEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the video mute feature.|–|–|Enables or disables the video mute feature.|
|videoPathSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**attr**: pointer to the video path configuration.|–|–|Sets the video path.|
| videoPathSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**attr**: pointer to the video path configuration.| –| –| Sets the video path.|
|audioMuteEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the audio mute feature.|–|–|Enables or disables the audio mute feature.|
|avmuteSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the AV mute feature.|–|–|Enables or disables the AV mute feature.|
|ddcTransfer|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**ddcCfg**: pointer to the DDC configuration.|**ddcCfg**: DDC configuration.|HDF_STATUS|Reads and writes data through the DDC.|
|scdcSourceScrambleGet|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|Scrambling status of the source.|Obtains the scrambling status of the source.|
| scdcSourceScrambleGet | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| Scrambling status of the source.| Obtains the scrambling status of the source.|
|scdcSourceScrambleSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the scrambling for the source.|–|HDF_STATUS|Enables or disable scrambling for the source.|
|frlEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the FRL.|–|HDF_STATUS|Enables or disables the FRL.|
|audioNctsSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**cfg**: pointer to the N/CTS configuration.|–|HDF_STATUS|Sets the audio N/CTS information.|
| audioNctsSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**cfg**: pointer to the N/CTS configuration.| –| HDF_STATUS| Sets the audio N/CTS information.|
|frlTrainingConfigSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**cfg**: pointer to the FRL training configuration.|–|–|Sets FRL training information.|
|frlTrainingStart|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|–|Starts FRL training.|
|frlGetTriningRslt|**cntlr**: structure pointer to an HDMI controller at the core layer.|**rslt**: FRL training result.|–|Obtains the FRL training result.|
|hdcpRegInit|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|–|Initializes registers related to the High-bandwidth Digital Content Protection (HDCP) process.|
|hdcpGenerateAksvAndAn|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|HDF_STATUS|Generates the **Aksv** and **An** in the HDCP process.|
|hdcpOptReg|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**type**: operation type.<br>**data**: register data.<br>**len**: data length.|**data**: register data.|HDF_STATUS|Reads or writes the registers during the HDCP process.|
|hdrTimerSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**config**: pointer to the timer configuration|–|–|Sets the HDR-related timer.|
| frlTrainingStart | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| –| Starts FRL training.|
| frlGetTriningRslt | **cntlr**: structure pointer to an HDMI controller at the core layer.| **rslt**: FRL training result.| –| Obtains the FRL training result.|
| hdcpRegInit | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| –| Initializes registers related to the High-bandwidth Digital Content Protection (HDCP) process.|
|hdcpGenerateAksvAndAn |**cntlr**: structure pointer to an HDMI controller at the core layer.| –| HDF_STATUS| Generates the **Aksv** and **An** in the HDCP process.|
| hdcpOptReg | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**type**: operation type.<br>**data**: register data.<br>**len**: data length.| **data**: register data.| HDF_STATUS| Reads or writes the registers during the HDCP process.|
| hdrTimerSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**config**: pointer to the timer configuration| –| –| Sets the HDR-related timer.|
### How to Develop
......@@ -139,9 +137,9 @@ The HDMI module adaptation involves the following steps:
The driver entry must be a global variable of the **HdfDriverEntry** type (which is defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind()** function and then the **Init()** function to load a driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
HDMI driver entry reference:
HDMI driver entry example:
```c
struct HdfDriverEntry g_hdmiDriverEntry = {
......@@ -149,25 +147,25 @@ The HDMI module adaptation involves the following steps:
.Bind = HdmiAdapterBind,
.Init = HdmiAdapterInit,
.Release = HdmiAdapterRelease,
.moduleName = "adapter_hdmi_driver",// (Mandatory) The value must be the same as that in the .hcs file.
.moduleName = "adapter_hdmi_driver",// (mandatory) The value must be the same as that in the .hcs file.
};
HDF_INIT(g_hdmiDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
```
2. Configure attribute files.
Add **deviceNode** to the **device_info.hcs** file, and configure the device attributes in the **hdmi\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or restriction ranges of the **HdmiCntlr** members at the core layer.
Add **deviceNode** to the **device_info.hcs** file, and configure the device attributes in the **hdmi_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or restriction ranges of the **HdmiCntlr** members at the core layer.
Configure HDMI controller information from the first node. This node specifies a type of HDMI controllers rather than a specific HDMI controller. In this example, there is only one HDMI controller. If there are multiple HDMI controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **hdmi\_config** file.
Configure HDMI controller information from the first node. This node specifies a type of HDMI controllers rather than a specific HDMI controller. In this example, there is only one HDMI controller. If there are multiple HDMI controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **hdmi_config** file.
- **device\_info.hcs** configuration reference
- **device_info.hcs** configuration example:
```c
root {
platform :: host {
device_hdmi :: device {
device0 :: deviceNode {
policy = 2; // The value 2 means to publish a service.
policy = 2; // Publish services.
priority = 20; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver.
serviceName = "HDF_PLATFORM_HDMI_0"; // (Mandatory) Unique name of the service published by the driver.
......@@ -179,7 +177,7 @@ The HDMI module adaptation involves the following steps:
}
```
- **hdmi_config.hcs** configuration reference
- **hdmi_config.hcs** configuration example:
```c
root {
......@@ -230,13 +228,15 @@ The HDMI module adaptation involves the following steps:
3. Instantiate the **HdmiCntlr** object.
Initialize the **HdmiCntlr** object at the core layer, including initializing the vendor custom structure (passing parameters and data) and instantiating the **HdmiCntlrOps** (used to call the underlying functions of the driver). The **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) must be implemented in this step.
Initialize the **HdmiCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init** and **Release**) to instantiate **HdmiCntlrOps** in **HdmiCntlr** (so that the underlying driver functions can be called).
- Custom structure reference
> ![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
> To the driver, the custom structure carries parameters and data. The values in the **hdmi_config.hcs** file are read by the HDF, and structure members are initialized by **DeviceResourceIface**. Some important values (such as the device number and bus number) are also passed to the **HdmiCntlr** object at the core layer.
- Defining the custom structure
> ![](../public_sys-resources/icon-note.gif) **NOTE**
>
>
> To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **hdmi_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the device number and bus number, to the **HdmiCntlr** object at the core layer.
```c
struct HdmiAdapterHost {
struct HdmiCntlr *cntlr; // (Mandatory) Control object at the core layer. The details are as follows:
......@@ -245,8 +245,8 @@ The HDMI module adaptation involves the following steps:
uint32_t regSize; // (Mandatory) Register bit width.
uint32_t irqNum; // (Mandatory) IRQ number.
};
/* HdmiCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init() function. */
/* HdmiCntlr is the controller structure at the core layer. The Init function assigns values to the members of HdmiCntlr. */
struct HdmiCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj;
......@@ -272,8 +272,8 @@ The HDMI module adaptation involves the following steps:
};
```
- Instantiate **HdmiCntlrOps** in **HdmiCntlr**.
- Instantiating **HdmiCntlrOps** in **HdmiCntlr**
```c
static struct HdmiCntlrOps g_hdmiAdapterHostOps = {
.hardWareInit = HdmiAdapterHardWareInit,
......@@ -313,28 +313,30 @@ The HDMI module adaptation involves the following steps:
};
```
- **Bind()** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
**Return value**:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** definition in the **/drivers/framework/include/utils/hdf\_base.h file**.)
| State | Description |
- **Bind** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
HDF_STATUS
The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
|Status|Description|
|:-|:-|
|HDF_ERR_INVALID_OBJECT|Invalid controller object.|
|HDF_ERR_INVALID_PARAM|Invalid parameter.|
|HDF_ERR_MALLOC_FAIL |Memory allocation failed.|
|HDF_ERR_INVALID_PARAM |Invalid parameter.|
|HDF_ERR_MALLOC_FAIL |Failed to allocate memory.|
|HDF_ERR_IO |I/O error.|
|HDF_SUCCESS |Transmission successful.|
|HDF_FAILURE |Transmission failed.|
**Function description**:
**Function description**:
Initializes the custom structure object **HdmiAdapterHost** and **HdmiCntlr**, and calls the **HdmiCntlrAdd** function to add the HDMI controller to the core layer.
The **HdmiCntlr**, **HdmiAdapterHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully.
```c
static int32_t HdmiAdapterBind(struct HdfDeviceObject *obj)
{
......@@ -355,13 +357,13 @@ The HDMI module adaptation involves the following steps:
cntlr->ops = &g_hdmiHostOps; // (Mandatory) Connect to the HdmiCntlrOps instance.
cntlr->hdfDevObj = obj; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and HdmiCntlr.
obj->service = &cntlr->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and HdmiCntlr.
ret = HdmiAdapterCntlrParse(cntlr, obj); // (Mandatory) Initialize cntlr. If the operation fails, execute goto__ERR.
ret = HdmiAdapterCntlrParse(cntlr, obj); // (Mandatory) Initialize cntlr. If the operation fails, execute goto __ERR.
...
ret = HdmiAdapterHostParse(host, obj); // (Mandatory) Initialize the attributes of the host object. If the initialization fails, execute goto__ERR.
ret = HdmiAdapterHostParse(host, obj); // (Mandatory) Initialize the attributes of the host object. If the operation fails, execute goto__ERR.
...
ret = HdmiAdapterHostInit(host, cntlr); // Perform vendor custom structure initialization. If the initialization fails, execute goto __ERR.
ret = HdmiAdapterHostInit(host, cntlr); // Initialize the custom structure. If the operation fails, execute goto __ERR.
...
ret = HdmiCntlrAdd(cntlr); // Call the function at the core layer. If the operation fails, execute goto__ERR.
ret = HdmiCntlrAdd(cntlr); // Call the functions at the core layer. If the operation fails, execute goto__ERR.
...
HDF_LOGD("HdmiAdapterBind: success.");
return HDF_SUCCESS;
......@@ -371,47 +373,47 @@ The HDMI module adaptation involves the following steps:
return ret;
}
```
- **Init()** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
- **Init** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
**Return value**:
HDF_STATUS
**Function description**:
**Function description**:
Implements the **HdmiAdapterInit** function.
```c
static int32_t HdmiAdapterInit(struct HdfDeviceObject *obj)
{
return HDF_SUCCESS;
}
```
- **Release()** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
- **Release** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
**Return value**:
No value is returned.
**Function description**:
Releases the memory and deletes the controller. This function assigns a value to the **Release()** API in the driver entry structure. If the HDF fails to call the **Init()** function to initialize the driver, the **Release()** function can be called to release driver resources.
**Function description**:
Releases the memory and deletes the controller. This function assigns values to the **Release** callback in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
```c
static void HdmiAdapterRelease(struct HdfDeviceObject *obj)
{
struct HdmiCntlr *cntlr = NULL;
...
cntlr = (struct MmcCntlr *)obj->service;// Forcibly convert HdfDeviceObject to HdmiCntlr by using service. For details about the value assignment, see the Bind() function.
cntlr = (struct MmcCntlr *)obj->service;// Forcibly convert HdfDeviceObject to HdmiCntlr by using service. For details about the value assignment, see the Bind function.
...
HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);// Memory release function customized by the vendor. A forced conversion from HdmiCntlr to HimciAdapterHost is involved in the process.
HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);// Customized memory release function. A forced conversion from HdmiCntlr to HimciAdapterHost is involved in the process.
}
```
> ![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
> All forced conversion operations for obtaining the corresponding object can be successful only when the **Init()** function has the corresponding value assignment operations.
> ![](../public_sys-resources/icon-note.gif) **NOTE**<br>
> All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册