提交 9daecffa 编写于 作者: D duangavin123

切纯净版

Signed-off-by: Nduangavin123 <duanxichao@huawei.com>
上级 ddf1e404
# 驱动使用指南
- [HDF驱动框架](driver-hdf.md)
- HDF驱动框架
- [HDF开发概述](driver-hdf-overview.md)
- [驱动开发](driver-hdf-development.md)
- [驱动服务管理](driver-hdf-servicemanage.md)
- [驱动消息机制管理](driver-hdf-message-management.md)
- [配置管理](driver-hdf-manage.md)
- [HDF开发实例](driver-hdf-sample.md)
- [平台驱动开发](driver-develop.md)
- 平台驱动开发
- [ADC](driver-platform-adc-develop.md)
- [DAC](driver-platform-dac-develop.md)
- [GPIO](driver-platform-gpio-develop.md)
- [HDMI](driver-platform-hdmi-develop.md)
- [I2C](driver-platform-i2c-develop.md)
- [I3C](driver-platform-i3c-develop.md)
- [MIPI-CSI](driver-platform-mipicsi-develop.md)
- [MIPI-DSI](driver-platform-mipidsi-develop.md)
- [MIPI CSI](driver-platform-mipicsi-develop.md)
- [MIPI DSI](driver-platform-mipidsi-develop.md)
- [MMC](driver-platform-mmc-develop.md)
- [PIN](driver-platform-pin-develop.md)
- [PWM](driver-platform-pwm-develop.md)
- [REGULATOR](driver-platform-regulator-develop.md)
- [Regulator](driver-platform-regulator-develop.md)
- [RTC](driver-platform-rtc-develop.md)
- [SDIO](driver-platform-sdio-develop.md)
- [SPI](driver-platform-spi-develop.md)
- [UART](driver-platform-uart-develop.md)
- [WatchDog](driver-platform-watchdog-develop.md)
- [平台驱动使用](driver-platform.md)
- 平台驱动使用
- [ADC](driver-platform-adc-des.md)
- [DAC](driver-platform-dac-des.md)
- [GPIO](driver-platform-gpio-des.md)
- [HDMI](driver-platform-hdmi-des.md)
- [I2C](driver-platform-i2c-des.md)
- [I3C](driver-platform-i3c-des.md)
- [MIPI-CSI](driver-platform-mipicsi-des.md)
- [MIPI-DSI](driver-platform-mipidsi-des.md)
- [MIPI CSI](driver-platform-mipicsi-des.md)
- [MIPI DSI](driver-platform-mipidsi-des.md)
- [PIN](driver-platform-pin-des.md)
- [PWM](driver-platform-pwm-des.md)
- [REGULATOR](driver-platform-regulator-des.md)
- [Regulator](driver-platform-regulator-des.md)
- [RTC](driver-platform-rtc-des.md)
- [SDIO](driver-platform-sdio-des.md)
- [SPI](driver-platform-spi-des.md)
- [UART](driver-platform-uart-des.md)
- [WATCHDOG](driver-platform-watchdog-des.md)
- [外设驱动使用](driver-peripherals.md)
- [WatchDog](driver-platform-watchdog-des.md)
- 外设驱动使用
- [LCD](driver-peripherals-lcd-des.md)
- [TOUCHSCREEN](driver-peripherals-touch-des.md)
- [SENSOR](driver-peripherals-sensor-des.md)
- [Touchscreen](driver-peripherals-touch-des.md)
- [Sensor](driver-peripherals-sensor-des.md)
- [WLAN](driver-peripherals-external-des.md)
- [AUDIO](driver-peripherals-audio-des.md)
- [Audio](driver-peripherals-audio-des.md)
- [USB](driver-peripherals-usb-des.md)
- [CAMERA](driver-peripherals-camera-des.md)
- [VIBRATOR](driver-peripherals-vibrator-des.md)
- [LIGHT](driver-peripherals-light-des.md)
- [Camera](driver-peripherals-camera-des.md)
- [Vibrator](driver-peripherals-vibrator-des.md)
- [Light](driver-peripherals-light-des.md)
\ No newline at end of file
# 平台驱动开发<a name="ZH-CN_TOPIC_0000001160769576"></a>
# 平台驱动开发
- **[ADC](driver-platform-adc-develop.md)**
- **[DAC](driver-platform-dac-develop.md)**
- **[GPIO](driver-platform-gpio-develop.md)**
- **[ADC](driver-platform-adc-develop.md)**
- **[HDMI](driver-platform-hdmi-develop.md)**
- **[GPIO](driver-platform-gpio-develop.md)**
- **[I2C](driver-platform-i2c-develop.md)**
- **[I2C](driver-platform-i2c-develop.md)**
- **[I3C](driver-platform-i3c-develop.md)**
- **[MIPI DSI](driver-platform-mipidsi-develop.md)**
- **[MIPI-CSI](driver-platform-mipicsi-develop.md)**
- **[MMC](driver-platform-mmc-develop.md)**
- **[MIPI-DSI](driver-platform-mipidsi-develop.md)**
- **[PWM](driver-platform-pwm-develop.md)**
- **[MMC](driver-platform-mmc-develop.md)**
- **[RTC](driver-platform-rtc-develop.md)**
- **[PWM](driver-platform-pwm-develop.md)**
- **[SDIO](driver-platform-sdio-develop.md)**
- **[RTC](driver-platform-rtc-develop.md)**
- **[SPI](driver-platform-spi-develop.md)**
- **[SDIO](driver-platform-sdio-develop.md)**
- **[UART](driver-platform-uart-develop.md)**
- **[SPI](driver-platform-spi-develop.md)**
- **[UART](driver-platform-uart-develop.md)**
- **[WatchDog](driver-platform-watchdog-develop.md)**
- **[WatchDog](driver-platform-watchdog-develop.md)**
\ No newline at end of file
# 配置管理<a name="ZH-CN_TOPIC_0000001053493462"></a>
# 配置管理
- [配置概述](#section59914284576)
- [配置语法](#section533713333580)
- [关键字](#section4522107333)
- [基本结构](#section853042911312)
- [数据类型](#section177001259134)
- [预处理](#section14867121641)
- [注释](#section1323412417)
- [引用修改](#section193708571145)
- [节点复制](#section1487792020513)
- [删除](#section1096515391155)
- [属性引用](#section20271317611)
- [模板](#section958819191063)
- [配置生成](#section106152531919)
- [hc-gen介绍](#section359734416616)
## 配置概述
HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。
## 配置概述<a name="section59914284576"></a>
HC-GEN(HDF Configuration Generator)是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式:
HCS\(**H**DF **C**onfiguration **S**ource\)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理
- 在弱性能环境中,转换为配置树源码或配置树宏定义,驱动可直接调用C代码或宏式APIs获取配置
HC-GEN**\(H**DF **C**onfiguration **G**enerator**\)**是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式:
- 在弱性能环境中,转换为配置树源码或配置树宏定义,驱动可直接调用C代码或宏式APIs获取配置。
- 在高性能环境中,转换为HCB\(**H**DF **C**onfiguration **B**inary\)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。
- 在高性能环境中,转换为HCB(HDF Configuration Binary)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。
以下是使用HCB模式的典型应用场景:
**图 1** 配置使用流程图<a name="fig772653312159"></a>
![](figures/配置使用流程图.png "配置使用流程图")
**图1** 配置使用流程图
![zh-cn_image_0000001154105768](figures/zh-cn_image_0000001154105768.png)
HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。
## 配置语法<a name="section533713333580"></a>
## 配置语法
HCS的语法介绍如下:
### 关键字<a name="section4522107333"></a>
### 关键字
HCS配置语法保留了以下关键字。
**表 1** HCS配置语法保留关键字
<a name="table197619515016"></a>
<table><thead align="left"><tr id="row107621651103"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.1"><p id="p0745257902"><a name="p0745257902"></a><a name="p0745257902"></a>关键字</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.2"><p id="p1974510571305"><a name="p1974510571305"></a><a name="p1974510571305"></a>用途</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p10745175720020"><a name="p10745175720020"></a><a name="p10745175720020"></a>说明</p>
</th>
</tr>
</thead>
<tbody><tr id="row77624515014"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p8745657307"><a name="p8745657307"></a><a name="p8745657307"></a>root</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p074525719015"><a name="p074525719015"></a><a name="p074525719015"></a>配置根节点</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1174515575018"><a name="p1174515575018"></a><a name="p1174515575018"></a>-</p>
</td>
</tr>
<tr id="row18762175115012"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p11745175710019"><a name="p11745175710019"></a><a name="p11745175710019"></a>include</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p167458577016"><a name="p167458577016"></a><a name="p167458577016"></a>引用其他HCS配置文件</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p9745135718012"><a name="p9745135718012"></a><a name="p9745135718012"></a>-</p>
</td>
</tr>
<tr id="row20762251608"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p16745105712015"><a name="p16745105712015"></a><a name="p16745105712015"></a>delete</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p774585716016"><a name="p774585716016"></a><a name="p774585716016"></a>删除节点或属性</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p974514571102"><a name="p974514571102"></a><a name="p974514571102"></a>只能用于操作include导入的配置树</p>
</td>
</tr>
<tr id="row18762751509"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p174617571907"><a name="p174617571907"></a><a name="p174617571907"></a>template</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1874610571705"><a name="p1874610571705"></a><a name="p1874610571705"></a>定义模板节点</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p774617571019"><a name="p774617571019"></a><a name="p774617571019"></a>-</p>
</td>
</tr>
<tr id="row376320511903"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p3746557501"><a name="p3746557501"></a><a name="p3746557501"></a>match_attr</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1174635712015"><a name="p1174635712015"></a><a name="p1174635712015"></a>用于标记节点的匹配查找属性</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1774615571508"><a name="p1774615571508"></a><a name="p1774615571508"></a>解析配置时可以使用该属性的值查找到对应节点</p>
</td>
</tr>
</tbody>
</table>
### 基本结构<a name="section853042911312"></a>
HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。
**表1** HCS配置语法保留关键字
| 关键字 | 用途 | 说明 |
| -------- | -------- | -------- |
| root | 配置根节点 | - |
| include | 引用其他HCS配置文件 | - |
| delete | 删除节点或属性 | 只能用于操作include导入的配置树 |
| template | 定义模板节点 | - |
| match_attr | 用于标记节点的匹配查找属性 | 解析配置时可以使用该属性的值查找到对应节点 |
### 基本结构
HCS主要分为属性(Attribute)和节点(Node)两种结构。
**属性**
属性即最小的配置单元,是一个独立的配置项。语法如下:
```
attribute_name = value;
```
- attribute\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。
- value的可用格式如下:
- 数字常量,支持二进制、八进制、十进制、十六进制数,具体参考数据类型节。
- 字符串,内容使用双引号\(""\)引用。
- attribute_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。
- 节点引用。
- value的可用格式如下:
- 数字常量,支持二进制、八进制、十进制、十六进制数,具体参考数据类型节。
- 字符串,内容使用双引号("")引用。
- 节点引用。
- attribute 必须以分号\(;\)结束且必须属于一个node。
- attribute 必须以分号(;)结束且必须属于一个node。
**节点**
节点是一组属性的集合,语法如下:
```
node_name {
module = "sample";
......@@ -127,40 +75,41 @@ HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。
}
```
- node\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。
- node_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。
- 大括号后无需添加结束符“;”。
- 大括号后无需添加结束符“;”
- root为保留关键字,用于声明配置表的根节点。每个配置表必须以root节点开始
- root为保留关键字,用于声明配置表的根节点。每个配置表必须以root节点开始
- root节点中必须包含module属性,其值应该为一个字符串,用于表征该配置所属模块
- root节点中必须包含module属性,其值应该为一个字符串,用于表征该配置所属模块
- 节点中可以增加match_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点
- 节点中可以增加match\_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点。
### 数据类型<a name="section177001259134"></a>
### 数据类型
在属性定义中使用自动数据类型,不显式指定类型,属性支持的数据类型如下:
**整型**
整型长度自动推断,根据实际数据长度给与最小空间占用的类型。
- 二进制,0b前缀,示例:0b1010。
整型长度自动推断,根据实际数据长度给与最小空间占用的类型。
- 二进制,0b前缀,示例:0b1010。
- 八进制,0前缀,示例:0664。
- 十进制 ,无前缀,且支持有符号与无符号,示例:1024,+1024均合法。负值在读取时注意使用有符号数读取接口。
- 八进制,0前缀,示例:0664。
- 十六进制,0x前缀,示例:0xff00、0xFF
- 十进制 ,无前缀,且支持有符号与无符号,示例:1024,+1024均合法。负值在读取时注意使用有符号数读取接口
- 十六进制,0x前缀,示例:0xff00、0xFF。
**字符串**
字符串使用双引号\(""\)表示。
字符串使用双引号("")表示。
**数组**
数组元素支持整型、字符串,不支持混合类型。整型数组中uint32\_t uint64\_t混用会向上转型为uint64\_t 数组。整型数组与字符串数组示例如下:
数组元素支持整型、字符串,不支持混合类型。整型数组中uint32_t uint64_t混用会向上转型为uint64_t 数组。整型数组与字符串数组示例如下:
```
attr_foo = [0x01, 0x02, 0x03, 0x04];
attr_bar = ["hello", "world"];
......@@ -170,52 +119,59 @@ attr_bar = ["hello", "world"];
bool类型中**true**表示真,**false**表示假。
### 预处理<a name="section14867121641"></a>
### 预处理
**include**
用于导入其他HCS文件。语法示例如下:
```
#include "foo.hcs"
#include "../bar.hcs"
```
- 文件名必须使用双引号\(""\),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。
- 多个include,如果存在相同的节点,后者覆盖前者,其余的节点依次展开。
- 文件名必须使用双引号(""),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。
- 多个include,如果存在相同的节点,后者覆盖前者,其余的节点依次展开。
### 注释<a name="section1323412417"></a>
### 注释
支持两种注释风格。
- 单行注释。
- 单行注释。
```
// comment
```
```
// comment
```
- 多行注释。
- 多行注释。
```
/*
comment
*/
```
```
/*
comment
*/
```
>![](../public_sys-resources/icon-note.gif) **说明:**
>多行注释不支持嵌套。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 多行注释不支持嵌套。
### 引用修改<a name="section193708571145"></a>
### 引用修改
引用修改可以实现修改另外任意一个节点的内容,语法为:
```
node :& source_node
```
上述语句表示node中的内容是对source\_node节点内容的修改。示例如下:
上述语句表示node中的内容是对source_node节点内容的修改。示例如下:
```
root {
module = "sample";
......@@ -239,6 +195,7 @@ root {
最终生成配置树为:
```
root {
module = "sample";
......@@ -253,21 +210,25 @@ root {
}
```
在以上示例中,可以看到foo.foo\_节点通过引用将bar.attr属性的值修改为了"foo",foo.foo1节点通过引用将foo.foo2.attr属性的值修改为了0x2。foo.foo\_以及foo.foo1节点表示对目标节点内容的修改,其自身并不会存在最终生成的配置树中。
在以上示例中,可以看到foo.foo_节点通过引用将bar.attr属性的值修改为了"foo",foo.foo1节点通过引用将foo.foo2.attr属性的值修改为了0x2。foo.foo_以及foo.foo1节点表示对目标节点内容的修改,其自身并不会存在最终生成的配置树中。
- 引用同级node,可以直接使用node名称,否则被引用的节点必须使用绝对路径,节点间使用“.”分隔,root表示根节点,格式为root开始的节点路径序列,例如root.foo.bar即为一个合法的绝对路径。
- 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。
- 引用同级node,可以直接使用node名称,否则被引用的节点必须使用绝对路径,节点间使用“.”分隔,root表示根节点,格式为root开始的节点路径序列,例如root.foo.bar即为一个合法的绝对路径。
### 节点复制<a name="section1487792020513"></a>
- 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。
### 节点复制
节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法为:
```
node : source_node
```
上述语句表示在定义"node"节点时将另一个节点"source\_node"的属性复制过来。示例如下:
上述语句表示在定义"node"节点时将另一个节点"source_node"的属性复制过来。示例如下:
```
root {
module = "sample";
......@@ -282,6 +243,7 @@ root {
上述代码的最终生成配置树为:
```
root {
module = "sample";
......@@ -295,14 +257,16 @@ root {
}
```
在上述示例中,编译后bar节点即包含attr\_0属性也包含attr\_1属性,在bar中对attr\_0的修改不会影响到foo。
在上述示例中,编译后bar节点即包含attr_0属性也包含attr_1属性,在bar中对attr_0的修改不会影响到foo。
在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#引用修改)
在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#section193708571145)
### 删除<a name="section1096515391155"></a>
### 删除
要对include导入的base配置树中不需要的节点或属性进行删除,可以使用delete关键字。下面的举例中sample1.hcs通过include导入了sample2.hcs中的配置内容,并使用delete删除了sample2.hcs中的attribute2属性和foo\_2节点,示例如下:
要对include导入的base配置树中不需要的节点或属性进行删除,可以使用delete关键字。下面的举例中sample1.hcs通过include导入了sample2.hcs中的配置内容,并使用delete删除了sample2.hcs中的attribute2属性和foo_2节点,示例如下:
```
// sample2.hcs
root {
......@@ -322,27 +286,31 @@ root {
}
```
上述代码在生成过程中将会删除root.foo\_2节点与attr\_2,最终生成配置树为:
上述代码在生成过程中将会删除root.foo_2节点与attr_2,最终生成配置树为:
```
root {
attr_1 = 0x1;
}
```
>![](../public_sys-resources/icon-note.gif) **说明:**
>在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。
### 属性引用<a name="section20271317611"></a>
### 属性引用
为了在解析配置时快速定位到关联的节点,可以把节点作为属性的右值,通过读取属性查找到对应节点。语法为:
```
attribute = &node;
```
上述语句表示attribute的值是一个节点node的引用,在解析时可以用这个attribute快速定位到node,便于关联和查询其他node。示例如下:
```
node1 {
attributes;
......@@ -351,8 +319,10 @@ node2 {
attr_1 = &root.node1;
}
```
```
node2 {
node1 {
......@@ -362,12 +332,14 @@ node2 {
}
```
### 模板<a name="section958819191063"></a>
### 模板
模板的用途在于生成严格一致的node结构,以便对同类型node进行遍历和管理。
使用template关键字定义模板node,子node通过双冒号“::”声明继承关系。子节点可以改写但不能新增和删除template中的属性,子节点中没有定义的属性将使用template中的定义作为默认值。示例如下:
```
root {
module = "sample";
......@@ -387,6 +359,7 @@ root {
生成配置树如下:
```
root {
module = "sample";
......@@ -401,16 +374,19 @@ root {
}
```
在上述示例中,bar和bar\_1节点继承了foo节点,生成配置树节点结构与foo保持了完全一致,只是属性的值不同。
在上述示例中,bar和bar_1节点继承了foo节点,生成配置树节点结构与foo保持了完全一致,只是属性的值不同。
## 配置生成<a name="section106152531919"></a>
## 配置生成
hc-gen是配置生成的工具,可以对HCS配置语法进行检查并把HCS源文件转化成HCB二进制文件。
### hc-gen介绍<a name="section359734416616"></a>
### hc-gen介绍
hc-gen参数说明:
```
Usage: hc-gen [Options] [File]
options:
......@@ -418,7 +394,6 @@ options:
-a hcb align with four bytes
-b output binary output, default enable
-t output config in C language source file style
-m output config in macro source file style
-i output binary hex dump in C language source file style
-p <prefix> prefix of generated symbol name
-d decompile hcb to hcs
......@@ -429,25 +404,28 @@ options:
生成.c/.h 配置文件方法:
```
hc-gen -o [OutputCFileName] -t [SourceHcsFileName]
```
生成HCB 配置文件方法:
```
hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName]
```
生成宏定义配置文件方法:
```
hc-gen -o [OutputMacroFileName] -m [SourceHcsFileName]
```
反编译HCB文件为HCS方法:
```
hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName]
```
# 驱动消息机制管理<a name="ZH-CN_TOPIC_0000001052657065"></a>
# 驱动消息机制管理
- [使用场景](#section33014541954)
- [接口说明](#section538852311616)
- [开发步骤](#section946912121153)
## 使用场景<a name="section33014541954"></a>
## 使用场景
当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。
## 接口说明<a name="section538852311616"></a>
消息机制的功能主要有以下两种:
1. 用户态应用发送消息到驱动。
2. 用户态应用接收驱动主动上报事件。
**表 1** 消息机制接口
<a name="table208212674114"></a>
<table><thead align="left"><tr id="row08282618416"><th class="cellrowborder" valign="top" width="46.379999999999995%" id="mcps1.2.3.1.1"><p id="p382132664112"><a name="p382132664112"></a><a name="p382132664112"></a>方法</p>
</th>
<th class="cellrowborder" valign="top" width="53.620000000000005%" id="mcps1.2.3.1.2"><p id="p4826264419"><a name="p4826264419"></a><a name="p4826264419"></a>描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row1582426174114"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p182341916144420"><a name="p182341916144420"></a><a name="p182341916144420"></a>struct HdfIoService *HdfIoServiceBind(const char *serviceName)</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p58272614113"><a name="p58272614113"></a><a name="p58272614113"></a>用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。</p>
</td>
</tr>
<tr id="row578565084913"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p15786185024918"><a name="p15786185024918"></a><a name="p15786185024918"></a>void HdfIoServiceRecycle(struct HdfIoService *service);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p47861750154912"><a name="p47861750154912"></a><a name="p47861750154912"></a>释放驱动服务。</p>
</td>
</tr>
<tr id="row1382112617413"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p482182611415"><a name="p482182611415"></a><a name="p482182611415"></a>int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p18825261412"><a name="p18825261412"></a><a name="p18825261412"></a>用户态程序注册接收驱动上报事件的操作方法。</p>
</td>
</tr>
<tr id="row498956124019"><td class="cellrowborder" valign="top" width="46.379999999999995%" headers="mcps1.2.3.1.1 "><p id="p6412911184019"><a name="p6412911184019"></a><a name="p6412911184019"></a>int HdfDeviceSendEvent(struct HdfDeviceObject *deviceObject, uint32_t id, struct HdfSBuf *data);</p>
</td>
<td class="cellrowborder" valign="top" width="53.620000000000005%" headers="mcps1.2.3.1.2 "><p id="p1698915634018"><a name="p1698915634018"></a><a name="p1698915634018"></a>驱动主动上报事件接口。</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section946912121153"></a>
1. 将驱动配置信息中服务策略policy字段设置为2(SERVICE\_POLICY\_CAPACITY,参考[policy定义](driver-hdf-servicemanage.md))。
```
device_sample :: Device {
policy = 2;
...
}
```
2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。
3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。
```
// Dispatch是用来处理用户态发下来的消息
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
HDF_LOGE("sample driver lite A dispatch");
return 0;
}
int32_t SampleDriverBind(struct HdfDeviceObject *device)
{
HDF_LOGE("test for lite os sample driver A Open!");
if (device == NULL) {
HDF_LOGE("test for lite os sample driver A Open failed!");
return -1;
}
static struct ISampleDriverService sampleDriverA = {
.ioService.Dispatch = SampleDriverDispatch,
.ServiceA = SampleDriverServiceA,
.ServiceB = SampleDriverServiceB,
};
device->service = (struct IDeviceIoService *)(&sampleDriverA);
return 0;
}
```
4. 驱动定义消息处理函数中的cmd类型。
```
#define SAMPLE_WRITE_READ 1 // 读写操作码1
```
5. 用户态获取服务接口并发送消息到驱动。
```
int SendMsg(const char *testMsg)
{
if (testMsg == NULL) {
HDF_LOGE("test msg is null");
return -1;
}
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
}
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
if (data == NULL) {
HDF_LOGE("fail to obtain sbuf data");
return -1;
}
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
if (reply == NULL) {
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
goto out;
}
if (!HdfSbufWriteString(data, testMsg)) {
HDF_LOGE("fail to write sbuf");
ret = HDF_FAILURE;
goto out;
}
int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS) {
HDF_LOGE("fail to send service call");
goto out;
}
out:
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
HdfIoServiceRecycle(serv);
return ret;
}
```
6. 用户态接收该驱动上报的消息。
1. 用户态编写驱动上报消息的处理函数。
```
static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
OsalTimespec time;
OsalGetTime(&time);
HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec);
const char *string = HdfSbufReadString(data);
if (string == NULL) {
HDF_LOGE("fail to read string in event data");
return -1;
}
HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string);
return 0;
}
```
2. 用户态注册接收驱动上报消息的操作方法。
```
int RegisterListen()
{
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
}
static struct HdfDevEventlistener listener = {
.callBack = OnDevEventReceived,
.priv ="Service0"
};
if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {
HDF_LOGE("fail to register event listener");
return -1;
}
......
HdfDeviceUnregisterEventListener(serv, &listener);
HdfIoServiceRecycle(serv);
return 0;
}
```
3. 驱动上报事件。
```
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
... // process api call here
return HdfDeviceSendEvent(deviceObject, cmdCode, data);
}
```
## 接口说明
消息机制的功能主要有以下两种:
1. 用户态应用发送消息到驱动。
2. 用户态应用接收驱动主动上报事件。
**表1** 消息机制接口
| 方法 | 描述 |
| -------- | -------- |
| struct&nbsp;HdfIoService&nbsp;\*HdfIoServiceBind(const&nbsp;char&nbsp;\*serviceName); | 用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。 |
| void&nbsp;HdfIoServiceRecycle(struct&nbsp;HdfIoService&nbsp;\*service); | 释放驱动服务。 |
| int&nbsp;HdfDeviceRegisterEventListener(struct&nbsp;HdfIoService&nbsp;\*target,&nbsp;struct&nbsp;HdfDevEventlistener&nbsp;\*listener); | 用户态程序注册接收驱动上报事件的操作方法。 |
| int&nbsp;HdfDeviceSendEvent(struct&nbsp;HdfDeviceObject&nbsp;\*deviceObject,&nbsp;uint32_t&nbsp;id,&nbsp;struct&nbsp;HdfSBuf&nbsp;\*data); | 驱动主动上报事件接口。 |
## 开发步骤
1. 将驱动配置信息中服务策略policy字段设置为2(SERVICE_POLICY_CAPACITY,参考[policy定义](../driver/driver-hdf-servicemanage.md))。
```
device_sample :: Device {
policy = 2;
...
}
```
2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。
3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。
```
// Dispatch是用来处理用户态发下来的消息
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
HDF_LOGE("sample driver lite A dispatch");
return 0;
}
int32_t SampleDriverBind(struct HdfDeviceObject *device)
{
HDF_LOGE("test for lite os sample driver A Open!");
if (device == NULL) {
HDF_LOGE("test for lite os sample driver A Open failed!");
return -1;
}
static struct ISampleDriverService sampleDriverA = {
.ioService.Dispatch = SampleDriverDispatch,
.ServiceA = SampleDriverServiceA,
.ServiceB = SampleDriverServiceB,
};
device->service = (struct IDeviceIoService *)(&sampleDriverA);
return 0;
}
```
4. 驱动定义消息处理函数中的cmd类型。
```
#define SAMPLE_WRITE_READ 1 // 读写操作码1
```
5. 用户态获取服务接口并发送消息到驱动。
```
int SendMsg(const char *testMsg)
{
if (testMsg == NULL) {
HDF_LOGE("test msg is null");
return -1;
}
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
}
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
if (data == NULL) {
HDF_LOGE("fail to obtain sbuf data");
return -1;
}
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
if (reply == NULL) {
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
goto out;
}
if (!HdfSbufWriteString(data, testMsg)) {
HDF_LOGE("fail to write sbuf");
ret = HDF_FAILURE;
goto out;
}
int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS) {
HDF_LOGE("fail to send service call");
goto out;
}
out:
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
HdfIoServiceRecycle(serv);
return ret;
}
```
6. 用户态接收该驱动上报的消息。
1. 用户态编写驱动上报消息的处理函数。
```
static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
OsalTimespec time;
OsalGetTime(&time);
HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec);
const char *string = HdfSbufReadString(data);
if (string == NULL) {
HDF_LOGE("fail to read string in event data");
return -1;
}
HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string);
return 0;
}
```
2. 用户态注册接收驱动上报消息的操作方法。
```
int RegisterListen()
{
struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
if (serv == NULL) {
HDF_LOGE("fail to get service");
return -1;
}
static struct HdfDevEventlistener listener = {
.callBack = OnDevEventReceived,
.priv ="Service0"
};
if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {
HDF_LOGE("fail to register event listener");
return -1;
}
......
HdfDeviceUnregisterEventListener(serv, &listener);
HdfIoServiceRecycle(serv);
return 0;
}
```
3. 驱动上报事件。
```
int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
... // process api call here
return HdfDeviceSendEvent(deviceObject, cmdCode, data);
}
```
# HDF开发概述<a name="ZH-CN_TOPIC_0000001051611604"></a>
# HDF开发概述
- [简介](#section0649162112376)
- [驱动加载](#section68701942154319)
- [驱动服务管理](#section12453133414412)
- [驱动消息机制](#section129410710451)
## 简介<a name="section0649162112376"></a>
## 简介
HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理和驱动消息机制。旨在构建统一的驱动架构平台,为驱动开发者提供更精准、更高效的开发环境,力求做到一次开发,多系统部署。
## 驱动加载<a name="section68701942154319"></a>
HDF驱动加载包括按需加载和按序加载。
- 按需加载
## 驱动加载
HDF框架支持驱动在系统启动过程中默认加载,或者在系统启动之后动态加载。
HDF驱动加载包括按需加载和按序加载。
- 按序加载
- 按需加载
HDF框架支持驱动在系统启动过程中默认加载,或者在系统启动之后动态加载。
HDF框架支持驱动在系统启动的过程中按照驱动的优先级进行加载。
- 按序加载
HDF框架支持驱动在系统启动的过程中按照驱动的优先级进行加载。
## 驱动服务管理<a name="section12453133414412"></a>
## 驱动服务管理
HDF框架可以集中管理驱动服务,开发者可直接通过HDF框架对外提供的能力接口获取驱动相关的服务。
## 驱动消息机制<a name="section129410710451"></a>
HDF框架提供统一的驱动消息机制,支持用户态应用向内核态驱动发送消息,也支持内核态驱动向用户态应用发送消息。
## 驱动消息机制
HDF框架提供统一的驱动消息机制,支持用户态应用向内核态驱动发送消息,也支持内核态驱动向用户态应用发送消息。
# HDF开发实例<a name="ZH-CN_TOPIC_0000001052451677"></a>
# HDF开发实例
- [添加配置](#section27261067111)
- [编写驱动代码](#section177988005)
- [编写用户程序和驱动交互代码](#section6205173816412)
下面基于HDF框架,提供一个完整的样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。
## 添加配置<a name="section27261067111"></a>
在HDF框架的配置文件(例如vendor/hisilicon/xxx/hdf_config/device\_info)中添加该驱动的配置信息,如下所示:
## 添加配置
在HDF框架的配置文件(例如vendor/hisilicon/xxx/hdf_config/device_info)中添加该驱动的配置信息,如下所示:
```
root {
device_info {
......@@ -46,10 +45,12 @@ root {
}
```
## 编写驱动代码<a name="section177988005"></a>
基于HDF框架编写的sample驱动代码如下(编译参考 [驱动开发](driver-hdf-development.md)):
## 编写驱动代码
基于HDF框架编写的sample驱动代码如下(编译参考[驱动开发](../driver/driver-hdf-development.md)):
```
#include <fcntl.h>
#include <sys/stat.h>
......@@ -118,10 +119,12 @@ struct HdfDriverEntry g_sampleDriverEntry = {
HDF_INIT(g_sampleDriverEntry);
```
## 编写用户程序和驱动交互代码<a name="section6205173816412"></a>
基于HDF框架编写的用户态程序和驱动交互的代码如下(代码可以放在目录drivers/adapter/uhdf下面编译,build.gn可以参考drivers/framework/sample/platform/uart/dev/build.gn):
## 编写用户程序和驱动交互代码
基于HDF框架编写的用户态程序和驱动交互的代码如下(代码可以放在目录drivers/adapter/uhdf下面编译,build.gn可以参考drivers/framework/sample/platform/uart/dev/build.gn):
```
#include <fcntl.h>
#include <sys/stat.h>
......@@ -229,10 +232,13 @@ int main()
}
```
>![](../public_sys-resources/icon-note.gif) **说明:**
>用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf\_core和osal的动态库,在gn编译文件中添加如下依赖项:
>deps = \[
>"//drivers/adapter/uhdf/manager:hdf\_core",
>"//drivers/adapter/uhdf/posix:hdf\_posix\_osal",
>\]
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf_core和osal的动态库,在gn编译文件中添加如下依赖项:
>
> deps = [
>
> "//drivers/adapter/uhdf/manager:hdf_core",
>
> "//drivers/adapter/uhdf/posix:hdf_posix_osal",
>
> ]
# 驱动服务管理<a name="ZH-CN_TOPIC_0000001052777057"></a>
# 驱动服务管理
- [使用场景](#section14244270117)
- [接口说明](#section1432412561722)
- [开发步骤](#section393515164416)
驱动服务是HDF驱动设备对外提供能力的对象,由HDF框架统一管理。驱动服务管理主要包含驱动服务的发布和获取。
HDF框架定义了驱动对外发布服务的策略,是由配置文件中的policy字段来控制,policy字段的取值范围以及含义如下:
```
typedef enum {
/* 驱动不提供服务 */
......@@ -25,141 +25,119 @@ typedef enum {
} ServicePolicy;
```
## 使用场景<a name="section14244270117"></a>
## 使用场景
当驱动以接口的形式对外提供能力时,可以使用HDF框架的驱动服务管理能力。
## 接口说明<a name="section1432412561722"></a>
## 接口说明
针对驱动服务管理功能,HDF框架开放了以下接口供开发者调用,如下表所示:
**表 1** 服务管理接口
<a name="table8431122013592"></a>
<table><thead align="left"><tr id="row13431820135919"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1670132714592"><a name="p1670132714592"></a><a name="p1670132714592"></a>方法</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p770172785910"><a name="p770172785910"></a><a name="p770172785910"></a>描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row1743112017594"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p18601333135911"><a name="p18601333135911"></a><a name="p18601333135911"></a>int32_t (*Bind)(struct HdfDeviceObject *deviceObject);</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p46015332591"><a name="p46015332591"></a><a name="p46015332591"></a>需要驱动开发者实现Bind函数,将自己的服务接口绑定到HDF框架中。</p>
</td>
</tr>
<tr id="row1543212045914"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19601163314590"><a name="p19601163314590"></a><a name="p19601163314590"></a>const struct HdfObject *DevSvcManagerClntGetService(const char *svcName);</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1601123318598"><a name="p1601123318598"></a><a name="p1601123318598"></a>获取驱动的服务。</p>
</td>
</tr>
<tr id="row20432162019594"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p960173310590"><a name="p960173310590"></a><a name="p960173310590"></a>int HdfDeviceSubscribeService(</p>
<p id="p126021533165915"><a name="p126021533165915"></a><a name="p126021533165915"></a>struct HdfDeviceObject *deviceObject, const char *serviceName, struct SubscriberCallback callback);</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p06029334597"><a name="p06029334597"></a><a name="p06029334597"></a>订阅驱动的服务。</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section393515164416"></a>
**表1** 服务管理接口
驱动服务管理的开发包括驱动服务的编写、绑定、获取或者订阅,详细步骤如下。
| 方法 | 描述 |
| -------- | -------- |
| int32_t&nbsp;(\*Bind)(struct&nbsp;HdfDeviceObject&nbsp;\*deviceObject); | 需要驱动开发者实现Bind函数,将自己的服务接口绑定到HDF框架中。 |
| const&nbsp;struct&nbsp;HdfObject&nbsp;\*DevSvcManagerClntGetService(const&nbsp;char&nbsp;\*svcName); | 获取驱动的服务。 |
| int&nbsp;HdfDeviceSubscribeService(<br/>struct&nbsp;HdfDeviceObject&nbsp;\*deviceObject,&nbsp;const&nbsp;char&nbsp;\*serviceName,&nbsp;struct&nbsp;SubscriberCallback&nbsp;callback); | 订阅驱动的服务。 |
1. 驱动服务发布。
```
驱动服务结构的定义
struct ISampleDriverService {
struct IDeviceIoService ioService; // 服务结构的首个成员必须是IDeviceIoService类型的成员
int32_t (*ServiceA)(void); // 驱动的第一个服务接口
int32_t (*ServiceB)(uint32_t inputCode); // 驱动的第二个服务接口,有多个可以依次往下累加
};
驱动服务接口的实现
int32_t SampleDriverServiceA(void)
{
// 驱动开发者实现业务逻辑
return 0;
}
int32_t SampleDriverServiceB(uint32_t inputCode)
{
// 驱动开发者实现业务逻辑
return 0;
}
```
2. 驱动服务绑定到HDF框架中,实现HdfDriverEntry中的Bind指针函数。
```
int32_t SampleDriverBind(struct HdfDeviceObject *deviceObject)
{
// deviceObject为HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口
if (deviceObject == NULL) {
HDF_LOGE("Sample device object is null!");
return -1;
}
static struct ISampleDriverService sampleDriverA = {
.ServiceA = SampleDriverServiceA,
.ServiceB = SampleDriverServiceB,
};
deviceObject->service = &sampleDriverA.ioService;
return 0;
}
```
3. 驱动服务获取。
驱动服务的获取有两种方式,HDF框架提供接口直接获取和HDF框架提供订阅机制获取。
- 通过HDF接口直接获取
当明确驱动已经加载完成时,获取该驱动的服务可以通过HDF框架提供的能力接口直接获取,如下所示:
```
const struct ISampleDriverService *sampleService =
(const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver");
if (sampleService == NULL) {
return -1;
}
sampleService->ServiceA();
sampleService->ServiceB(5);
```
- 通过HDF提供的订阅机制获取
当内核态对驱动(同一个host)加载的时机不感知时,可以通过HDF框架提供的订阅机制来订阅该驱动,当该驱动加载完成时,HDF框架会将被订阅的驱动服务发布给订阅者,实现方式如下所示:
```
// 订阅回调函数的编写,当被订阅的驱动加载完成后,HDF框架会将被订阅驱动的服务发布给订阅者,通过这个回调函数给订阅者使用
// object为订阅者的私有数据,service为被订阅的服务对象
int32_t TestDriverSubCallBack(struct HdfDeviceObject *deviceObject, const struct HdfObject *service)
{
const struct ISampleDriverService *sampleService =
(const struct ISampleDriverService *)service;
if (sampleService == NULL) {
return -1;
}
sampleService->ServiceA();
sampleService->ServiceB(5);
}
// 订阅过程的实现
int32_t TestDriverInit(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
HDF_LOGE("Test driver init failed, deviceObject is null!");
return -1;
}
struct SubscriberCallback callBack;
callBack.deviceObject = deviceObject;
callBack.OnServiceConnected = TestDriverSubCallBack;
int32_t ret = HdfDeviceSubscribeService(deviceObject, "sample_driver", callBack);
if (ret != 0) {
HDF_LOGE("Test driver subscribe sample driver failed!");
}
return ret;
}
```
## 开发步骤
驱动服务管理的开发包括驱动服务的编写、绑定、获取或者订阅,详细步骤如下。
1. 驱动服务发布。
```
驱动服务结构的定义
struct ISampleDriverService {
struct IDeviceIoService ioService; // 服务结构的首个成员必须是IDeviceIoService类型的成员
int32_t (*ServiceA)(void); // 驱动的第一个服务接口
int32_t (*ServiceB)(uint32_t inputCode); // 驱动的第二个服务接口,有多个可以依次往下累加
};
驱动服务接口的实现
int32_t SampleDriverServiceA(void)
{
// 驱动开发者实现业务逻辑
return 0;
}
int32_t SampleDriverServiceB(uint32_t inputCode)
{
// 驱动开发者实现业务逻辑
return 0;
}
```
2. 驱动服务绑定到HDF框架中,实现HdfDriverEntry中的Bind指针函数。
```
int32_t SampleDriverBind(struct HdfDeviceObject *deviceObject)
{
// deviceObject为HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口
if (deviceObject == NULL) {
HDF_LOGE("Sample device object is null!");
return -1;
}
static struct ISampleDriverService sampleDriverA = {
.ServiceA = SampleDriverServiceA,
.ServiceB = SampleDriverServiceB,
};
deviceObject->service = &sampleDriverA.ioService;
return 0;
}
```
3. 驱动服务获取。
驱动服务的获取有两种方式,HDF框架提供接口直接获取和HDF框架提供订阅机制获取。
- 通过HDF接口直接获取
当明确驱动已经加载完成时,获取该驱动的服务可以通过HDF框架提供的能力接口直接获取,如下所示:
```
const struct ISampleDriverService *sampleService =
(const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver");
if (sampleService == NULL) {
return -1;
}
sampleService->ServiceA();
sampleService->ServiceB(5);
```
- 通过HDF提供的订阅机制获取
当内核态对驱动(同一个host)加载的时机不感知时,可以通过HDF框架提供的订阅机制来订阅该驱动,当该驱动加载完成时,HDF框架会将被订阅的驱动服务发布给订阅者,实现方式如下所示:
```
// 订阅回调函数的编写,当被订阅的驱动加载完成后,HDF框架会将被订阅驱动的服务发布给订阅者,通过这个回调函数给订阅者使用
// object为订阅者的私有数据,service为被订阅的服务对象
int32_t TestDriverSubCallBack(struct HdfDeviceObject *deviceObject, const struct HdfObject *service)
{
const struct ISampleDriverService *sampleService =
(const struct ISampleDriverService *)service;
if (sampleService == NULL) {
return -1;
}
sampleService->ServiceA();
sampleService->ServiceB(5);
}
// 订阅过程的实现
int32_t TestDriverInit(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
HDF_LOGE("Test driver init failed, deviceObject is null!");
return -1;
}
struct SubscriberCallback callBack;
callBack.deviceObject = deviceObject;
callBack.OnServiceConnected = TestDriverSubCallBack;
int32_t ret = HdfDeviceSubscribeService(deviceObject, "sample_driver", callBack);
if (ret != 0) {
HDF_LOGE("Test driver subscribe sample driver failed!");
}
return ret;
}
```
# HDF驱动框架<a name="ZH-CN_TOPIC_0000001157319419"></a>
# HDF驱动框架
- **[HDF开发概述](driver-hdf-overview.md)**
- **[驱动开发](driver-hdf-development.md)**
- **[驱动服务管理](driver-hdf-servicemanage.md)**
- **[HDF开发概述](driver-hdf-overview.md)**
- **[驱动消息机制管理](driver-hdf-message-management.md)**
- **[驱动开发](driver-hdf-development.md)**
- **[配置管理](driver-hdf-manage.md)**
- **[驱动服务管理](driver-hdf-servicemanage.md)**
- **[HDF开发实例](driver-hdf-sample.md)**
- **[驱动消息机制管理](driver-hdf-message-management.md)**
- **[配置管理](driver-hdf-manage.md)**
- **[HDF开发实例](driver-hdf-sample.md)**
\ No newline at end of file
# LCD<a name="ZH-CN_TOPIC_0000001052857284"></a>
# LCD
## 概述<a name="section141575391542"></a>
## 概述
LCD(Liquid Crystal Display)液晶显示驱动,对LCD进行上电,并通过接口初始化LCD内部寄存器,使LCD正常工作。Display驱动模型基于HDF( Hardware Driver Foundation)[驱动框架](driver-hdf-overview.md)开发,实现跨OS、跨平台,为LCD硬件提供上下电功能、发送初始化序列功能,使LCD进入正常的工作模式,显示芯片平台侧的图像数据,基于HDF驱动框架的Display驱动模型如[图1](#fig69138814229)
LCD(Liquid Crystal Display)液晶显示驱动,对LCD进行上电,并通过接口初始化LCD内部寄存器,使LCD正常工作。Display驱动模型基于HDF( Hardware Driver Foundation)[驱动框架](../driver/driver-hdf-overview.md)开发,实现跨OS、跨平台为LCD硬件提供上下电功能、发送初始化序列功能,使LCD进入正常的工作模式,显示芯片平台侧的图像数据。基于HDF驱动框架的Display驱动模型如下所示
**图 1** 基于HDF驱动框架的Display驱动模型<a name="fig69138814229"></a>
![](figures/基于HDF驱动框架的Display驱动模型.png "基于HDF驱动框架的Display驱动模型")
**图1** 基于HDF驱动框架的Display驱动模型
**Display驱动模型介绍**
![zh-cn_image_0000001170262223](figures/zh-cn_image_0000001170262223.png)
Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共hal层,支撑HDI(Hardware Display Interface)接口的实现,通过Display-HDI对图形服务提供各类驱动能力接口。
- Display平台驱动层:通过HDF提供的IOService数据通道,与公共Hal层对接,集中接收并处理各类上层调用指令。
- SOC平台驱动适配层:借助此SOC适配层,实现Display驱动和SOC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层。
- LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。
Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共HAL层,支撑HDI(Hardware Display Interface)接口的实现,通过Display-HDI对图形服务提供各类驱动能力接口。
- Display平台驱动层:通过HDF提供的IOService数据通道,与公共HAL层对接,集中接收并处理各类上层调用指令。
- SoC平台驱动适配层:借助此SoC适配层,实现Display驱动和SoC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层。
- LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。
基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。
## 接口说明<a name="section53793327396"></a>
## 接口说明
LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,常用的是MIPI DSI接口和TTL接口,下面对常用的MIPI DSI接口和TTL接口作简要介绍。
- MIPI DSI接口
- MIPI DSI接口
**图2** MIPI DSI接口
![zh-cn_image_0000001147040198](figures/zh-cn_image_0000001147040198.png)
**图 2** MIPI DSI接口<a name="fig6936451331"></a>
![](figures/MIPI-DSI接口.png "MIPI-DSI接口")
MIPI DSI接口是MIPI(Mobile Industry Processor Interface)联盟定义的显示接口,主要用于移动终端显示屏接口,接口数据传输遵循MIPI协议,MIPI DSI接口为数据接口,传输图像数据,通常情况下MIPI DSI接口的控制信息以MIPI包形式通过MIPI DSI接口发送到对端IC,不需要额外的外设接口。
MIPI DSI接口是MIPI(Mobile Industry Processor Interface)联盟定义的显示接口,主要用于移动终端显示屏接口,接口数据传输遵循MIPI协议,MIPI DSI接口为数据接口,传输图像数据,通常情况下MIPI DSI接口的控制信息以MIPI包形式通过MIPI DSI接口发送到对端IC,不需要额外的外设接口。
- TTL接口
- TTL接口
**图3** TTL接口
**图 3** TTL接口<a name="fig141611855635"></a>
![](figures/TTL接口.png "TTL接口")
![zh-cn_image_0000001192960023](figures/zh-cn_image_0000001192960023.png)
TTL(Transistor Transistor Logic)即晶体管-晶体管逻辑,TTL电平信号由TTL器件产生,TTL器件是数字集成电路的一大门类,它采用双极型工艺制造,具有高速度、低功耗和品种多等特点。
TTL(Transistor Transistor Logic)即晶体管-晶体管逻辑,TTL电平信号由TTL器件产生,TTL器件是数字集成电路的一大门类,它采用双极型工艺制造,具有高速度、低功耗和品种多等特点。
TTL接口是并行方式传输数据的接口,有数据信号、时钟信号和控制信号(行同步、帧同步、数据有效信号等),在控制信号控制下完成数据传输。通常TTL接口的LCD,内部寄存器读写需要额外的外设接口,比如SPI接口、I2C接口等。
TTL接口是并行方式传输数据的接口,有数据信号、时钟信号和控制信号(行同步、帧同步、数据有效信号等),在控制信号控制下完成数据传输。通常TTL接口的LCD,内部寄存器读写需要额外的外设接口,比如SPI接口、I2C接口等。
## 开发步骤<a name="section12394223125615"></a>
## 开发步骤
Display驱动模型基于HDF驱动框架、Platform接口及OSAL接口开发,可以做到不区分OS(LiteOS、Linux)和芯片平台(Hi35xx、Hi38xx、V3S等),为LCD器件提供统一的驱动模型。
Display驱动模型基于HDF驱动框架、Platform接口及OSAL接口开发,可以做到不区分OS(LiteOS、Linux)和芯片平台(Hi35xx、Hi38xx、V3S等),为LCD器件提供统一的驱动模型。开发步骤如下:
1. 添加LCD驱动相关的设备描述配置。
2. 在SOC平台驱动适配层中适配对应的芯片平台驱动。
3. 添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口:
- LCD上下电
根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC
1. 添加LCD驱动相关的设备描述配置
- 发送初始化序列
2. 在SoC平台驱动适配层中适配对应的芯片平台驱动。
根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。
3. 添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口:
- LCD上下电
根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC。
- 发送初始化序列
根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。
4. 根据需求实现HDF框架其他接口,比如Release接口。
5. 根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。
4. 根据需求实现HDF框架其他接口,比如Release接口。
## 开发实例<a name="section7441155155813"></a>
5. 根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。
## 开发实例
添加设备描述配置:
```
/* Display驱动相关的设备描述配置 */
display :: host {
......@@ -75,7 +84,7 @@ display :: host {
serviceName = "hdf_disp";
}
}
/* SOC适配层驱动设备描述 */
/* SoC适配层驱动设备描述 */
device_hi35xx_disp :: device {
device0 :: deviceNode {
policy = 0;
......@@ -103,6 +112,7 @@ display :: host {
SOC适配层驱动,以Hi35xx系列芯片为例,需要在本层驱动中适配MIPI等和芯片平台相关的配置,示例如下:
```
static int32_t MipiDsiInit(struct PanelInfo *info)
{
......@@ -145,6 +155,7 @@ static int32_t MipiDsiInit(struct PanelInfo *info)
LCD器件驱动示例如下:
```
#define RESET_GPIO 5
#define MIPI_DSI0 0
......@@ -347,4 +358,3 @@ struct HdfDriverEntry g_sampleDevEntry = {
HDF_INIT(g_sampleDevEntry);
```
......@@ -5,7 +5,7 @@
### 功能简介
​ Light驱动模型为上层Light硬件服务层提供稳定的灯控制能力接口,包括获取灯类型、配置点灯模式、配置灯闪烁效果、点灯、熄灯等。基于HDF(Hardware Driver Foundation)驱动框架开发的Light驱动模型,实现跨操作系统迁移,器件差异配置等功能。实现Light驱动“一次开发,多系统部署”的目标。Light驱动模型如图1示:
​ Light驱动模型为上层Light硬件服务层提供稳定的灯控制能力接口,包括获取灯类型、配置点灯模式、配置灯闪烁效果、点灯、熄灯等。基于HDF(Hardware Driver Foundation)驱动框架开发的Light驱动模型,实现跨操作系统迁移,器件差异配置等功能。实现Light驱动“一次开发,多系统部署”的目标。Light驱动模型如[图1](#Light驱动模型图)示:
**图 1** Light驱动模型图
......@@ -13,7 +13,7 @@
### 运作机制
通过介绍Light驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如图2所示:
通过介绍Light驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如[图2](#Light驱动运行图)所示:
**图 2** Light驱动运行图
......@@ -36,7 +36,7 @@ Light驱动模型以标准系统Hi3516DV300为例,介绍整个驱动加载及
### 接口说明
Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模式和闪烁时间的能力。Light硬件服务调用GetLightInfo获取Light设备的基本信息;调用TurnOnLight接口启动配置的闪烁效果。Light驱动模型对外开放的API接口能力,参考表1
Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模式和闪烁时间的能力。Light硬件服务调用GetLightInfo获取Light设备的基本信息;调用TurnOnLight接口启动配置的闪烁效果。Light驱动模型对外开放的API接口能力,参考[表1](#Light驱动模型对外API接口能力介绍)
**表1** Light驱动模型对外API接口能力介绍
......@@ -148,7 +148,7 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模
HdfWorkDestroy(&drvData->work);
HdfWorkQueueDestroy(&drvData->workQueue);
(void)OsalMutexDestroy(&drvData->mutex);
OsalMemFree(drvData);
(void)OsalMemFree(drvData);
g_lightDrvData = NULL;
}
```
......
# TOUCHSCREEN<a name="ZH-CN_TOPIC_0000001052857350"></a>
# Touchscreen
- [概述](#section175431838101617)
- [接口说明](#section105459441659)
- [开发步骤](#section65745222184)
- [开发实例](#section263714411191)
- [设备描述配置](#section18249155619195)
- [板级配置及器件私有配置](#section3571192072014)
- [添加器件驱动](#section6356758162015)
## 概述
## 概述<a name="section175431838101617"></a>
- **Touchscreen驱动主要任务**
Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定Input相关配置、下载及更新固件等操作。
- **Touchscreen驱动主要任务**
- **Touchscreen驱动模型说明**
本节主要介绍基于Input驱动模型开发Touchscreen器件驱动,Input模型整体的框架如下图所示。
Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定Input相关配置、下载及更新固件等操作
Input驱动模型基于HDF驱动框架、Platform接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层Input Service可以通过HDI接口层获取相应的驱动能力,进而操控Touchscreen等输入设备
**图1** 基于HDF驱动框架的Input驱动模型
- **Touchscreen驱动层次说明**
![zh-cn_image_0000001123742904](figures/zh-cn_image_0000001123742904.png)
本节主要介绍基于Input驱动模型开发touchscreen器件驱动,Input模型整体的框架如[图1](#fig6251184817261)。
- **Input驱动模型介绍**
Input驱动模型基于HDF驱动框架、Platform接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层Input service可以通过HDI接口层获取相应的驱动能力,进而操控touchscreen等输入设备。
Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明:
- Input设备管理:为各类输入设备驱动提供Input设备的注册、注销接口,同时统一管理Input设备列表。
- Input平台驱动:指各类Input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册Input设备等。
- Input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化。
- Input数据通道:提供一套通用的数据上报通道,各类别的Input设备驱动均可用此通道上报Input事件。
- Input配置解析:负责对Input设备的板级配置及器件私有配置进行解析及管理。
**图 1** 基于HDF驱动框架的Input驱动模型<a name="fig6251184817261"></a>
![](figures/基于HDF驱动框架的input驱动模型.png "基于HDF驱动框架的input驱动模型")
- **基于HDF驱动框架开发器件驱动的优势**
- **Input驱动模型介绍**
在HDF(Hardware Driver Foundation)[驱动管理框架](../driver/driver-hdf-development.md)的基础上,Input驱动模型调用OSAL接口层和Platform接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于Input驱动模型实现的Touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。
Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明:
- Input设备管理:为各类输入设备驱动提供Input设备的注册、注销接口,同时统一管理Input设备列表。
## 接口说明
- Input平台驱动:指各类Input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册Input设备等。
- Input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化。
- Input数据通道:提供一套通用的数据上报通道,各类别的Input设备驱动均可用此通道上报Input事件。
- Input配置解析:负责对Input设备的板级配置及器件私有配置进行解析及管理。
- **基于HDF驱动框架开发器件驱动的优势**
在HDF(Hardware Driver Foundation)[驱动管理框架](driver-hdf-development.md)的基础上,Input驱动模型调用OSAL接口层和Platfom接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于Input驱动模型实现的touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。
Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类:
- 电源接口
## 接口说明<a name="section105459441659"></a>
- IO控制接口
Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类:
- 通信接口
- 电源接口
- IO控制接口
- 通信接口
**图2** Touchscreen器件常用管脚
**图 2** Touchscreen器件常用管脚<a name="fig1290384314416"></a>
![](figures/Touchscreen器件常用管脚.png "Touchscreen器件常用管脚")
![zh-cn_image_0000001192846991](figures/zh-cn_image_0000001192846991.png)
如上图所示的三类接口,分别做简要说明如下:
1. **电源接口**
- LDO\_1P8:1.8V数字电路
- LDO\_3P3:3.3V模拟电路
1. **电源接口**
- LDO_1P8:1.8V数字电路
- LDO_3P3:3.3V模拟电路
通常情况下,Touchscreenreen驱动IC和LCD驱动IC是相互分离的,这种情况下,Touchscreen驱动IC一般同时需要1.8V和3.3V两路供电。随着芯片演进,业内已有Touchscreen驱动IC和LCD驱动IC集成在一颗IC中的芯片案例,对Touchscreen而言,只需要关注1.8V供电即可,其内部需要的3.3V电源,会在驱动IC内部从LCD的VSP电源(典型值5.5V)中分出来。
通常情况下,touchscreen驱动IC和LCD驱动IC是相互分离的,这种情况下,touchscreen驱动IC一般同时需要1.8V和3.3V两路供电。随着芯片演进,业内已有touchscreen驱动IC和LCD驱动IC集成在一颗IC中的芯片案例,对touchscreen而言,只需要关注1.8V供电即可,其内部需要的3.3V电源,会在驱动IC内部从LCD的VSP电源(典型值5.5V)中分出来。
2. **IO控制接口**
- Reset:reset管脚,用于在系统休眠、唤醒时,由主机侧对驱动IC进行复位操作。
- INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作。
2. **IO控制接口**
- Reset:reset管脚,用于在系统休眠、唤醒时,由主机侧对驱动IC进行复位操作
- INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作
3. **通信接口**
- I2C:由于Touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](../driver/driver-platform-i2c-des.md#概述)
- SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](../driver/driver-platform-spi-des.md#概述)
3. **通信接口**
- I2C:由于touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](driver-platform-i2c-des.md#section5361140416)
- SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](driver-platform-spi-des.md#section193356154511)
## 开发步骤
## 开发步骤<a name="section65745222184"></a>
Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为Touchscreen等输入器件提供统一的驱动开发架构。
Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为touchscreen等输入器件提供统一的驱动开发架构。
如下以touchscreen器件驱动为例,说明Input驱动模型的完整加载流程:
如下以Touchscreen器件驱动为例,说明Input驱动模型的完整加载流程:
(1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。
......@@ -94,26 +80,25 @@ Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区
请参考如下相关步骤:
1. 设备描述配置
目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。驱动的相关配置请参考[HDF驱动框架配置指导](driver-hdf-development.md#section1969312275533)。
1. 设备描述配置
目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。驱动的相关配置请参考[HDF驱动框架配置指导](../driver/driver-hdf-development.md#驱动开发步骤)
2. 板级配置及Touchscreen器件私有配置
2. 板级配置及Touchscreen器件私有配置
配置对应的IO管脚功能,例如对单板上为Touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。
配置对应的IO管脚功能,例如对单板上为touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。
3. 实现器件差异化适配接口
根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](../driver/driver-platform-gpio-des.md#概述)
3. 实现器件差异化适配接口
根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](driver-platform-gpio-des.md#section1635911016188)
## 开发实例
本实例提供Touchscreen驱动开发示例,并简要对具体关键点进行开发说明。
## 开发实例<a name="section263714411191"></a>
本实例提供touchscreen驱动开发示例,并简要对具体关键点进行开发说明。
### 设备描述配置
### 设备描述配置<a name="section18249155619195"></a>
如下配置主要包含Input驱动模型各模块层级信息,具体原理可参考[HDF驱动开发指南](../driver/driver-hdf-development.md),HDF框架依据该配置信息实现对Input模型各模块的依次加载等。
如下配置主要包含Input驱动模型各模块层级信息,具体原理可参考[HDF驱动开发指南](driver-hdf-development.md),HDF框架依据该配置信息实现对Input模型各模块的依次加载等。
```
input :: host {
......@@ -156,10 +141,12 @@ input :: host {
}
```
### 板级配置及器件私有配置<a name="section3571192072014"></a>
### 板级配置及器件私有配置
如下配置包含板级硬件配置及器件私有数据配置,实际业务开发时,可根据具体需求增删及修改如下配置文件信息。
```
root {
input_config {
......@@ -245,10 +232,12 @@ root {
}
```
### 添加器件驱动<a name="section6356758162015"></a>
### 添加器件驱动
在器件驱动中,主要实现了平台预留的差异化接口,以器件数据获取及解析进行示例说明。具体开发过程,需要根据实际使用的单板及器件进行适配。
```
/* 将从器件中读取到的报点数据解析为坐标 */
static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum)
......@@ -402,4 +391,3 @@ struct HdfDriverEntry g_touchSampleChipEntry = {
HDF_INIT(g_touchSampleChipEntry);
```
# 外设驱动使用<a name="ZH-CN_TOPIC_0000001157319411"></a>
# 外设驱动使用
- **[LCD](driver-peripherals-lcd-des.md)**
- **[TOUCHSCREEN](driver-peripherals-touch-des.md)**
- **[SENSOR](driver-peripherals-sensor-des.md)**
- **[LCD](driver-peripherals-lcd-des.md)**
- **[WLAN](driver-peripherals-external-des.md)**
- **[Touchscreen](driver-peripherals-touch-des.md)**
- **[AUDIO](driver-peripherals-audio-des.md)**
\ No newline at end of file
- **[SENSOR](driver-peripherals-sensor-des.md)**
- **[WLAN](driver-peripherals-external-des.md)**
- **[USB](driver-peripherals-usb-des.md)**
\ No newline at end of file
# I2C<a name="ZH-CN_TOPIC_0000001206171515"></a>
# I2C
- [概述](#section5361140416)
- [接口说明](#section545869122317)
- [使用指导](#section1695201514281)
- [使用流程](#section1338373417288)
- [打开I2C控制器](#section13751110132914)
- [进行I2C通信](#section9202183372916)
- [关闭I2C控制器](#section19481164133018)
- [使用实例](#section5302202015300)
## 概述
## 概述<a name="section5361140416"></a>
- I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。
- I2C\(Inter Integrated Circuit\)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。
- I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA\(SerialData\)串行数据线以及SCL\(SerialClock\)串行时钟线两根线相连,如[图1 ](#fig1135561232714)所示。
- I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA(SerialData)串行数据线以及SCL(SerialClock)串行时钟线两根线相连,如图1所示。
- I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。
- I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。
- I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。
- I2C接口定义了完成I2C传输的通用方法集合,包括:
- I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。
- I2C控制器管理: 打开或关闭I2C控制器
- I2C消息传输:通过消息传输结构体数组进行自定义传输
- I2C接口定义了完成I2C传输的通用方法集合,包括:
- I2C控制器管理: 打开或关闭I2C控制器
- I2C消息传输:通过消息传输结构体数组进行自定义传输
**图 1** I2C物理连线示意图<a name="fig1135561232714"></a>
![](figures/I2C物理连线示意图.png "I2C物理连线示意图")
**图1** I2C物理连线示意图
![zh-cn_image_0000001160653004](figures/zh-cn_image_0000001160653004.png)
## 接口说明<a name="section545869122317"></a>
**表 1** I2C驱动API接口功能介绍
## 接口说明
<a name="table1731550155318"></a>
<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" valign="top" width="18.63%" id="mcps1.2.4.1.1"><p id="p641050105320"><a name="p641050105320"></a><a name="p641050105320"></a>功能分类</p>
</th>
<th class="cellrowborder" valign="top" width="28.03%" id="mcps1.2.4.1.2"><p id="p54150165315"><a name="p54150165315"></a><a name="p54150165315"></a>接口名</p>
</th>
<th class="cellrowborder" valign="top" width="53.339999999999996%" id="mcps1.2.4.1.3"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row34145016535"><td class="cellrowborder" rowspan="2" valign="top" width="18.63%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>I2C控制器管理接口</p>
</td>
<td class="cellrowborder" valign="top" width="28.03%" headers="mcps1.2.4.1.2 "><p id="p19389143041518"><a name="p19389143041518"></a><a name="p19389143041518"></a>I2cOpen</p>
</td>
<td class="cellrowborder" valign="top" width="53.339999999999996%" headers="mcps1.2.4.1.3 "><p id="p8738101941716"><a name="p8738101941716"></a><a name="p8738101941716"></a>打开I2C控制器</p>
</td>
</tr>
<tr id="row5632152611414"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p143890309153"><a name="p143890309153"></a><a name="p143890309153"></a>I2cClose</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p573815197171"><a name="p573815197171"></a><a name="p573815197171"></a>关闭I2C控制器</p>
</td>
</tr>
<tr id="row15108165391412"><td class="cellrowborder" valign="top" width="18.63%" headers="mcps1.2.4.1.1 "><p id="p91084533141"><a name="p91084533141"></a><a name="p91084533141"></a>I2c消息传输接口</p>
</td>
<td class="cellrowborder" valign="top" width="28.03%" headers="mcps1.2.4.1.2 "><p id="p13901730101511"><a name="p13901730101511"></a><a name="p13901730101511"></a>I2cTransfer</p>
</td>
<td class="cellrowborder" valign="top" width="53.339999999999996%" headers="mcps1.2.4.1.3 "><p id="p12738111912171"><a name="p12738111912171"></a><a name="p12738111912171"></a>自定义传输</p>
</td>
</tr>
</tbody>
</table>
**表1** I2C驱动API接口功能介绍
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
| 功能分类 | 接口描述 |
| -------- | -------- |
| I2C控制器管理接口 | -&nbsp;I2cOpen:打开I2C控制器<br/>-&nbsp;I2cClose:关闭I2C控制器 |
| I2C消息传输接口 | I2cTransfer:自定义传输 |
## 使用指导<a name="section1695201514281"></a>
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
### 使用流程<a name="section1338373417288"></a>
使用I2C设备的一般流程如[图2](#fig183017194234)所示。
## 使用指导
**图 2** I2C设备使用流程图<a name="fig183017194234"></a>
![](figures/I2C设备使用流程图.png "I2C设备使用流程图")
### 打开I2C控制器<a name="section13751110132914"></a>
### 使用流程
使用I2C设备的一般流程如下图所示。
**图2** I2C设备使用流程图
![zh-cn_image_0000001206291495](figures/zh-cn_image_0000001206291495.png)
### 打开I2C控制器
在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。
DevHandle I2cOpen\(int16\_t number\);
**表 2** I2cOpen参数和返回值描述
<a name="table7603619123820"></a>
<table><thead align="left"><tr id="row1060351914386"><th class="cellrowborder" valign="top" width="20.66%" id="mcps1.2.3.1.1"><p id="p14603181917382"><a name="p14603181917382"></a><a name="p14603181917382"></a><strong id="b16510829133012"><a name="b16510829133012"></a><a name="b16510829133012"></a>参数</strong></p>
</th>
<th class="cellrowborder" valign="top" width="79.34%" id="mcps1.2.3.1.2"><p id="p36031519183819"><a name="p36031519183819"></a><a name="p36031519183819"></a><strong id="b65222293309"><a name="b65222293309"></a><a name="b65222293309"></a>参数描述</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row1960431983813"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p3604719123817"><a name="p3604719123817"></a><a name="p3604719123817"></a>number</p>
</td>
<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p221392414442"><a name="p221392414442"></a><a name="p221392414442"></a>I2C控制器号</p>
</td>
</tr>
<tr id="row11410612183019"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p460381915385"><a name="p460381915385"></a><a name="p460381915385"></a><strong id="b4349113243013"><a name="b4349113243013"></a><a name="b4349113243013"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p96031619153812"><a name="p96031619153812"></a><a name="p96031619153812"></a><strong id="b63502322308"><a name="b63502322308"></a><a name="b63502322308"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row15410111273017"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p1060418195389"><a name="p1060418195389"></a><a name="p1060418195389"></a>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p760471912388"><a name="p760471912388"></a><a name="p760471912388"></a>打开I2C控制器失败</p>
</td>
</tr>
<tr id="row1241081213303"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p5604719133811"><a name="p5604719133811"></a><a name="p5604719133811"></a>设备句柄</p>
</td>
<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p3604181933818"><a name="p3604181933818"></a><a name="p3604181933818"></a>打开的I2C控制器设备句柄</p>
</td>
</tr>
</tbody>
</table>
DevHandle I2cOpen(int16_t number);
**表2** I2cOpen参数和返回值描述
| **参数** | **参数描述** |
| -------- | -------- |
| number | I2C控制器号 |
| **返回值** | **返回值描述** |
| NULL | 打开I2C控制器失败 |
| 设备句柄 | 打开的I2C控制器设备句柄 |
假设系统中存在8个I2C控制器,编号从0到7,那么我们现在获取3号控制器
```
DevHandle i2cHandle = NULL; /* I2C控制器句柄 /
......@@ -125,56 +74,27 @@ if (i2cHandle == NULL) {
}
```
### 进行I2C通信<a name="section9202183372916"></a>
### 进行I2C通信
消息传输
int32\_t I2cTransfer\(DevHandle handle, struct I2cMsg \*msgs, int16\_t count\);
**表 3** I2cTransfer参数和返回值描述
<a name="table1934414174212"></a>
<table><thead align="left"><tr id="row1134415176216"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p13295152320217"><a name="p13295152320217"></a><a name="p13295152320217"></a><strong id="b17389641205115"><a name="b17389641205115"></a><a name="b17389641205115"></a>参数</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p1295112352115"><a name="p1295112352115"></a><a name="p1295112352115"></a><strong id="b19401541175118"><a name="b19401541175118"></a><a name="b19401541175118"></a>参数描述</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row5344101702113"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19295132382111"><a name="p19295132382111"></a><a name="p19295132382111"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1051172572919"><a name="p1051172572919"></a><a name="p1051172572919"></a>I2C控制器设备句柄</p>
</td>
</tr>
<tr id="row17344171722117"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p9295122332113"><a name="p9295122332113"></a><a name="p9295122332113"></a>msgs</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p202951238218"><a name="p202951238218"></a><a name="p202951238218"></a>待传输数据的消息结构体数组</p>
</td>
</tr>
<tr id="row45812466213"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1659246112117"><a name="p1659246112117"></a><a name="p1659246112117"></a>count</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p259124622119"><a name="p259124622119"></a><a name="p259124622119"></a>消息数组长度</p>
</td>
</tr>
<tr id="row04701426105110"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17295142322113"><a name="p17295142322113"></a><a name="p17295142322113"></a><strong id="b2159044145115"><a name="b2159044145115"></a><a name="b2159044145115"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p142959232211"><a name="p142959232211"></a><a name="p142959232211"></a><strong id="b16160044135114"><a name="b16160044135114"></a><a name="b16160044135114"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row74701226125110"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p929532313211"><a name="p929532313211"></a><a name="p929532313211"></a>正整数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p829512237217"><a name="p829512237217"></a><a name="p829512237217"></a>成功传输的消息结构体数目</p>
</td>
</tr>
<tr id="row204701126195115"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p12958234217"><a name="p12958234217"></a><a name="p12958234217"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1295192312112"><a name="p1295192312112"></a><a name="p1295192312112"></a>执行失败</p>
</td>
</tr>
</tbody>
</table>
int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count);
**表3** I2cTransfer参数和返回值描述
| **参数** | **参数描述** |
| -------- | -------- |
| handle | I2C控制器设备句柄 |
| msgs | 待传输数据的消息结构体数组 |
| count | 消息数组长度 |
| **返回值** | **返回值描述** |
| 正整数 | 成功传输的消息结构体数目 |
| 负数 | 执行失败 |
I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。
```
int32_t ret;
uint8_t wbuff[2] = { 0x12, 0x13 };
......@@ -196,58 +116,54 @@ if (ret != 2) {
}
```
>![](../public_sys-resources/icon-caution.gif) **注意:**
>- I2cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。
>- 本函数不对消息结构体个数count做限制,其最大个数度由具体I2C控制器决定。
>- 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I2C控制器决定。
>- 本函数可能会引起系统休眠,不允许在中断上下文调用
> ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**
> - I2cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。
>
> - 本函数不对消息结构体个数count做限制,其最大个数度由具体I2C控制器决定。
>
> - 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I2C控制器决定。
>
> - 本函数可能会引起系统休眠,不允许在中断上下文调用
### 关闭I2C控制器<a name="section19481164133018"></a>
### 关闭I2C控制器
I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所示:
void I2cClose\(DevHandle handle\);
**表 4** I2cClose参数和返回值描述
<a name="table72517953115"></a>
<table><thead align="left"><tr id="row1525793312"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p115402031153111"><a name="p115402031153111"></a><a name="p115402031153111"></a>参数</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p65406313319"><a name="p65406313319"></a><a name="p65406313319"></a>参数描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row1926109193116"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p105419317318"><a name="p105419317318"></a><a name="p105419317318"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1213245577"><a name="p1213245577"></a><a name="p1213245577"></a>I2C控制器设备句柄</p>
</td>
</tr>
</tbody>
</table>
void I2cClose(DevHandle handle);
**表4** I2cClose参数和返回值描述
| 参数 | 参数描述 |
| -------- | -------- |
| handle | I2C控制器设备句柄 |
```
I2cClose(i2cHandle); /* 关闭I2C控制器 */
```
## 使用实例<a name="section5302202015300"></a>
## 使用实例
本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。
本例拟对Hi3516DV300某开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下:
- SOC:hi3516dv300。
- SOC:hi3516dv300。
- Touch IC:I2C地址为0x38, IC内部寄存器位宽为1字节。
- Touch IC:I2C地址为0x38, IC内部寄存器位宽为1字节。
- 原理图信息:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO。
- 原理图信息:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO。
本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。
>![](../public_sys-resources/icon-note.gif) **说明:**
>本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。
示例如下:
```
#include "i2c_if.h" /* I2C标准接口头文件 */
#include "gpio_if.h" /* GPIO标准接口头文件 */
......@@ -420,4 +336,3 @@ static int32_t TestCaseI2c(void)
return ret;
}
```
# 平台驱动使用<a name="ZH-CN_TOPIC_0000001111199424"></a>
# 平台驱动使用
- **[ADC](driver-platform-adc-des.md)**
- **[DAC](driver-platform-dac-des.md)**
- **[GPIO](driver-platform-gpio-des.md)**
- **[GPIO](driver-platform-gpio-des.md)**
- **[HDMI](driver-platform-hdmi-des.md)**
- **[I2C](driver-platform-i2c-des.md)**
- **[I2C](driver-platform-i2c-des.md)**
- **[RTC](driver-platform-rtc-des.md)**
- **[I3C](driver-platform-i3c-des.md)**
- **[SDIO](driver-platform-sdio-des.md)**
- **[MIPI-CSI](driver-platform-mipicsi-des.md)**
- **[SPI](driver-platform-spi-des.md)**
- **[MIPI-DSI](driver-platform-mipidsi-des.md)**
- **[UART](driver-platform-uart-des.md)**
- **[PIN](driver-platform-pin-des.md)**
- **[Watchdog](driver-platform-watchdog-des.md)**
- **[PWM](driver-platform-pwm-des.md)**
- **[MIPI DSI](driver-platform-mipidsi-des.md)**
- **[RTC](driver-platform-rtc-des.md)**
- **[SDIO](driver-platform-sdio-des.md)**
- **[SPI](driver-platform-spi-des.md)**
- **[UART](driver-platform-uart-des.md)**
- **[WATCHDOG](driver-platform-watchdog-des.md)**
- **[PWM](driver-platform-pwm-des.md)**
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册