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

切纯净版

Signed-off-by: Nduangavin123 <duanxichao@huawei.com>
上级 ddf1e404
# 驱动使用指南 # 驱动使用指南
- [HDF驱动框架](driver-hdf.md) - HDF驱动框架
- [HDF开发概述](driver-hdf-overview.md) - [HDF开发概述](driver-hdf-overview.md)
- [驱动开发](driver-hdf-development.md) - [驱动开发](driver-hdf-development.md)
- [驱动服务管理](driver-hdf-servicemanage.md) - [驱动服务管理](driver-hdf-servicemanage.md)
- [驱动消息机制管理](driver-hdf-message-management.md) - [驱动消息机制管理](driver-hdf-message-management.md)
- [配置管理](driver-hdf-manage.md) - [配置管理](driver-hdf-manage.md)
- [HDF开发实例](driver-hdf-sample.md) - [HDF开发实例](driver-hdf-sample.md)
- [平台驱动开发](driver-develop.md) - 平台驱动开发
- [ADC](driver-platform-adc-develop.md) - [ADC](driver-platform-adc-develop.md)
- [DAC](driver-platform-dac-develop.md) - [DAC](driver-platform-dac-develop.md)
- [GPIO](driver-platform-gpio-develop.md) - [GPIO](driver-platform-gpio-develop.md)
- [HDMI](driver-platform-hdmi-develop.md) - [HDMI](driver-platform-hdmi-develop.md)
- [I2C](driver-platform-i2c-develop.md) - [I2C](driver-platform-i2c-develop.md)
- [I3C](driver-platform-i3c-develop.md) - [I3C](driver-platform-i3c-develop.md)
- [MIPI-CSI](driver-platform-mipicsi-develop.md) - [MIPI CSI](driver-platform-mipicsi-develop.md)
- [MIPI-DSI](driver-platform-mipidsi-develop.md) - [MIPI DSI](driver-platform-mipidsi-develop.md)
- [MMC](driver-platform-mmc-develop.md) - [MMC](driver-platform-mmc-develop.md)
- [PIN](driver-platform-pin-develop.md) - [PIN](driver-platform-pin-develop.md)
- [PWM](driver-platform-pwm-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) - [RTC](driver-platform-rtc-develop.md)
- [SDIO](driver-platform-sdio-develop.md) - [SDIO](driver-platform-sdio-develop.md)
- [SPI](driver-platform-spi-develop.md) - [SPI](driver-platform-spi-develop.md)
- [UART](driver-platform-uart-develop.md) - [UART](driver-platform-uart-develop.md)
- [WatchDog](driver-platform-watchdog-develop.md) - [WatchDog](driver-platform-watchdog-develop.md)
- [平台驱动使用](driver-platform.md) - 平台驱动使用
- [ADC](driver-platform-adc-des.md) - [ADC](driver-platform-adc-des.md)
- [DAC](driver-platform-dac-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) - [HDMI](driver-platform-hdmi-des.md)
- [I2C](driver-platform-i2c-des.md) - [I2C](driver-platform-i2c-des.md)
- [I3C](driver-platform-i3c-des.md) - [I3C](driver-platform-i3c-des.md)
- [MIPI-CSI](driver-platform-mipicsi-des.md) - [MIPI CSI](driver-platform-mipicsi-des.md)
- [MIPI-DSI](driver-platform-mipidsi-des.md) - [MIPI DSI](driver-platform-mipidsi-des.md)
- [PIN](driver-platform-pin-des.md) - [PIN](driver-platform-pin-des.md)
- [PWM](driver-platform-pwm-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) - [RTC](driver-platform-rtc-des.md)
- [SDIO](driver-platform-sdio-des.md) - [SDIO](driver-platform-sdio-des.md)
- [SPI](driver-platform-spi-des.md) - [SPI](driver-platform-spi-des.md)
- [UART](driver-platform-uart-des.md) - [UART](driver-platform-uart-des.md)
- [WATCHDOG](driver-platform-watchdog-des.md) - [WatchDog](driver-platform-watchdog-des.md)
- [外设驱动使用](driver-peripherals.md) - 外设驱动使用
- [LCD](driver-peripherals-lcd-des.md) - [LCD](driver-peripherals-lcd-des.md)
- [TOUCHSCREEN](driver-peripherals-touch-des.md) - [Touchscreen](driver-peripherals-touch-des.md)
- [SENSOR](driver-peripherals-sensor-des.md) - [Sensor](driver-peripherals-sensor-des.md)
- [WLAN](driver-peripherals-external-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) - [USB](driver-peripherals-usb-des.md)
- [CAMERA](driver-peripherals-camera-des.md) - [Camera](driver-peripherals-camera-des.md)
- [VIBRATOR](driver-peripherals-vibrator-des.md) - [Vibrator](driver-peripherals-vibrator-des.md)
- [LIGHT](driver-peripherals-light-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)**
- **[MIPI-DSI](driver-platform-mipidsi-develop.md)**
- **[MMC](driver-platform-mmc-develop.md)** - **[MMC](driver-platform-mmc-develop.md)**
......
# 驱动开发<a name="ZH-CN_TOPIC_0000001051930361"></a> # 驱动开发
- [驱动模型介绍](#section157425168112)
- [驱动开发步骤](#section1969312275533)
## 驱动模型介绍<a name="section157425168112"></a> ## 驱动模型介绍
HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node,HDF驱动模型如下图所示: HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node,HDF驱动模型如下图所示:
**图 1** HDF驱动模型<a name="fig3580184214210"></a> **图1** HDF驱动模型
![](figures/HDF驱动模型.png "HDF驱动模型")
## 驱动开发步骤<a name="section1969312275533"></a> ![zh-cn_image_0000001153947412](figures/zh-cn_image_0000001153947412.png)
基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,详细开发流程如下所示:
1. <a name="li35182436435"></a>驱动实现 ## 驱动开发步骤
基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,详细开发流程如下所示:
1. 驱动实现
驱动实现包含驱动业务代码和驱动入口注册,具体写法如下: 驱动实现包含驱动业务代码和驱动入口注册,具体写法如下:
- 驱动业务代码 - 驱动业务代码
``` ```
#include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件 #include "hdf_device_desc.h" // HDF框架对驱动开发相关能力接口的头文件
#include "hdf_log.h" // HDF 框架提供的日志接口头文件 #include "hdf_log.h" // HDF 框架提供的日志接口头文件
#define HDF_LOG_TAG "sample_driver" // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签 #define HDF_LOG_TAG "sample_driver" // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签
...@@ -47,7 +46,6 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 ...@@ -47,7 +46,6 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提
return; return;
} }
``` ```
- 驱动入口注册到HDF框架 - 驱动入口注册到HDF框架
``` ```
...@@ -65,15 +63,13 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 ...@@ -65,15 +63,13 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提
``` ```
2. 驱动编译 2. 驱动编译
- liteos - liteos
涉及makefile和BUILD.gn修改:
涉及makefile和BUILD.gn修改: - makefile部分:
* makefile部分:
驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。 驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。
``` ```
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk #导入hdf预定义内容,必需 include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk #导入hdf预定义内容,必需
MODULE_NAME := #生成的结果文件 MODULE_NAME := #生成的结果文件
...@@ -85,15 +81,16 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 ...@@ -85,15 +81,16 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提
编译结果文件链接到内核镜像,添加到drivers/adapter/khdf/liteos目录下的hdf_lite.mk里面,示例如下: 编译结果文件链接到内核镜像,添加到drivers/adapter/khdf/liteos目录下的hdf_lite.mk里面,示例如下:
``` ```
LITEOS_BASELIB += -lxxx #链接生成的静态库 LITEOS_BASELIB += -lxxx #链接生成的静态库
LIB_SUBDIRS += #驱动代码Makefile的目录 LIB_SUBDIRS += #驱动代码Makefile的目录
``` ```
* BUILD.gn部分: - BUILD.gn部分:
添加模块BUILD.gn参考定义如下内容: 添加模块BUILD.gn参考定义如下内容:
``` ```
import("//build/lite/config/component/lite_component.gni") import("//build/lite/config/component/lite_component.gni")
import("//drivers/adapter/khdf/liteos/hdf.gni") import("//drivers/adapter/khdf/liteos/hdf.gni")
...@@ -114,6 +111,7 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 ...@@ -114,6 +111,7 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提
把新增模块的BUILD.gn所在的目录添加到/drivers/adapter/khdf/liteos/BUILD.gn里面: 把新增模块的BUILD.gn所在的目录添加到/drivers/adapter/khdf/liteos/BUILD.gn里面:
``` ```
group("liteos") { group("liteos") {
public_deps = [ ":$module_name" ] public_deps = [ ":$module_name" ]
...@@ -122,39 +120,36 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 ...@@ -122,39 +120,36 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提
] ]
} }
``` ```
- linux - linux
如果需要定义模块控制宏,需要在模块目录xxx里面添加Kconfig文件,并把Kconfig文件路径添加到drivers/adapter/khdf/linux/Kconfig里面: 如果需要定义模块控制宏,需要在模块目录xxx里面添加Kconfig文件,并把Kconfig文件路径添加到drivers/adapter/khdf/linux/Kconfig里面:
``` ```
source "drivers/hdf/khdf/xxx/Kconfig" #目录为hdf模块软链接到kernel里面的目录 source "drivers/hdf/khdf/xxx/Kconfig" #目录为hdf模块软链接到kernel里面的目录
``` ```
添加模块目录到drivers/adapter/khdf/linux/Makefile: 添加模块目录到drivers/adapter/khdf/linux/Makefile:
``` ```
obj-$(CONFIG_DRIVERS_HDF) += xxx/ obj-$(CONFIG_DRIVERS_HDF) += xxx/
``` ```
在模块目录xxx里面添加Makefile文件,在Makefile文件里面添加模块代码编译规则: 在模块目录xxx里面添加Makefile文件,在Makefile文件里面添加模块代码编译规则:
``` ```
obj-y += xxx.o obj-y += xxx.o
``` ```
3. 驱动配置 3. 驱动配置
HDF使用HCS作为配置描述源码,HCS详细介绍参考[配置管理](../driver/driver-hdf-manage.md)介绍。
HDF使用HCS作为配置描述源码,HCS详细介绍参考[配置管理](driver-hdf-manage.md)介绍。
驱动配置包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息,具体写法如下: 驱动配置包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息,具体写法如下:
- 驱动设备描述(必选) - 驱动设备描述(必选)
HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示:
HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device\_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示:
``` ```
root { root {
...@@ -193,10 +188,9 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 ...@@ -193,10 +188,9 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提
} }
} }
``` ```
- 驱动私有配置信息(可选) - 驱动私有配置信息(可选)
如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考步骤1)传递给驱动,驱动的配置信息示例如下:
如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](#li35182436435))传递给驱动,驱动的配置信息示例如下:
``` ```
root { root {
...@@ -210,35 +204,18 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 ...@@ -210,35 +204,18 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提
配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs(这一块可以通过OpenHarmony驱动子系统在DevEco集成驱动开发套件工具一键式配置,具体使用方法参考驱动开发套件中的介绍),示例如下: 配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs(这一块可以通过OpenHarmony驱动子系统在DevEco集成驱动开发套件工具一键式配置,具体使用方法参考驱动开发套件中的介绍),示例如下:
``` ```
#include "device_info/device_info.hcs" #include "device_info/device_info.hcs"
#include "sample/sample_config.hcs" #include "sample/sample_config.hcs"
``` ```
4. 用户态驱动服务启动配置
用户态需要把驱动服务配置到文件drivers/adapter/uhdf2/host/hdf_devhostmusl.cfg中,如下: > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 驱动加载方式支持按需加载和按序加载两种方式,具体使用方法如下:
``` >
{ > - 按需加载
"name" : "sample_host", //驱动服务进程名字,和device_info.hcs中配置的hostName对应 >
"dynamic" : true, //动态加载,目前驱动服务只支持动态加载,即由hdf_devmgr在初始化时调用init模块接口启动
"path" : ["/vendor/bin/hdf_devhost"],//hdf_devhost所在的目录
"uid" : "sample_host",//进程的用户ID
"gid" : ["sample_host"],//进程的组ID
"caps" : ["DAC_OVERRIDE", "DAC_READ_SEARCH"]//进程的Linux capabilities配置
}
```
进程的用户ID在文件base/startup/init_lite/services/etc/passwd中配置,进程的组ID在文件base/startup/init_lite/services/etc/group中配置,进程用户ID和组ID配置参考:[系统服务用户组添加方法](https://gitee.com/openharmony/startup_init_lite/wikis)
>![](../public_sys-resources/icon-note.gif) **说明:**
>驱动加载方式支持按需加载和按序加载两种方式,具体使用方法如下:
>- 按需加载
> ``` > ```
> typedef enum { > typedef enum {
> DEVICE_PRELOAD_ENABLE = 0, > DEVICE_PRELOAD_ENABLE = 0,
...@@ -247,7 +224,8 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 ...@@ -247,7 +224,8 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提
> DEVICE_PRELOAD_INVALID > DEVICE_PRELOAD_INVALID
> } DevicePreload; > } DevicePreload;
> ``` > ```
> 配置文件中preload 字段配成 0 (DEVICE\_PRELOAD\_ENABLE ),则系统启动过程中默认加载;配成1(DEVICE\_PRELOAD\_ENABLE\_STEP2),当系统支持快启的时候,则在系统完成之后再加载这一类驱动,否则和DEVICE\_PRELOAD\_ENABLE 含义相同;配成2(DEVICE\_PRELOAD\_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](driver-hdf-message-management.md))时,如果驱动服务不存在时,HDF框架会尝试动态加载该驱动。 >
>- 按序加载(需要驱动为默认加载) > 配置文件中preload 字段配成 0(DEVICE_PRELOAD_ENABLE),则系统启动过程中默认加载;配成1(DEVICE_PRELOAD_ENABLE_STEP2),当系统支持快启的时候,则在系统完成之后再加载这一类驱动,否则和DEVICE_PRELOAD_ENABLE含义相同;配成2(DEVICE_PRELOAD_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](../driver/driver-hdf-message-management.md))时,如果驱动服务不存在,HDF框架会尝试动态加载该驱动。
>
> - 按序加载(需要驱动为默认加载)
> 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。 > 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。
# 配置管理<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为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。
HC-GEN**\(H**DF **C**onfiguration **G**enerator**\)**是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式:
- 在弱性能环境中,转换为配置树源码或配置树宏定义,驱动可直接调用C代码或宏式APIs获取配置。 - 在弱性能环境中,转换为配置树源码或配置树宏定义,驱动可直接调用C代码或宏式APIs获取配置。
- 在高性能环境中,转换为HCB\(**H**DF **C**onfiguration **B**inary\)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。
- 在高性能环境中,转换为HCB(HDF Configuration Binary)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。
以下是使用HCB模式的典型应用场景: 以下是使用HCB模式的典型应用场景:
**图 1** 配置使用流程图<a name="fig772653312159"></a> **图1** 配置使用流程图
![](figures/配置使用流程图.png "配置使用流程图")
![zh-cn_image_0000001154105768](figures/zh-cn_image_0000001154105768.png)
HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。 HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。
## 配置语法<a name="section533713333580"></a>
## 配置语法
HCS的语法介绍如下: HCS的语法介绍如下:
### 关键字<a name="section4522107333"></a>
### 关键字
HCS配置语法保留了以下关键字。 HCS配置语法保留了以下关键字。
**表 1** 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> | root | 配置根节点 | - |
<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> | include | 引用其他HCS配置文件 | - |
</th> | delete | 删除节点或属性 | 只能用于操作include导入的配置树 |
<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> | template | 定义模板节点 | - |
</th> | match_attr | 用于标记节点的匹配查找属性 | 解析配置时可以使用该属性的值查找到对应节点 |
</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> HCS主要分为属性(Attribute)和节点(Node)两种结构。
</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\)两种结构。
**属性** **属性**
属性即最小的配置单元,是一个独立的配置项。语法如下: 属性即最小的配置单元,是一个独立的配置项。语法如下:
``` ```
attribute_name = value; attribute_name = value;
``` ```
- attribute\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 - attribute_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。
- value的可用格式如下: - value的可用格式如下:
- 数字常量,支持二进制、八进制、十进制、十六进制数,具体参考数据类型节。 - 数字常量,支持二进制、八进制、十进制、十六进制数,具体参考数据类型节。
- 字符串,内容使用双引号("")引用。
- 字符串,内容使用双引号\(""\)引用。
- 节点引用。 - 节点引用。
- attribute 必须以分号(;)结束且必须属于一个node。
- attribute 必须以分号\(;\)结束且必须属于一个node。
**节点** **节点**
节点是一组属性的集合,语法如下: 节点是一组属性的集合,语法如下:
``` ```
node_name { node_name {
module = "sample"; module = "sample";
...@@ -127,7 +75,7 @@ HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。 ...@@ -127,7 +75,7 @@ HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。
} }
``` ```
- node\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 - node_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。
- 大括号后无需添加结束符“;”。 - 大括号后无需添加结束符“;”。
...@@ -135,31 +83,32 @@ HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。 ...@@ -135,31 +83,32 @@ HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。
- root节点中必须包含module属性,其值应该为一个字符串,用于表征该配置所属模块。 - root节点中必须包含module属性,其值应该为一个字符串,用于表征该配置所属模块。
- 节点中可以增加match\_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点。 - 节点中可以增加match_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点。
### 数据类型<a name="section177001259134"></a>
### 数据类型
在属性定义中使用自动数据类型,不显式指定类型,属性支持的数据类型如下: 在属性定义中使用自动数据类型,不显式指定类型,属性支持的数据类型如下:
**整型** **整型**
整型长度自动推断,根据实际数据长度给与最小空间占用的类型。 整型长度自动推断,根据实际数据长度给与最小空间占用的类型。
- 二进制,0b前缀,示例:0b1010。 - 二进制,0b前缀,示例:0b1010。
- 八进制,0前缀,示例:0664。 - 八进制,0前缀,示例:0664。
- 十进制 ,无前缀,且支持有符号与无符号,示例:1024,+1024均合法。负值在读取时注意使用有符号数读取接口。 - 十进制 ,无前缀,且支持有符号与无符号,示例:1024,+1024均合法。负值在读取时注意使用有符号数读取接口。
- 十六进制,0x前缀,示例:0xff00、0xFF。 - 十六进制,0x前缀,示例:0xff00、0xFF。
**字符串** **字符串**
字符串使用双引号\(""\)表示。 字符串使用双引号("")表示。
**数组** **数组**
数组元素支持整型、字符串,不支持混合类型。整型数组中uint32\_t uint64\_t混用会向上转型为uint64\_t 数组。整型数组与字符串数组示例如下: 数组元素支持整型、字符串,不支持混合类型。整型数组中uint32_t uint64_t混用会向上转型为uint64_t 数组。整型数组与字符串数组示例如下:
``` ```
attr_foo = [0x01, 0x02, 0x03, 0x04]; attr_foo = [0x01, 0x02, 0x03, 0x04];
...@@ -170,51 +119,58 @@ attr_bar = ["hello", "world"]; ...@@ -170,51 +119,58 @@ attr_bar = ["hello", "world"];
bool类型中**true**表示真,**false**表示假。 bool类型中**true**表示真,**false**表示假。
### 预处理<a name="section14867121641"></a>
### 预处理
**include** **include**
用于导入其他HCS文件。语法示例如下: 用于导入其他HCS文件。语法示例如下:
``` ```
#include "foo.hcs" #include "foo.hcs"
#include "../bar.hcs" #include "../bar.hcs"
``` ```
- 文件名必须使用双引号\(""\),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。 - 文件名必须使用双引号(""),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。
- 多个include,如果存在相同的节点,后者覆盖前者,其余的节点依次展开。 - 多个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节点内容的修改。示例如下: 上述语句表示node中的内容是对source_node节点内容的修改。示例如下:
``` ```
root { root {
...@@ -239,6 +195,7 @@ root { ...@@ -239,6 +195,7 @@ root {
最终生成配置树为: 最终生成配置树为:
``` ```
root { root {
module = "sample"; module = "sample";
...@@ -253,20 +210,24 @@ root { ...@@ -253,20 +210,24 @@ 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即为一个合法的绝对路径。 - 引用同级node,可以直接使用node名称,否则被引用的节点必须使用绝对路径,节点间使用“.”分隔,root表示根节点,格式为root开始的节点路径序列,例如root.foo.bar即为一个合法的绝对路径。
- 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。 - 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。
### 节点复制<a name="section1487792020513"></a>
### 节点复制
节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法为: 节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法为:
``` ```
node : source_node node : source_node
``` ```
上述语句表示在定义"node"节点时将另一个节点"source\_node"的属性复制过来。示例如下: 上述语句表示在定义"node"节点时将另一个节点"source_node"的属性复制过来。示例如下:
``` ```
root { root {
...@@ -282,6 +243,7 @@ root { ...@@ -282,6 +243,7 @@ root {
上述代码的最终生成配置树为: 上述代码的最终生成配置树为:
``` ```
root { root {
module = "sample"; module = "sample";
...@@ -295,13 +257,15 @@ root { ...@@ -295,13 +257,15 @@ root {
} }
``` ```
在上述示例中,编译后bar节点即包含attr\_0属性也包含attr\_1属性,在bar中对attr\_0的修改不会影响到foo。 在上述示例中,编译后bar节点即包含attr_0属性也包含attr_1属性,在bar中对attr_0的修改不会影响到foo。
在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#section193708571145) 在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#引用修改)
### 删除<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 // sample2.hcs
...@@ -322,7 +286,8 @@ root { ...@@ -322,7 +286,8 @@ root {
} }
``` ```
上述代码在生成过程中将会删除root.foo\_2节点与attr\_2,最终生成配置树为: 上述代码在生成过程中将会删除root.foo_2节点与attr_2,最终生成配置树为:
``` ```
root { root {
...@@ -330,19 +295,22 @@ root { ...@@ -330,19 +295,22 @@ root {
} }
``` ```
>![](../public_sys-resources/icon-note.gif) **说明:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。 > 在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。
### 属性引用<a name="section20271317611"></a>
### 属性引用
为了在解析配置时快速定位到关联的节点,可以把节点作为属性的右值,通过读取属性查找到对应节点。语法为: 为了在解析配置时快速定位到关联的节点,可以把节点作为属性的右值,通过读取属性查找到对应节点。语法为:
``` ```
attribute = &node; attribute = &node;
``` ```
上述语句表示attribute的值是一个节点node的引用,在解析时可以用这个attribute快速定位到node,便于关联和查询其他node。示例如下: 上述语句表示attribute的值是一个节点node的引用,在解析时可以用这个attribute快速定位到node,便于关联和查询其他node。示例如下:
``` ```
node1 { node1 {
attributes; attributes;
...@@ -351,8 +319,10 @@ node2 { ...@@ -351,8 +319,10 @@ node2 {
attr_1 = &root.node1; attr_1 = &root.node1;
} }
``` ```
``` ```
node2 { node2 {
node1 { node1 {
...@@ -362,12 +332,14 @@ node2 { ...@@ -362,12 +332,14 @@ node2 {
} }
``` ```
### 模板<a name="section958819191063"></a>
### 模板
模板的用途在于生成严格一致的node结构,以便对同类型node进行遍历和管理。 模板的用途在于生成严格一致的node结构,以便对同类型node进行遍历和管理。
使用template关键字定义模板node,子node通过双冒号“::”声明继承关系。子节点可以改写但不能新增和删除template中的属性,子节点中没有定义的属性将使用template中的定义作为默认值。示例如下: 使用template关键字定义模板node,子node通过双冒号“::”声明继承关系。子节点可以改写但不能新增和删除template中的属性,子节点中没有定义的属性将使用template中的定义作为默认值。示例如下:
``` ```
root { root {
module = "sample"; module = "sample";
...@@ -387,6 +359,7 @@ root { ...@@ -387,6 +359,7 @@ root {
生成配置树如下: 生成配置树如下:
``` ```
root { root {
module = "sample"; module = "sample";
...@@ -401,16 +374,19 @@ root { ...@@ -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是配置生成的工具,可以对HCS配置语法进行检查并把HCS源文件转化成HCB二进制文件。
### hc-gen介绍<a name="section359734416616"></a>
### hc-gen介绍
hc-gen参数说明: hc-gen参数说明:
``` ```
Usage: hc-gen [Options] [File] Usage: hc-gen [Options] [File]
options: options:
...@@ -418,7 +394,6 @@ options: ...@@ -418,7 +394,6 @@ options:
-a hcb align with four bytes -a hcb align with four bytes
-b output binary output, default enable -b output binary output, default enable
-t output config in C language source file style -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 -i output binary hex dump in C language source file style
-p <prefix> prefix of generated symbol name -p <prefix> prefix of generated symbol name
-d decompile hcb to hcs -d decompile hcb to hcs
...@@ -429,25 +404,28 @@ options: ...@@ -429,25 +404,28 @@ options:
生成.c/.h 配置文件方法: 生成.c/.h 配置文件方法:
``` ```
hc-gen -o [OutputCFileName] -t [SourceHcsFileName] hc-gen -o [OutputCFileName] -t [SourceHcsFileName]
``` ```
生成HCB 配置文件方法: 生成HCB 配置文件方法:
``` ```
hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName] hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName]
``` ```
生成宏定义配置文件方法: 生成宏定义配置文件方法:
``` ```
hc-gen -o [OutputMacroFileName] -m [SourceHcsFileName] hc-gen -o [OutputMacroFileName] -m [SourceHcsFileName]
``` ```
反编译HCB文件为HCS方法: 反编译HCB文件为HCS方法:
``` ```
hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName] hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName]
``` ```
# 驱动消息机制管理<a name="ZH-CN_TOPIC_0000001052657065"></a> # 驱动消息机制管理
- [使用场景](#section33014541954)
- [接口说明](#section538852311616)
- [开发步骤](#section946912121153)
## 使用场景<a name="section33014541954"></a> ## 使用场景
当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。 当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。
## 接口说明<a name="section538852311616"></a>
## 接口说明
消息机制的功能主要有以下两种: 消息机制的功能主要有以下两种:
1. 用户态应用发送消息到驱动。 1. 用户态应用发送消息到驱动。
2. 用户态应用接收驱动主动上报事件。 2. 用户态应用接收驱动主动上报事件。
**表 1** 消息机制接口 **表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> | struct&nbsp;HdfIoService&nbsp;\*HdfIoServiceBind(const&nbsp;char&nbsp;\*serviceName); | 用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。 |
<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> | void&nbsp;HdfIoServiceRecycle(struct&nbsp;HdfIoService&nbsp;\*service); | 释放驱动服务。 |
</th> | int&nbsp;HdfDeviceRegisterEventListener(struct&nbsp;HdfIoService&nbsp;\*target,&nbsp;struct&nbsp;HdfDevEventlistener&nbsp;\*listener); | 用户态程序注册接收驱动上报事件的操作方法。 |
</tr> | int&nbsp;HdfDeviceSendEvent(struct&nbsp;HdfDeviceObject&nbsp;\*deviceObject,&nbsp;uint32_t&nbsp;id,&nbsp;struct&nbsp;HdfSBuf&nbsp;\*data); | 驱动主动上报事件接口。 |
</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> 1. 将驱动配置信息中服务策略policy字段设置为2(SERVICE_POLICY_CAPACITY,参考[policy定义](../driver/driver-hdf-servicemanage.md))。
</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 { device_sample :: Device {
...@@ -59,6 +36,7 @@ ...@@ -59,6 +36,7 @@
``` ```
2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。 2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。
3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。 3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。
``` ```
...@@ -153,7 +131,6 @@ ...@@ -153,7 +131,6 @@
return 0; return 0;
} }
``` ```
2. 用户态注册接收驱动上报消息的操作方法。 2. 用户态注册接收驱动上报消息的操作方法。
``` ```
...@@ -178,7 +155,6 @@ ...@@ -178,7 +155,6 @@
return 0; return 0;
} }
``` ```
3. 驱动上报事件。 3. 驱动上报事件。
``` ```
...@@ -188,6 +164,3 @@ ...@@ -188,6 +164,3 @@
return HdfDeviceSendEvent(deviceObject, cmdCode, data); 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)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理和驱动消息机制。旨在构建统一的驱动架构平台,为驱动开发者提供更精准、更高效的开发环境,力求做到一次开发,多系统部署。 HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理和驱动消息机制。旨在构建统一的驱动架构平台,为驱动开发者提供更精准、更高效的开发环境,力求做到一次开发,多系统部署。
## 驱动加载<a name="section68701942154319"></a>
## 驱动加载
HDF驱动加载包括按需加载和按序加载。 HDF驱动加载包括按需加载和按序加载。
- 按需加载 - 按需加载
HDF框架支持驱动在系统启动过程中默认加载,或者在系统启动之后动态加载。 HDF框架支持驱动在系统启动过程中默认加载,或者在系统启动之后动态加载。
- 按序加载 - 按序加载
HDF框架支持驱动在系统启动的过程中按照驱动的优先级进行加载。 HDF框架支持驱动在系统启动的过程中按照驱动的优先级进行加载。
## 驱动服务管理<a name="section12453133414412"></a> ## 驱动服务管理
HDF框架可以集中管理驱动服务,开发者可直接通过HDF框架对外提供的能力接口获取驱动相关的服务。 HDF框架可以集中管理驱动服务,开发者可直接通过HDF框架对外提供的能力接口获取驱动相关的服务。
## 驱动消息机制<a name="section129410710451"></a>
HDF框架提供统一的驱动消息机制,支持用户态应用向内核态驱动发送消息,也支持内核态驱动向用户态应用发送消息。 ## 驱动消息机制
HDF框架提供统一的驱动消息机制,支持用户态应用向内核态驱动发送消息,也支持内核态驱动向用户态应用发送消息。
# HDF开发实例<a name="ZH-CN_TOPIC_0000001052451677"></a> # HDF开发实例
- [添加配置](#section27261067111)
- [编写驱动代码](#section177988005)
- [编写用户程序和驱动交互代码](#section6205173816412)
下面基于HDF框架,提供一个完整的样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。 下面基于HDF框架,提供一个完整的样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。
## 添加配置<a name="section27261067111"></a>
在HDF框架的配置文件(例如vendor/hisilicon/xxx/hdf_config/device\_info)中添加该驱动的配置信息,如下所示: ## 添加配置
在HDF框架的配置文件(例如vendor/hisilicon/xxx/hdf_config/device_info)中添加该驱动的配置信息,如下所示:
``` ```
root { root {
...@@ -46,9 +45,11 @@ root { ...@@ -46,9 +45,11 @@ root {
} }
``` ```
## 编写驱动代码<a name="section177988005"></a>
基于HDF框架编写的sample驱动代码如下(编译参考 [驱动开发](driver-hdf-development.md)): ## 编写驱动代码
基于HDF框架编写的sample驱动代码如下(编译参考[驱动开发](../driver/driver-hdf-development.md)):
``` ```
#include <fcntl.h> #include <fcntl.h>
...@@ -118,9 +119,11 @@ struct HdfDriverEntry g_sampleDriverEntry = { ...@@ -118,9 +119,11 @@ struct HdfDriverEntry g_sampleDriverEntry = {
HDF_INIT(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 <fcntl.h>
...@@ -229,10 +232,13 @@ int main() ...@@ -229,10 +232,13 @@ int main()
} }
``` ```
>![](../public_sys-resources/icon-note.gif) **说明:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf\_core和osal的动态库,在gn编译文件中添加如下依赖项: > 用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf_core和osal的动态库,在gn编译文件中添加如下依赖项:
>deps = \[ >
>"//drivers/adapter/uhdf/manager:hdf\_core", > deps = [
>"//drivers/adapter/uhdf/posix:hdf\_posix\_osal", >
>\] > "//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驱动设备对外提供能力的对象,由HDF框架统一管理。驱动服务管理主要包含驱动服务的发布和获取。
HDF框架定义了驱动对外发布服务的策略,是由配置文件中的policy字段来控制,policy字段的取值范围以及含义如下: HDF框架定义了驱动对外发布服务的策略,是由配置文件中的policy字段来控制,policy字段的取值范围以及含义如下:
``` ```
typedef enum { typedef enum {
/* 驱动不提供服务 */ /* 驱动不提供服务 */
...@@ -25,43 +25,26 @@ typedef enum { ...@@ -25,43 +25,26 @@ typedef enum {
} ServicePolicy; } ServicePolicy;
``` ```
## 使用场景<a name="section14244270117"></a>
## 使用场景
当驱动以接口的形式对外提供能力时,可以使用HDF框架的驱动服务管理能力。 当驱动以接口的形式对外提供能力时,可以使用HDF框架的驱动服务管理能力。
## 接口说明<a name="section1432412561722"></a>
## 接口说明
针对驱动服务管理功能,HDF框架开放了以下接口供开发者调用,如下表所示: 针对驱动服务管理功能,HDF框架开放了以下接口供开发者调用,如下表所示:
**表 1** 服务管理接口 **表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> | int32_t&nbsp;(\*Bind)(struct&nbsp;HdfDeviceObject&nbsp;\*deviceObject); | 需要驱动开发者实现Bind函数,将自己的服务接口绑定到HDF框架中。 |
<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> | const&nbsp;struct&nbsp;HdfObject&nbsp;\*DevSvcManagerClntGetService(const&nbsp;char&nbsp;\*svcName); | 获取驱动的服务。 |
</th> | int&nbsp;HdfDeviceSubscribeService(<br/>struct&nbsp;HdfDeviceObject&nbsp;\*deviceObject,&nbsp;const&nbsp;char&nbsp;\*serviceName,&nbsp;struct&nbsp;SubscriberCallback&nbsp;callback); | 订阅驱动的服务。 |
</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>
驱动服务管理的开发包括驱动服务的编写、绑定、获取或者订阅,详细步骤如下。 驱动服务管理的开发包括驱动服务的编写、绑定、获取或者订阅,详细步骤如下。
...@@ -109,13 +92,12 @@ typedef enum { ...@@ -109,13 +92,12 @@ typedef enum {
``` ```
3. 驱动服务获取。 3. 驱动服务获取。
驱动服务的获取有两种方式,HDF框架提供接口直接获取和HDF框架提供订阅机制获取。 驱动服务的获取有两种方式,HDF框架提供接口直接获取和HDF框架提供订阅机制获取。
- 通过HDF接口直接获取 - 通过HDF接口直接获取
当明确驱动已经加载完成时,获取该驱动的服务可以通过HDF框架提供的能力接口直接获取,如下所示: 当明确驱动已经加载完成时,获取该驱动的服务可以通过HDF框架提供的能力接口直接获取,如下所示:
``` ```
const struct ISampleDriverService *sampleService = const struct ISampleDriverService *sampleService =
(const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver"); (const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver");
...@@ -125,11 +107,10 @@ typedef enum { ...@@ -125,11 +107,10 @@ typedef enum {
sampleService->ServiceA(); sampleService->ServiceA();
sampleService->ServiceB(5); sampleService->ServiceB(5);
``` ```
- 通过HDF提供的订阅机制获取 - 通过HDF提供的订阅机制获取
当内核态对驱动(同一个host)加载的时机不感知时,可以通过HDF框架提供的订阅机制来订阅该驱动,当该驱动加载完成时,HDF框架会将被订阅的驱动服务发布给订阅者,实现方式如下所示: 当内核态对驱动(同一个host)加载的时机不感知时,可以通过HDF框架提供的订阅机制来订阅该驱动,当该驱动加载完成时,HDF框架会将被订阅的驱动服务发布给订阅者,实现方式如下所示:
``` ```
// 订阅回调函数的编写,当被订阅的驱动加载完成后,HDF框架会将被订阅驱动的服务发布给订阅者,通过这个回调函数给订阅者使用 // 订阅回调函数的编写,当被订阅的驱动加载完成后,HDF框架会将被订阅驱动的服务发布给订阅者,通过这个回调函数给订阅者使用
// object为订阅者的私有数据,service为被订阅的服务对象 // object为订阅者的私有数据,service为被订阅的服务对象
...@@ -160,6 +141,3 @@ typedef enum { ...@@ -160,6 +141,3 @@ typedef enum {
return ret; return ret;
} }
``` ```
# HDF驱动框架<a name="ZH-CN_TOPIC_0000001157319419"></a> # HDF驱动框架
- **[HDF开发概述](driver-hdf-overview.md)** - **[HDF开发概述](driver-hdf-overview.md)**
...@@ -11,5 +13,3 @@ ...@@ -11,5 +13,3 @@
- **[配置管理](driver-hdf-manage.md)** - **[配置管理](driver-hdf-manage.md)**
- **[HDF开发实例](driver-hdf-sample.md)** - **[HDF开发实例](driver-hdf-sample.md)**
\ No newline at end of file
# WLAN<a name="ZH-CN_TOPIC_0000001051643558"></a> # WLAN
- [概述](#section729758162218)
- [WLAN驱动接口架构](#section178022416377)
- [接口说明](#section7331102018815) ## 概述
- [开发步骤](#section15957746172412)
- [开发实例](#section1395253612512)
## 概述<a name="section729758162218"></a> WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。WLAN模块框架图如下:
WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。[WLAN模块框架图](#fig4415112614415)如下: **图1** WLAN框架
![zh-cn_image_0000001200092359](figures/zh-cn_image_0000001200092359.png)
**图 1** WLAN框架<a name="fig4415112614415"></a>
![](figures/WLAN框架.png "WLAN框架")
### WLAN驱动接口架构<a name="section178022416377"></a> ### WLAN驱动接口架构
WLAN模块有三部分对外开放的API接口,如[下图2](#fig1492411431166)所示: WLAN模块有三部分对外开放的API接口,如下图所示:
1. 对HDI层提供的能力接口。 1. 对HDI层提供的能力接口。
...@@ -24,227 +19,105 @@ WLAN模块有三部分对外开放的API接口,如[下图2](#fig1492411431166) ...@@ -24,227 +19,105 @@ WLAN模块有三部分对外开放的API接口,如[下图2](#fig1492411431166)
3. 提供给各厂商实现的能力接口。 3. 提供给各厂商实现的能力接口。
**图 2** WLAN模块开放能力分布图<a name="fig1492411431166"></a> **图2** WLAN模块开放能力分布图
![](figures/WLAN模块开放能力分布图.png "WLAN模块开放能力分布图") ![zh-cn_image_0000001197807387](figures/zh-cn_image_0000001197807387.png)
## 接口说明<a name="section7331102018815"></a>
## 接口说明
WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。提供的部分接口说明如[表1](#table1521573319472)所示:
WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。
**表 1** 可直接调用的接口
可直接调用的接口如下:
<a name="table1521573319472"></a>
<table><thead align="left"><tr id="row121519334474"><th class="cellrowborder" valign="top" width="15.079999999999998%" id="mcps1.2.4.1.1"><p id="p1221510339475"><a name="p1221510339475"></a><a name="p1221510339475"></a>头文件</p> **表1** wifi_module.h
</th>
<th class="cellrowborder" valign="top" width="60.33%" id="mcps1.2.4.1.2"><p id="p0215153344716"><a name="p0215153344716"></a><a name="p0215153344716"></a>接口名称</p> | 接口名称 | 功能描述 |
</th> | -------- | -------- |
<th class="cellrowborder" valign="top" width="24.59%" id="mcps1.2.4.1.3"><p id="p1421503315478"><a name="p1421503315478"></a><a name="p1421503315478"></a>功能描述</p> | struct&nbsp;WifiModule&nbsp;\*WifiModuleCreate(const&nbsp;struct&nbsp;HdfConfigWifiModuleConfig&nbsp;\*config) | 基于HDF开发WLAN驱动时,创建一个WifiModule。 |
</th> | void&nbsp;WifiModuleDelete(struct&nbsp;WifiModule&nbsp;\*module) | 基于HDF开发WLAN驱动时,删除并释放WifiModule所有数据。 |
</tr> | int32_t&nbsp;DelFeature(struct&nbsp;WifiModule&nbsp;\*module,&nbsp;uint16_t&nbsp;featureType) | 基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件。 |
</thead> | int32_t&nbsp;AddFeature(struct&nbsp;WifiModule&nbsp;\*module,&nbsp;uint16_t&nbsp;featureType,&nbsp;struct&nbsp;WifiFeature&nbsp;\*featureData) | 基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule。 |
<tbody><tr id="row112150333476"><td class="cellrowborder" rowspan="4" valign="top" width="15.079999999999998%" headers="mcps1.2.4.1.1 "><p id="p2155710125317"><a name="p2155710125317"></a><a name="p2155710125317"></a>wifi_module.h</p>
<p id="p189132019183"><a name="p189132019183"></a><a name="p189132019183"></a></p> **表2** wifi_mac80211_ops.h
</td>
<td class="cellrowborder" valign="top" width="60.33%" headers="mcps1.2.4.1.2 "><p id="p363110387399"><a name="p363110387399"></a><a name="p363110387399"></a>struct WifiModule *WifiModuleCreate(const struct HdfConfigWifiModuleConfig *config);</p> | 接口名称 | 功能描述 |
</td> | -------- | -------- |
<td class="cellrowborder" valign="top" width="24.59%" headers="mcps1.2.4.1.3 "><p id="p1363012387393"><a name="p1363012387393"></a><a name="p1363012387393"></a>基于HDF开发WLAN驱动时,创建一个WifiModule。</p> | int32_t&nbsp;(\*startAp)(NetDevice&nbsp;\*netDev) | 启动AP。 |
</td> | int32_t&nbsp;(\*stopAp)(NetDevice&nbsp;\*netDev) | 停止AP。 |
</tr> | int32_t&nbsp;(\*connect)(NetDevice&nbsp;\*netDev,&nbsp;WifiConnectParams&nbsp;\*param) | 开始关联。 |
<tr id="row112151233194714"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p7629163817393"><a name="p7629163817393"></a><a name="p7629163817393"></a>void WifiModuleDelete(struct WifiModule *module);</p> | int32_t&nbsp;(\*disconnect)(NetDevice&nbsp;\*netDev,&nbsp;uint16_t&nbsp;reasonCode) | 取消关联。 |
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p2627638173917"><a name="p2627638173917"></a><a name="p2627638173917"></a>基于HDF开发WLAN驱动时,删除并释放WifiModule所有数据。</p> **表3** hdf_netbuf.h
</td>
</tr> | 接口名称 | 功能描述 |
<tr id="row1121533316475"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p12626103814399"><a name="p12626103814399"></a><a name="p12626103814399"></a>int32_t DelFeature(struct WifiModule *module, uint16_t featureType);</p> | -------- | -------- |
</td> | static&nbsp;inline&nbsp;void&nbsp;NetBufQueueInit(struct&nbsp;NetBufQueue&nbsp;\*q) | 初始化NetBuf队列。 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1162543816393"><a name="p1162543816393"></a><a name="p1162543816393"></a>基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件。</p> | struct&nbsp;NetBuf&nbsp;\*NetBufAlloc(uint32_t&nbsp;size) | 申请NetBuf。 |
</td> | void&nbsp;NetBufFree(struct&nbsp;NetBuf&nbsp;\*nb) | 释放NetBuf |
</tr> | struct&nbsp;NetBuf&nbsp;\*Pbuf2NetBuf(const&nbsp;struct&nbsp;NetDevice&nbsp;\*netdev,&nbsp;struct&nbsp;pbuf&nbsp;\*lwipBuf) | lwip的pbuf转换为NetBuf。 |
<tr id="row172153335473"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p162433816392"><a name="p162433816392"></a><a name="p162433816392"></a>int32_t AddFeature(struct WifiModule *module, uint16_t featureType, struct WifiFeature *featureData);</p> | struct&nbsp;pbuf&nbsp;\*NetBuf2Pbuf(const&nbsp;struct&nbsp;NetBuf&nbsp;\*nb) | NetBuf转换为lwip的pbuf。 |
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p186235383393"><a name="p186235383393"></a><a name="p186235383393"></a>基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule。</p> 同时WLAN驱动模块也提供了需要驱动开发人员实现的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如下表所示:
</td>
</tr> **表4** net_device.h
<tr id="row451796205011"><td class="cellrowborder" rowspan="4" valign="top" width="15.079999999999998%" headers="mcps1.2.4.1.1 "><p id="p2659417135013"><a name="p2659417135013"></a><a name="p2659417135013"></a>wifi_mac80211_ops.h</p>
</td> | 接口名称 | 功能描述 |
<td class="cellrowborder" valign="top" width="60.33%" headers="mcps1.2.4.1.2 "><p id="p175181615011"><a name="p175181615011"></a><a name="p175181615011"></a>int32_t (*startAp)(NetDevice *netDev);</p> | -------- | -------- |
</td> | int32_t&nbsp;(\*init)(struct&nbsp;NetDevice&nbsp;\*netDev) | 初始化NetDevice。 |
<td class="cellrowborder" valign="top" width="24.59%" headers="mcps1.2.4.1.3 "><p id="p195182610507"><a name="p195182610507"></a><a name="p195182610507"></a>启动AP。</p> | struct&nbsp;NetDevStats&nbsp;\*(\*getStats)(struct&nbsp;NetDevice&nbsp;\*netDev) | 获取NetDevice的状态。 |
</td> | int32_t&nbsp;(\*setMacAddr)(struct&nbsp;NetDevice&nbsp;\*netDev,&nbsp;void&nbsp;\*addr) | 设置Mac地址。 |
</tr> | void&nbsp;(\*deInit)(struct&nbsp;NetDevice&nbsp;\*netDev) | 注销NetDevice。 |
<tr id="row5518663503"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p125181260501"><a name="p125181260501"></a><a name="p125181260501"></a>int32_t (*stopAp)(NetDevice *netDev);</p> | int32_t&nbsp;(\*open)(struct&nbsp;NetDevice&nbsp;\*netDev) | 打开NetDevice。 |
</td> | int32_t&nbsp;(\*stop)(struct&nbsp;NetDevice&nbsp;\*netDev) | 关闭NetDevice。 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1151815635014"><a name="p1151815635014"></a><a name="p1151815635014"></a>停止AP。</p>
</td> WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如下表所示:
</tr>
<tr id="row851915617503"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p20519865500"><a name="p20519865500"></a><a name="p20519865500"></a>int32_t (*connect)(NetDevice *netDev, WifiConnectParams *param);</p> **表5** wifi_hal.h
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p14519469509"><a name="p14519469509"></a><a name="p14519469509"></a>开始关联。</p> | 接口名称 | 功能描述 |
</td> | -------- | -------- |
</tr> | int32_t&nbsp;WifiConstruct(struct&nbsp;IWiFi&nbsp;\*\*wifiInstance) | 创建IWiFi对象,提供IWiFi基本能力。 |
<tr id="row18519136185016"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p145195620502"><a name="p145195620502"></a><a name="p145195620502"></a>int32_t (*disconnect)(NetDevice *netDev, uint16_t reasonCode);</p> | int32_t&nbsp;WifiDestruct(struct&nbsp;IWiFi&nbsp;\*\*wifiInstance) | 销毁IWiFi对象。 |
</td> | int32_t&nbsp;(\*start)(struct&nbsp;IWiFi&nbsp;\*) | 创建HAL和驱动之间的通道及获取驱动支持的网卡信息。 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p175191863503"><a name="p175191863503"></a><a name="p175191863503"></a>取消关联。</p> | int32_t&nbsp;(\*stop)(struct&nbsp;IWiFi&nbsp;\*) | 销毁通道。 |
</td>
</tr> **表6** wifi_hal_base_feature.h
<tr id="row176421942125016"><td class="cellrowborder" rowspan="5" valign="top" width="15.079999999999998%" headers="mcps1.2.4.1.1 "><p id="p7937165012500"><a name="p7937165012500"></a><a name="p7937165012500"></a>hdf_netbuf.h</p>
</td> | 接口名称 | 功能描述 |
<td class="cellrowborder" valign="top" width="60.33%" headers="mcps1.2.4.1.2 "><p id="p1964211423505"><a name="p1964211423505"></a><a name="p1964211423505"></a>static inline void NetBufQueueInit(struct NetBufQueue *q);</p> | -------- | -------- |
</td> | int32_t&nbsp;(\*getFeatureType)(const&nbsp;struct&nbsp;IWiFiBaseFeature&nbsp;\*) | 获取特性的类型。 |
<td class="cellrowborder" valign="top" width="24.59%" headers="mcps1.2.4.1.3 "><p id="p364254211507"><a name="p364254211507"></a><a name="p364254211507"></a>初始化NetBuf队列。</p> | int32_t&nbsp;(\*setMacAddress)(const&nbsp;struct&nbsp;IWiFiBaseFeature&nbsp;\*,&nbsp;unsigned&nbsp;char&nbsp;\*,&nbsp;uint8_t) | 设置MAC地址。 |
</td> | int32_t&nbsp;(\*getDeviceMacAddress)(const&nbsp;struct&nbsp;IWiFiBaseFeature&nbsp;\*,&nbsp;unsigned&nbsp;char&nbsp;\*,&nbsp;uint8_t) | 获取设备持久化的MAC地址。 |
</tr> | int32_t&nbsp;(\*setTxPower)(const&nbsp;struct&nbsp;IWiFiBaseFeature&nbsp;\*,&nbsp;int32_t) | 设置发射功率。 |
<tr id="row664264225020"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p166421942115017"><a name="p166421942115017"></a><a name="p166421942115017"></a>struct NetBuf *NetBufAlloc(uint32_t size);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p3642164215501"><a name="p3642164215501"></a><a name="p3642164215501"></a>申请NetBuf。</p> ## 开发步骤
</td>
</tr>
<tr id="row19642134215018"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p964310425501"><a name="p964310425501"></a><a name="p964310425501"></a>void NetBufFree(struct NetBuf *nb);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1464312427503"><a name="p1464312427503"></a><a name="p1464312427503"></a>释放NetBuf。</p>
</td>
</tr>
<tr id="row7643194215013"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p20643164218508"><a name="p20643164218508"></a><a name="p20643164218508"></a>struct NetBuf *Pbuf2NetBuf(const struct NetDevice *netdev, struct pbuf *lwipBuf);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p186437429509"><a name="p186437429509"></a><a name="p186437429509"></a>lwip的pbuf转换为NetBuf。</p>
</td>
</tr>
<tr id="row7657132317518"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p86576231557"><a name="p86576231557"></a><a name="p86576231557"></a>struct pbuf *NetBuf2Pbuf(const struct NetBuf *nb);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1965702312510"><a name="p1965702312510"></a><a name="p1965702312510"></a>NetBuf转换为lwip的pbuf。</p>
</td>
</tr>
</tbody>
</table>
同时WLAN驱动模块也提供了需要驱动开发人员实现的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如[表2](#table74613501475)所示:
**表 2** 需要开发人员实现的接口
<a name="table74613501475"></a>
<table><thead align="left"><tr id="row194625016476"><th class="cellrowborder" valign="top" width="20.75%" id="mcps1.2.4.1.1"><p id="p10468502479"><a name="p10468502479"></a><a name="p10468502479"></a>头文件</p>
</th>
<th class="cellrowborder" valign="top" width="52.75%" id="mcps1.2.4.1.2"><p id="p184615501477"><a name="p184615501477"></a><a name="p184615501477"></a>接口名称</p>
</th>
<th class="cellrowborder" valign="top" width="26.5%" id="mcps1.2.4.1.3"><p id="p1146135044719"><a name="p1146135044719"></a><a name="p1146135044719"></a>功能描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row04616509472"><td class="cellrowborder" rowspan="6" valign="top" width="20.75%" headers="mcps1.2.4.1.1 "><p id="p14615017477"><a name="p14615017477"></a><a name="p14615017477"></a>net_device.h</p>
</td>
<td class="cellrowborder" valign="top" width="52.75%" headers="mcps1.2.4.1.2 "><p id="p144943564611"><a name="p144943564611"></a><a name="p144943564611"></a>int32_t (*init)(struct NetDevice *netDev);</p>
</td>
<td class="cellrowborder" valign="top" width="26.5%" headers="mcps1.2.4.1.3 "><p id="p18822442135411"><a name="p18822442135411"></a><a name="p18822442135411"></a>初始化NetDevice。</p>
</td>
</tr>
<tr id="row1546250114713"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1490010315564"><a name="p1490010315564"></a><a name="p1490010315564"></a>struct NetDevStats *(*getStats)(struct NetDevice *netDev);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p5900163115564"><a name="p5900163115564"></a><a name="p5900163115564"></a>获取NetDevice的状态。</p>
</td>
</tr>
<tr id="row1646165010470"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p16909135319564"><a name="p16909135319564"></a><a name="p16909135319564"></a>int32_t (*setMacAddr)(struct NetDevice *netDev, void *addr);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p122001431115713"><a name="p122001431115713"></a><a name="p122001431115713"></a>设置Mac地址。</p>
</td>
</tr>
<tr id="row12471250184711"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p154213655215"><a name="p154213655215"></a><a name="p154213655215"></a>void (*deInit)(struct NetDevice *netDev);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p14845675719"><a name="p14845675719"></a><a name="p14845675719"></a>注销NetDevice。</p>
</td>
</tr>
<tr id="row13471050104719"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p16686131655218"><a name="p16686131655218"></a><a name="p16686131655218"></a>int32_t (*open)(struct NetDevice *netDev);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p164825613576"><a name="p164825613576"></a><a name="p164825613576"></a>打开NetDevice。</p>
</td>
</tr>
<tr id="row1747125054714"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p2310615407"><a name="p2310615407"></a><a name="p2310615407"></a>int32_t (*stop)(struct NetDevice *netDev);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1982212428542"><a name="p1982212428542"></a><a name="p1982212428542"></a>关闭NetDevice。</p>
</td>
</tr>
</tbody>
</table>
WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如[表3](#table141076311618)所示:
**表 3** HAL层对外接口
<a name="table141076311618"></a>
<table><thead align="left"><tr id="row010716312120"><th class="cellrowborder" valign="top" width="15.950000000000001%" id="mcps1.2.4.1.1"><p id="p1110713311116"><a name="p1110713311116"></a><a name="p1110713311116"></a>头文件</p>
</th>
<th class="cellrowborder" valign="top" width="59.46%" id="mcps1.2.4.1.2"><p id="p161073311610"><a name="p161073311610"></a><a name="p161073311610"></a>接口名称</p>
</th>
<th class="cellrowborder" valign="top" width="24.59%" id="mcps1.2.4.1.3"><p id="p110716315118"><a name="p110716315118"></a><a name="p110716315118"></a>功能描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row41077311218"><td class="cellrowborder" rowspan="4" valign="top" width="15.950000000000001%" headers="mcps1.2.4.1.1 "><p id="p1810719311013"><a name="p1810719311013"></a><a name="p1810719311013"></a>wifi_hal.h</p>
<p id="p12107931715"><a name="p12107931715"></a><a name="p12107931715"></a></p>
</td>
<td class="cellrowborder" valign="top" width="59.46%" headers="mcps1.2.4.1.2 "><p id="p1910815311519"><a name="p1910815311519"></a><a name="p1910815311519"></a>int32_t WifiConstruct(struct IWiFi **wifiInstance);</p>
</td>
<td class="cellrowborder" valign="top" width="24.59%" headers="mcps1.2.4.1.3 "><p id="p12108133112115"><a name="p12108133112115"></a><a name="p12108133112115"></a>创建IWiFi对象,提供IWiFi基本能力。</p>
</td>
</tr>
<tr id="row20108183110111"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p71083311617"><a name="p71083311617"></a><a name="p71083311617"></a>int32_t WifiDestruct(struct IWiFi **wifiInstance);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1010810315118"><a name="p1010810315118"></a><a name="p1010810315118"></a>销毁IWiFi对象。</p>
</td>
</tr>
<tr id="row19108131417"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p810818315118"><a name="p810818315118"></a><a name="p810818315118"></a>int32_t (*start)(struct IWiFi *);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p9108113116119"><a name="p9108113116119"></a><a name="p9108113116119"></a>创建HAL和驱动之间的通道及获取驱动支持的网卡信息。</p>
</td>
</tr>
<tr id="row810803112116"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1310823110116"><a name="p1310823110116"></a><a name="p1310823110116"></a>int32_t (*stop)(struct IWiFi *);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p12108183112110"><a name="p12108183112110"></a><a name="p12108183112110"></a>销毁通道。</p>
</td>
</tr>
<tr id="row91081731717"><td class="cellrowborder" rowspan="4" valign="top" width="15.950000000000001%" headers="mcps1.2.4.1.1 "><p id="p1910814312115"><a name="p1910814312115"></a><a name="p1910814312115"></a>wifi_hal_base_feature.h</p>
</td>
<td class="cellrowborder" valign="top" width="59.46%" headers="mcps1.2.4.1.2 "><p id="p2108123113111"><a name="p2108123113111"></a><a name="p2108123113111"></a>int32_t (*getFeatureType)(const struct IWiFiBaseFeature *);</p>
</td>
<td class="cellrowborder" valign="top" width="24.59%" headers="mcps1.2.4.1.3 "><p id="p910843113113"><a name="p910843113113"></a><a name="p910843113113"></a>获取特性的类型。</p>
</td>
</tr>
<tr id="row161081931318"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1610814318119"><a name="p1610814318119"></a><a name="p1610814318119"></a>int32_t (*setMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p101081031818"><a name="p101081031818"></a><a name="p101081031818"></a>设置MAC地址。</p>
</td>
</tr>
<tr id="row191081631318"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p191087311317"><a name="p191087311317"></a><a name="p191087311317"></a>int32_t (*getDeviceMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1110810312012"><a name="p1110810312012"></a><a name="p1110810312012"></a>获取设备持久化的MAC地址。</p>
</td>
</tr>
<tr id="row21080317115"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p310873115118"><a name="p310873115118"></a><a name="p310873115118"></a>int32_t (*setTxPower)(const struct IWiFiBaseFeature *, int32_t);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p410817311911"><a name="p410817311911"></a><a name="p410817311911"></a>设置发射功率。</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section15957746172412"></a>
WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。 WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。
1. 通过wifi\_config.hcs文件,配置硬件参数:module\(不同feature\),芯片等。
1. 通过wifi_config.hcs文件,配置硬件参数:module(不同feature),芯片等。
2. 解析配置文件, 生成全量配置的结构体对象。 2. 解析配置文件, 生成全量配置的结构体对象。
3. Module初始化,创建Module。 3. Module初始化,创建Module。
4. 挂接chip,初始化chip。 4. 挂接chip,初始化chip。
5. 总线初始化。 5. 总线初始化。
6. 上层wpa业务挂接。 6. 上层wpa业务挂接。
>![](../public_sys-resources/icon-note.gif) **说明:**
>以上驱动框架适配步骤一部分已经提供(详细见开发实例),待开发人员实现的部分有:1、根据硬件,修改配置参数;2、适配挂接chip;3、测试自验证。
## 开发实例<a name="section1395253612512"></a> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 以上驱动框架适配步骤一部分已经提供(详细见开发实例),待开发人员实现的部分有:1、根据硬件,修改配置参数;2、适配挂接chip;3、测试自验证。
## 开发实例
本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以hi3881WLAN芯片为例): 本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以hi3881WLAN芯片为例):
1、根据硬件,修改配置参数。 1、根据硬件,修改配置参数。
``` ```
/* 根据硬件参数,通过wlan_platform.hcs配置相关参数,以下是WLAN平台配置的示例 */ /* 根据硬件参数,通过wlan_platform.hcs配置相关参数,以下是WLAN平台配置的示例 */
...@@ -296,7 +169,7 @@ root { ...@@ -296,7 +169,7 @@ root {
} }
``` ```
2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化 2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化
``` ```
/* WLAN初始化挂接流程 */ /* WLAN初始化挂接流程 */
...@@ -416,6 +289,7 @@ struct HdfDriverEntry g_hdfHisiChipEntry = { ...@@ -416,6 +289,7 @@ struct HdfDriverEntry g_hdfHisiChipEntry = {
HDF_INIT(g_hdfHisiChipEntry); HDF_INIT(g_hdfHisiChipEntry);
``` ```
``` ```
#include "hdf_wifi_product.h" #include "hdf_wifi_product.h"
#include "hi_wifi_api.h" #include "hi_wifi_api.h"
...@@ -425,7 +299,7 @@ HDF_INIT(g_hdfHisiChipEntry); ...@@ -425,7 +299,7 @@ HDF_INIT(g_hdfHisiChipEntry);
#endif #endif
#include "wifi_mac80211_ops.h" #include "wifi_mac80211_ops.h"
#include "wal_cfg80211.h" #include "wal_cfg80211.h"
#include "net_adpater.h" #include "net_adapter.h"
#include "hdf_wlan_utils.h" #include "hdf_wlan_utils.h"
#define HDF_LOG_TAG Hi3881Driver #define HDF_LOG_TAG Hi3881Driver
...@@ -511,7 +385,7 @@ int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevi ...@@ -511,7 +385,7 @@ int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevi
} }
``` ```
3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针 3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针
``` ```
hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len) hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len)
...@@ -562,6 +436,7 @@ hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, co ...@@ -562,6 +436,7 @@ hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, co
4、WifiMac80211Ops中的函数挂接实现。 4、WifiMac80211Ops中的函数挂接实现。
``` ```
/* 挂接mac80211的一些函数指针 */ /* 挂接mac80211的一些函数指针 */
...@@ -611,4 +486,3 @@ hi_void HiMac80211Init(struct HdfChipDriver *chipDriver) ...@@ -611,4 +486,3 @@ hi_void HiMac80211Init(struct HdfChipDriver *chipDriver)
chipDriver->apOps = &g_apOps; chipDriver->apOps = &g_apOps;
} }
``` ```
# 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> **图1** 基于HDF驱动框架的Display驱动模型
![](figures/基于HDF驱动框架的Display驱动模型.png "基于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侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层。 Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共HAL层,支撑HDI(Hardware Display Interface)接口的实现,通过Display-HDI对图形服务提供各类驱动能力接口。
- Display平台驱动层:通过HDF提供的IOService数据通道,与公共HAL层对接,集中接收并处理各类上层调用指令。
- SoC平台驱动适配层:借助此SoC适配层,实现Display驱动和SoC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层。
- LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。 - LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。
基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。 基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。
## 接口说明<a name="section53793327396"></a>
## 接口说明
LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,常用的是MIPI DSI接口和TTL接口,下面对常用的MIPI DSI接口和TTL接口作简要介绍。 LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,常用的是MIPI DSI接口和TTL接口,下面对常用的MIPI DSI接口和TTL接口作简要介绍。
- MIPI DSI接口 - MIPI DSI接口
**图 2** MIPI DSI接口<a name="fig6936451331"></a> **图2** MIPI DSI接口
![](figures/MIPI-DSI接口.png "MIPI-DSI接口")
![zh-cn_image_0000001147040198](figures/zh-cn_image_0000001147040198.png)
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接口<a name="fig141611855635"></a> **图3** TTL接口
![](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驱动相关的设备描述配置。 1. 添加LCD驱动相关的设备描述配置。
2. 在SOC平台驱动适配层中适配对应的芯片平台驱动。
2. 在SoC平台驱动适配层中适配对应的芯片平台驱动。
3. 添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口: 3. 添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口:
- LCD上下电 - LCD上下电
根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC。 根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC。
- 发送初始化序列 - 发送初始化序列
根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。 根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。
4. 根据需求实现HDF框架其他接口,比如Release接口。 4. 根据需求实现HDF框架其他接口,比如Release接口。
5. 根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。 5. 根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。
## 开发实例<a name="section7441155155813"></a>
## 开发实例
添加设备描述配置: 添加设备描述配置:
``` ```
/* Display驱动相关的设备描述配置 */ /* Display驱动相关的设备描述配置 */
display :: host { display :: host {
...@@ -75,7 +84,7 @@ display :: host { ...@@ -75,7 +84,7 @@ display :: host {
serviceName = "hdf_disp"; serviceName = "hdf_disp";
} }
} }
/* SOC适配层驱动设备描述 */ /* SoC适配层驱动设备描述 */
device_hi35xx_disp :: device { device_hi35xx_disp :: device {
device0 :: deviceNode { device0 :: deviceNode {
policy = 0; policy = 0;
...@@ -103,6 +112,7 @@ display :: host { ...@@ -103,6 +112,7 @@ display :: host {
SOC适配层驱动,以Hi35xx系列芯片为例,需要在本层驱动中适配MIPI等和芯片平台相关的配置,示例如下: SOC适配层驱动,以Hi35xx系列芯片为例,需要在本层驱动中适配MIPI等和芯片平台相关的配置,示例如下:
``` ```
static int32_t MipiDsiInit(struct PanelInfo *info) static int32_t MipiDsiInit(struct PanelInfo *info)
{ {
...@@ -145,6 +155,7 @@ static int32_t MipiDsiInit(struct PanelInfo *info) ...@@ -145,6 +155,7 @@ static int32_t MipiDsiInit(struct PanelInfo *info)
LCD器件驱动示例如下: LCD器件驱动示例如下:
``` ```
#define RESET_GPIO 5 #define RESET_GPIO 5
#define MIPI_DSI0 0 #define MIPI_DSI0 0
...@@ -347,4 +358,3 @@ struct HdfDriverEntry g_sampleDevEntry = { ...@@ -347,4 +358,3 @@ struct HdfDriverEntry g_sampleDevEntry = {
HDF_INIT(g_sampleDevEntry); HDF_INIT(g_sampleDevEntry);
``` ```
...@@ -5,7 +5,7 @@ ...@@ -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驱动模型图 **图 1** Light驱动模型图
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
### 运作机制 ### 运作机制
通过介绍Light驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如图2所示: 通过介绍Light驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如[图2](#Light驱动运行图)所示:
**图 2** Light驱动运行图 **图 2** Light驱动运行图
...@@ -36,7 +36,7 @@ Light驱动模型以标准系统Hi3516DV300为例,介绍整个驱动加载及 ...@@ -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接口能力介绍 **表1** Light驱动模型对外API接口能力介绍
...@@ -148,7 +148,7 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模 ...@@ -148,7 +148,7 @@ Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模
HdfWorkDestroy(&drvData->work); HdfWorkDestroy(&drvData->work);
HdfWorkQueueDestroy(&drvData->workQueue); HdfWorkQueueDestroy(&drvData->workQueue);
(void)OsalMutexDestroy(&drvData->mutex); (void)OsalMutexDestroy(&drvData->mutex);
OsalMemFree(drvData); (void)OsalMemFree(drvData);
g_lightDrvData = NULL; 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驱动主要任务**
Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定Input相关配置、下载及更新固件等操作。 Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定Input相关配置、下载及更新固件等操作。
- **Touchscreen驱动模型说明**
本节主要介绍基于Input驱动模型开发Touchscreen器件驱动,Input模型整体的框架如下图所示。
- **Touchscreen驱动层次说明** Input驱动模型基于HDF驱动框架、Platform接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层Input Service可以通过HDI接口层获取相应的驱动能力,进而操控Touchscreen等输入设备。
本节主要介绍基于Input驱动模型开发touchscreen器件驱动,Input模型整体的框架如[图1](#fig6251184817261)。
Input驱动模型基于HDF驱动框架、Platform接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层Input service可以通过HDI接口层获取相应的驱动能力,进而操控touchscreen等输入设备。 **图1** 基于HDF驱动框架的Input驱动模型
![zh-cn_image_0000001123742904](figures/zh-cn_image_0000001123742904.png)
**图 1** 基于HDF驱动框架的Input驱动模型<a name="fig6251184817261"></a>
![](figures/基于HDF驱动框架的input驱动模型.png "基于HDF驱动框架的input驱动模型")
- **Input驱动模型介绍** - **Input驱动模型介绍**
Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明: Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明:
- Input设备管理:为各类输入设备驱动提供Input设备的注册、注销接口,同时统一管理Input设备列表。 - Input设备管理:为各类输入设备驱动提供Input设备的注册、注销接口,同时统一管理Input设备列表。
- Input平台驱动:指各类Input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册Input设备等。 - Input平台驱动:指各类Input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册Input设备等。
- Input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化。 - Input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化。
- Input数据通道:提供一套通用的数据上报通道,各类别的Input设备驱动均可用此通道上报Input事件。 - Input数据通道:提供一套通用的数据上报通道,各类别的Input设备驱动均可用此通道上报Input事件。
- Input配置解析:负责对Input设备的板级配置及器件私有配置进行解析及管理。 - Input配置解析:负责对Input设备的板级配置及器件私有配置进行解析及管理。
- **基于HDF驱动框架开发器件驱动的优势** - **基于HDF驱动框架开发器件驱动的优势**
在HDF(Hardware Driver Foundation)[驱动管理框架](driver-hdf-development.md)的基础上,Input驱动模型调用OSAL接口层和Platfom接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于Input驱动模型实现的touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。 在HDF(Hardware Driver Foundation)[驱动管理框架](../driver/driver-hdf-development.md)的基础上,Input驱动模型调用OSAL接口层和Platform接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于Input驱动模型实现的Touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。
## 接口说明<a name="section105459441659"></a> ## 接口说明
Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类: Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类:
- 电源接口 - 电源接口
- IO控制接口 - IO控制接口
- 通信接口 - 通信接口
**图 2** Touchscreen器件常用管脚<a name="fig1290384314416"></a> **图2** Touchscreen器件常用管脚
![](figures/Touchscreen器件常用管脚.png "Touchscreen器件常用管脚")
![zh-cn_image_0000001192846991](figures/zh-cn_image_0000001192846991.png)
如上图所示的三类接口,分别做简要说明如下: 如上图所示的三类接口,分别做简要说明如下:
1. **电源接口** 1. **电源接口**
- LDO\_1P8:1.8V数字电路 - LDO_1P8:1.8V数字电路
- LDO\_3P3:3.3V模拟电路 - 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控制接口** 2. **IO控制接口**
- Reset:reset管脚,用于在系统休眠、唤醒时,由主机侧对驱动IC进行复位操作。 - Reset:reset管脚,用于在系统休眠、唤醒时,由主机侧对驱动IC进行复位操作。
- INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作。 - INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作。
3. **通信接口** 3. **通信接口**
- I2C:由于touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](driver-platform-i2c-des.md#section5361140416) - I2C:由于Touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](../driver/driver-platform-i2c-des.md#概述)
- SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](driver-platform-spi-des.md#section193356154511) - SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](../driver/driver-platform-spi-des.md#概述)
## 开发步骤<a name="section65745222184"></a> ## 开发步骤
Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为touchscreen等输入器件提供统一的驱动开发架构。 Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为Touchscreen等输入器件提供统一的驱动开发架构。
如下以touchscreen器件驱动为例,说明Input驱动模型的完整加载流程: 如下以Touchscreen器件驱动为例,说明Input驱动模型的完整加载流程:
(1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。 (1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。
...@@ -95,25 +81,24 @@ Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区 ...@@ -95,25 +81,24 @@ Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区
请参考如下相关步骤: 请参考如下相关步骤:
1. 设备描述配置 1. 设备描述配置
目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。驱动的相关配置请参考[HDF驱动框架配置指导](../driver/driver-hdf-development.md#驱动开发步骤)
目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。驱动的相关配置请参考[HDF驱动框架配置指导](driver-hdf-development.md#section1969312275533)。
2. 板级配置及Touchscreen器件私有配置 2. 板级配置及Touchscreen器件私有配置
配置对应的IO管脚功能,例如对单板上为Touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。
配置对应的IO管脚功能,例如对单板上为touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。
3. 实现器件差异化适配接口 3. 实现器件差异化适配接口
根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](../driver/driver-platform-gpio-des.md#概述)
根据硬件单板设计的通信接口,使用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 { input :: host {
...@@ -156,10 +141,12 @@ input :: host { ...@@ -156,10 +141,12 @@ input :: host {
} }
``` ```
### 板级配置及器件私有配置<a name="section3571192072014"></a>
### 板级配置及器件私有配置
如下配置包含板级硬件配置及器件私有数据配置,实际业务开发时,可根据具体需求增删及修改如下配置文件信息。 如下配置包含板级硬件配置及器件私有数据配置,实际业务开发时,可根据具体需求增删及修改如下配置文件信息。
``` ```
root { root {
input_config { input_config {
...@@ -245,10 +232,12 @@ root { ...@@ -245,10 +232,12 @@ root {
} }
``` ```
### 添加器件驱动<a name="section6356758162015"></a>
### 添加器件驱动
在器件驱动中,主要实现了平台预留的差异化接口,以器件数据获取及解析进行示例说明。具体开发过程,需要根据实际使用的单板及器件进行适配。 在器件驱动中,主要实现了平台预留的差异化接口,以器件数据获取及解析进行示例说明。具体开发过程,需要根据实际使用的单板及器件进行适配。
``` ```
/* 将从器件中读取到的报点数据解析为坐标 */ /* 将从器件中读取到的报点数据解析为坐标 */
static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum)
...@@ -402,4 +391,3 @@ struct HdfDriverEntry g_touchSampleChipEntry = { ...@@ -402,4 +391,3 @@ struct HdfDriverEntry g_touchSampleChipEntry = {
HDF_INIT(g_touchSampleChipEntry); HDF_INIT(g_touchSampleChipEntry);
``` ```
# USB<a name="ZH-CN_TOPIC_0000001228574475"></a> # USB
- [概述](#section127mcpsimp)
- [接口说明](#section141mcpsimp)
- [开发指导](#section581mcpsimp) ## 概述
- [Host DDK API驱动开发步骤](#section584mcpsimp)
- [Host RAW API驱动开发步骤](#section594mcpsimp)
- [Device DDK API驱动开发步骤](#section600mcpsimp)
- [开发实例](#section607mcpsimp) USB Host部分,主要包括协议封装、设备管理、驱动安装与卸载等。
- [Host DDK API驱动开发](#section609mcpsimp)
- [Host RAW API驱动开发](#section612mcpsimp)
- [Device DDK API驱动开发](#section615mcpsimp)
USB Device部分,支持USB功能设备的开发,提供USB设备相关功能,主要包括设备管理、配置管理、IO管理,实现USB功能设备创建、配置、数据通信等。
## 概述<a name="section127mcpsimp"></a> USB Host和Device驱动模型如下图所示:
USB Host部分,主要包括协议封装、设备管理、驱动安装与卸载等。 **图1** USB Host驱动模型图
USB Device部分,支持USB功能设备的开发,提供USB设备相关功能,主要包括设备管理、配置管理、IO管理,实现USB功能设备创建、配置、数据通信等。 ![zh-cn_image_0000001183058868](figures/zh-cn_image_0000001183058868.png)
USB Host驱动模型如下图1所示:
**图 1** USB Host驱动模型图<a name="fig1649563542917"></a> **图2** USB Device驱动模型图
![](figures/USB-Host驱动模型图.png "USB-Host驱动模型图")
**图 2** USB Device驱动模型图<a name="fig8847615103013"></a> ![zh-cn_image_0000001183218992](figures/zh-cn_image_0000001183218992.png)
![](figures/USB-Device驱动模型图.png "USB-Device驱动模型图")
USB驱动模型对外开放的API接口能力如下: USB驱动模型对外开放的API接口能力如下:
- Usb Host DDK提供给用户态可直接调用的驱动能力接口,按照功能分类三大类:DDK初始化类、对interface对象操作类、对request对象操作类,可以提供DDK初始化、interface绑定和释放,打开和关闭操作,request的申请和释放,同步和异步传输等。 - Usb Host DDK提供给用户态可直接调用的驱动能力接口,按照功能分类三大类:DDK初始化类、对interface对象操作类、对request对象操作类,可以提供DDK初始化、interface绑定和释放,打开和关闭操作,request的申请和释放,同步和异步传输等。
- Usb Deivce DDK提供设备管理、IO管理、配置管理,主要功能有:创建和删除设备、获取和打开接口、同步和异步传输等。
- Usb Device DDK提供设备管理、IO管理、配置管理,主要功能有:创建和删除设备、获取和打开接口、同步和异步传输等。
### 接口说明<a name="section141mcpsimp"></a>
USB驱动模型Host侧开放的API接口功能,参考[图1](#fig1649563542917) ### 接口说明
**表 1** USB驱动模型Host侧开放的API接口功能介绍 USB驱动模型Host侧开放的API接口功能,参考USB Host驱动模型图。
<a name="table11474102882612"></a> **表1** usb_ddk_interface.h
<table><thead align="left"><tr id="row1147413289268"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.1"><p id="p1966391682713"><a name="p1966391682713"></a><a name="p1966391682713"></a>头文件</p>
</th> | 接口名称 | 功能描述 |
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.2"><p id="p166313167274"><a name="p166313167274"></a><a name="p166313167274"></a>接口名称</p> | -------- | -------- |
</th> | int32_t&nbsp;UsbInitHostSdk(struct&nbsp;UsbSession&nbsp;\*\*session); | USB主机端驱动开发工具包初始化 |
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p1066341602710"><a name="p1066341602710"></a><a name="p1066341602710"></a>功能描述</p> | int32_t&nbsp;UsbExitHostSdk(const&nbsp;struct&nbsp;UsbSession<br/>\*session); | USB主机端驱动开发工具包退出 |
</th> | const&nbsp;struct&nbsp;UsbInterface&nbsp;\*UsbClaimInterface(const<br/>struct&nbsp;UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br/>usbAddr,&nbsp;uint8_t&nbsp;interfaceIndex); | 获取USB接口对象 |
</tr> | int&nbsp;UsbReleaseInterface(const&nbsp;struct&nbsp;UsbInterface<br/>\*interfaceObj); | 释放USB接口对象 |
</thead> | int&nbsp;UsbAddOrRemoveInterface(const&nbsp;struct&nbsp;UsbSession<br/>\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t&nbsp;usbAddr,&nbsp;uint8_t<br/>interfaceIndex,&nbsp;UsbInterfaceStatus&nbsp;status); | 增加移除接口 |
<tbody><tr id="row1275799122710"><td class="cellrowborder" rowspan="16" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p4725109162716"><a name="p4725109162716"></a><a name="p4725109162716"></a>usb_ddk_interface.h</p> | UsbInterfaceHandle&nbsp;\*UsbOpenInterface(const&nbsp;struct<br/>UsbInterface&nbsp;\*interfaceObj); | 打开USB对象接口 |
</td> | int32_t&nbsp;UsbCloseInterface(const&nbsp;UsbInterfaceHandle<br/>\*interfaceHandle); | 关闭USB接口对象 |
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p17725698274"><a name="p17725698274"></a><a name="p17725698274"></a>int32_t UsbInitHostSdk(struct UsbSession **session);</p> | int32_t&nbsp;UsbSelectInterfaceSetting(const<br/>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;uint8_t<br/>settingIndex,&nbsp;struct&nbsp;UsbInterface&nbsp;\*\*interfaceObj); | 设置可选配置 |
</td> | int32_t&nbsp;UsbGetPipeInfo(const&nbsp;UsbInterfaceHandle<br/>\*interfaceHandle,&nbsp;uint8_t&nbsp;settingIndex,&nbsp;uint8_t&nbsp;pipeId,<br/>struct&nbsp;UsbPipeInfo&nbsp;\*pipeInfo); | 获取指定可选设置的管道信息 |
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p27252992712"><a name="p27252992712"></a><a name="p27252992712"></a>USB主机端驱动开发工具包初始化</p> | int32_t&nbsp;UsbClearInterfaceHalt(const<br/>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;uint8_t<br/>pipeAddress); | 清除指定索引的管道状态 |
</td> | struct&nbsp;UsbRequest&nbsp;\*UsbAllocRequest(const<br/>UsbInterfaceHandle&nbsp;\*interfaceHandle,&nbsp;int&nbsp;isoPackets<br/>,&nbsp;int&nbsp;length); | 分配请求对象 |
</tr> | int&nbsp;UsbFreeRequest(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 释放请求对象 |
<tr id="row775779172719"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p14725149172712"><a name="p14725149172712"></a><a name="p14725149172712"></a>int32_t UsbExitHostSdk(const struct UsbSession *session);</p> | int&nbsp;UsbSubmitRequestAsync(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 发送异步请求 |
</td> | int32_t&nbsp;UsbFillRequest(const&nbsp;struct&nbsp;UsbRequest<br/>\*request,&nbsp;const&nbsp;UsbInterfaceHandle&nbsp;\*interfaceHandle,<br/>const&nbsp;struct&nbsp;UsbRequestParams&nbsp;\*params); | 填充请求 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p172549192711"><a name="p172549192711"></a><a name="p172549192711"></a>USB主机端驱动开发工具包退出</p> | sint&nbsp;UsbCancelRequest(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 取消异步请求 |
</td> | int&nbsp;UsbSubmitRequestSync(const&nbsp;struct&nbsp;UsbRequest<br/>\*request); | 发送同步请求 |
</tr>
<tr id="row975769172712"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p167251791278"><a name="p167251791278"></a><a name="p167251791278"></a>const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);</p> **表2** usb_raw_api.h
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p187255962716"><a name="p187255962716"></a><a name="p187255962716"></a>获取USB接口对象</p> | 接口名称 | 功能描述 |
</td> | -------- | -------- |
</tr> | int&nbsp;UsbRawInit(struct&nbsp;UsbSession&nbsp;\*\*session); | USB驱动开发工具包专家模式初始化 |
<tr id="row97577920273"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p16725497276"><a name="p16725497276"></a><a name="p16725497276"></a>int UsbReleaseInterface(const struct UsbInterface *interfaceObj);</p> | int&nbsp;UsbRawExit(const&nbsp;struct&nbsp;UsbSession&nbsp;\*session); | USB驱动开发工具包专家模式退出 |
</td> | UsbRawHandle&nbsp;\*UsbRawOpenDevice(const&nbsp;struct<br/>UsbSession&nbsp;\*session,&nbsp;uint8_t&nbsp;busNum,&nbsp;uint8_t<br/>usbAddr); | 打开USB设备对象 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p117251894270"><a name="p117251894270"></a><a name="p117251894270"></a>释放USB接口对象</p> | int&nbsp;UsbRawCloseDevice(const&nbsp;UsbRawHandle<br/>\*devHandle); | 关闭USB设备对象 |
</td> | int&nbsp;UsbRawSendControlRequest(const&nbsp;struct<br/>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbControlRequestData<br/>\*requestData); | 执行同步控制传输 |
</tr> | int&nbsp;UsbRawSendBulkRequest(const&nbsp;struct<br/>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbRequestData<br/>\*requestData); | 执行同步批量传输 |
<tr id="row67574982718"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p872514915277"><a name="p872514915277"></a><a name="p872514915277"></a>int UsbAddOrRemoveInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex, UsbInterfaceStatus status);</p> | int&nbsp;UsbRawSendInterruptRequest(const&nbsp;struct<br/>UsbRawRequest&nbsp;\*request,&nbsp;const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;const&nbsp;struct&nbsp;UsbRequestData<br/>\*requestData); | 执行同步中断传输 |
</td> | int&nbsp;UsbRawGetConfigDescriptor(const&nbsp;UsbRawDevice<br/>\*rawDev,&nbsp;uint8_t&nbsp;configIndex,&nbsp;struct<br/>UsbRawConfigDescriptor&nbsp;\*\*config); | 获取给定设备指定ID的设备配置描述符 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p157251914278"><a name="p157251914278"></a><a name="p157251914278"></a>增加移除接口</p> | void&nbsp;UsbRawFreeConfigDescriptor(const&nbsp;struct<br/>UsbRawConfigDescriptor&nbsp;\*config); | 释放配置描述符内存空间 |
</td> | int&nbsp;UsbRawGetConfiguration(const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;int&nbsp;\*config); | 获取当前激活配置 |
</tr> | int&nbsp;UsbRawSetConfiguration(const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;int&nbsp;config); | 设置当前激活配置 |
<tr id="row47576942720"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p572517916275"><a name="p572517916275"></a><a name="p572517916275"></a>UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);</p> | int&nbsp;UsbRawGetDescriptor(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawDescriptorParam&nbsp;\*param,&nbsp;const&nbsp;unsigned&nbsp;char<br/>\*data); | 获取描述符信息 |
</td> | UsbRawDevice&nbsp;\*UsbRawGetDevice(const&nbsp;UsbRawHandle<br/>\*devHandle); | 由设备句柄获取设备指针 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p67254915272"><a name="p67254915272"></a><a name="p67254915272"></a>打开USB对象接口</p> | int&nbsp;UsbRawGetDeviceDescriptor(const&nbsp;UsbRawDevice<br/>\*rawDev,&nbsp;struct<br/>UsbDeviceDescriptor&nbsp;\*desc); | 获取给定设备的USB设备描述符 |
</td> | int&nbsp;UsbRawClaimInterface(const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;int<br/>interfaceNumber); | 声明给定设备句柄上的接口 |
</tr> | int&nbsp;UsbRawReleaseInterface(const&nbsp;UsbRawHandle<br/>\*devHandle,&nbsp;in<br/>t&nbsp;interfaceNumber); | 释放之前声明的接口 |
<tr id="row197579952713"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p472514912712"><a name="p472514912712"></a><a name="p472514912712"></a>int32_t UsbCloseInterface(const UsbInterfaceHandle *interfaceHandle);</p> | int&nbsp;UsbRawResetDevice(const&nbsp;UsbRawHandle<br/>\*devHandle); | 复位设备 |
</td> | struct&nbsp;UsbRawRequest&nbsp;\*UsbRawAllocRequest(const<br/>UsbRawHandle<br/>\*devHandle,&nbsp;int&nbsp;isoPackets,&nbsp;int&nbsp;length); | 分配一个带有指定数量的同步包描述符的传输请求 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p67251095276"><a name="p67251095276"></a><a name="p67251095276"></a>关闭USB接口对象</p> | int&nbsp;UsbRawFreeRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request); | 释放之前分配的传输请求 |
</td> | int&nbsp;UsbRawFillBulkRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawFillRequestData&nbsp;\*fillData); | 填充批量传输请求所需信息 |
</tr> | int&nbsp;UsbRawFillControlSetup(const&nbsp;unsigned&nbsp;char&nbsp;\*setup,<br/>const&nbsp;struct&nbsp;UsbControlRequestData&nbsp;\*requestData); | 填充控制传输设置包所需信息 |
<tr id="row15757894278"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p5725169192717"><a name="p5725169192717"></a><a name="p5725169192717"></a>int32_t UsbSelectInterfaceSetting(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, struct UsbInterface **interfaceObj);</p> | int&nbsp;UsbRawFillControlRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawFillRequestData&nbsp;\*fillData); | 填充控制传输请求所需信息 |
</td> | int&nbsp;UsbRawFillInterruptRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawFillRequestData&nbsp;\*fillData); | 填充中断传输请求所需信息 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p6725109112720"><a name="p6725109112720"></a><a name="p6725109112720"></a>设置可选配置</p> | int&nbsp;UsbRawFillIsoRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request,&nbsp;const&nbsp;UsbRawHandle&nbsp;\*devHandle,&nbsp;const&nbsp;struct<br/>UsbRawFillRequestData&nbsp;\*fillData); | 填充同步传输(Isochronous&nbsp;Transfers)请求所需信息 |
</td> | int&nbsp;UsbRawSubmitRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request); | 提交一个传输请求 |
</tr> | int&nbsp;UsbRawCancelRequest(const&nbsp;struct&nbsp;UsbRawRequest<br/>\*request); | 取消一个传输请求 |
<tr id="row107579932715"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p11725199182715"><a name="p11725199182715"></a><a name="p11725199182715"></a>int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);</p> | int&nbsp;UsbRawHandleRequests(const&nbsp;UsbRawHandle<br/>\*devHandle); | 传输请求事件完成处理 |
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p107261298272"><a name="p107261298272"></a><a name="p107261298272"></a>获取指定可选设置的管道信息</p> USB驱动模型Device侧开放的API接口功能,参考USB Device驱动模型图。
</td>
</tr> **表3** usbfn_device.h
<tr id="row27577992716"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p8726890275"><a name="p8726890275"></a><a name="p8726890275"></a>int32_t UsbClearInterfaceHalt(const UsbInterfaceHandle *interfaceHandle, uint8_t pipeAddress);</p>
</td> | 接口名称 | 功能描述 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p177261797274"><a name="p177261797274"></a><a name="p177261797274"></a>清除指定索引的管道状态</p> | -------- | -------- |
</td> | const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnCreateDevice(const<br/>char&nbsp;\*udcName,&nbsp;const&nbsp;struct&nbsp;UsbFnDescriptorData<br/>\*descriptor); | 创建Usb设备 |
</tr> | int&nbsp;UsbFnRemoveDevice(struct&nbsp;UsbFnDevice<br/>\*fnDevice); | 删除Usb设备 |
<tr id="row1757189172714"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1726998273"><a name="p1726998273"></a><a name="p1726998273"></a>struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int isoPackets, int length);</p> | const&nbsp;struct&nbsp;UsbFnDevice&nbsp;\*UsbFnGetDevice(const&nbsp;char<br/>\*udcName); | 获取Usb设备 |
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1272617982713"><a name="p1272617982713"></a><a name="p1272617982713"></a>分配请求对象</p> **表4** usbfn_interface.h
</td>
</tr> | 接口名称 | 功能描述 |
<tr id="row07579911279"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p187261911279"><a name="p187261911279"></a><a name="p187261911279"></a>int UsbFreeRequest(const struct UsbRequest *request);</p> | -------- | -------- |
</td> | int&nbsp;UsbFnStartRecvInterfaceEvent(struct<br/>UsbFnInterface&nbsp;\*interface,&nbsp;uint32_t&nbsp;eventMask,<br/>UsbFnEventCallback&nbsp;callback,&nbsp;void&nbsp;\*context); | 开始接受Event事件 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p177271592271"><a name="p177271592271"></a><a name="p177271592271"></a>释放请求对象</p> | int&nbsp;UsbFnStopRecvInterfaceEvent(struct<br/>UsbFnInterface&nbsp;\*interface); | 停止接受Event事件 |
</td> | UsbFnInterfaceHandle&nbsp;UsbFnOpenInterface(struct&nbsp;UsbFnInterface&nbsp;\*interface); | 打开一个接口 |
</tr> | int&nbsp;UsbFnCloseInterface(UsbFnInterfaceHandle&nbsp;handle); | 关闭一个接口 |
<tr id="row075759142715"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p3727896271"><a name="p3727896271"></a><a name="p3727896271"></a>int UsbSubmitRequestAsync(const struct UsbRequest *request);</p> | int&nbsp;UsbFnGetInterfacePipeInfo(struct&nbsp;UsbFnInterface<br/>\*interface,&nbsp;uint8_t&nbsp;pipeId,&nbsp;struct&nbsp;UsbFnPipeInfo&nbsp;\*info); | 获取管道信息 |
</td> | int&nbsp;UsbFnSetInterfaceProp(const&nbsp;struct&nbsp;UsbFnInterface<br/>\*interface,&nbsp;const&nbsp;char&nbsp;\*name,&nbsp;const&nbsp;char&nbsp;\*value); | 设置自定义属性 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p372714942718"><a name="p372714942718"></a><a name="p372714942718"></a>发送异步请求</p>
</td> **表5** usbfn_request.h
</tr>
<tr id="row1475718919272"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1727698272"><a name="p1727698272"></a><a name="p1727698272"></a>int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);</p> | 接口名称 | 功能描述 |
</td> | -------- | -------- |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p872713910270"><a name="p872713910270"></a><a name="p872713910270"></a>填充请求</p> | struct&nbsp;UsbFnRequest<br/>\*UsbFnAllocCtrlRequest(UsbFnInterfaceHandle&nbsp;handle,<br/>uint32_t&nbsp;len); | 申请一个控制请求 |
</td> | struct&nbsp;UsbFnRequest&nbsp;\*UsbFnAllocRequest(UsbFnInterfaceHandle&nbsp;handle,<br/>uint8_t&nbsp;pipe,&nbsp;uint32_t&nbsp;len); | 申请一个数据请求 |
</tr> | int&nbsp;UsbFnFreeRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | 释放一个请求 |
<tr id="row117576932710"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p9727291278"><a name="p9727291278"></a><a name="p9727291278"></a>sint UsbCancelRequest(const struct UsbRequest *request);</p> | int&nbsp;UsbFnSubmitRequestAsync(struct&nbsp;UsbFnRequest<br/>\*req); | 发送异步请求 |
</td> | int&nbsp;UsbFnSubmitRequestSync(struct&nbsp;UsbFnRequest<br/>\*req,&nbsp;uint32_t&nbsp;timeout); | 发送同步请求 |
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p37271897276"><a name="p37271897276"></a><a name="p37271897276"></a>取消异步请求</p> | int&nbsp;UsbFnCancelRequest(struct&nbsp;UsbFnRequest&nbsp;\*req); | 取消请求 |
</td>
</tr>
<tr id="row1475714912715"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p2727698275"><a name="p2727698275"></a><a name="p2727698275"></a>int UsbSubmitRequestSync(const struct UsbRequest *request);</p> ## 开发步骤
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p87279914277"><a name="p87279914277"></a><a name="p87279914277"></a>发送同步请求</p>
</td>
</tr>
<tr id="row11756097274"><td class="cellrowborder" rowspan="27" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p12727179132710"><a name="p12727179132710"></a><a name="p12727179132710"></a>usb_raw_api.h</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p11727391272"><a name="p11727391272"></a><a name="p11727391272"></a>int UsbRawInit(struct UsbSession **session);</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1572711919272"><a name="p1572711919272"></a><a name="p1572711919272"></a>USB驱动开发工具包专家模式初始化</p>
</td>
</tr>
<tr id="row1575629182713"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p372711918279"><a name="p372711918279"></a><a name="p372711918279"></a>int UsbRawExit(const struct UsbSession *session);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p372710942717"><a name="p372710942717"></a><a name="p372710942717"></a>USB驱动开发工具包专家模式退出</p>
</td>
</tr>
<tr id="row5756999270"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p8727291277"><a name="p8727291277"></a><a name="p8727291277"></a>UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1772719972717"><a name="p1772719972717"></a><a name="p1772719972717"></a>打开USB设备对象</p>
</td>
</tr>
<tr id="row117561292270"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p772709122715"><a name="p772709122715"></a><a name="p772709122715"></a>int UsbRawCloseDevice(const UsbRawHandle *devHandle);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1372715902711"><a name="p1372715902711"></a><a name="p1372715902711"></a>关闭USB设备对象</p>
</td>
</tr>
<tr id="row775689182714"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p197272918272"><a name="p197272918272"></a><a name="p197272918272"></a>int UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p272715932717"><a name="p272715932717"></a><a name="p272715932717"></a>执行同步控制传输</p>
</td>
</tr>
<tr id="row3756179132714"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1727296276"><a name="p1727296276"></a><a name="p1727296276"></a>int UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p872789162713"><a name="p872789162713"></a><a name="p872789162713"></a>执行同步批量传输</p>
</td>
</tr>
<tr id="row27568916276"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1072719992711"><a name="p1072719992711"></a><a name="p1072719992711"></a>int UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p117271895271"><a name="p117271895271"></a><a name="p117271895271"></a>执行同步中断传输</p>
</td>
</tr>
<tr id="row14756149112710"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p772711917274"><a name="p772711917274"></a><a name="p772711917274"></a>int UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p472714912710"><a name="p472714912710"></a><a name="p472714912710"></a>获取给定设备指定ID的设备配置描述符</p>
</td>
</tr>
<tr id="row1775614902711"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p37277942718"><a name="p37277942718"></a><a name="p37277942718"></a>void UsbRawFreeConfigDescriptor(const struct UsbRawConfigDescriptor *config);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p772759162711"><a name="p772759162711"></a><a name="p772759162711"></a>释放配置描述符内存空间</p>
</td>
</tr>
<tr id="row9756119182711"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p3727699274"><a name="p3727699274"></a><a name="p3727699274"></a>int UsbRawGetConfiguration(const UsbRawHandle *devHandle, int *config);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p13728109192717"><a name="p13728109192717"></a><a name="p13728109192717"></a>获取当前激活配置</p>
</td>
</tr>
<tr id="row37567922714"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1872849162718"><a name="p1872849162718"></a><a name="p1872849162718"></a>int UsbRawSetConfiguration(const UsbRawHandle *devHandle, int config);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p87280914277"><a name="p87280914277"></a><a name="p87280914277"></a>设置当前激活配置</p>
</td>
</tr>
<tr id="row1775612982711"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p127283902712"><a name="p127283902712"></a><a name="p127283902712"></a>int UsbRawGetDescriptor(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawDescriptorParam *param, const unsigned char *data);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p17728209122710"><a name="p17728209122710"></a><a name="p17728209122710"></a>获取描述符信息</p>
</td>
</tr>
<tr id="row97564992719"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1672849122712"><a name="p1672849122712"></a><a name="p1672849122712"></a>UsbRawDevice *UsbRawGetDevice(const UsbRawHandle *devHandle);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p472879202719"><a name="p472879202719"></a><a name="p472879202719"></a>由设备句柄获取设备指针</p>
</td>
</tr>
<tr id="row1075612922718"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p172814982715"><a name="p172814982715"></a><a name="p172814982715"></a>int UsbRawGetDeviceDescriptor(const UsbRawDevice *rawDev, struct UsbDeviceDescriptor *desc);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p8728139172715"><a name="p8728139172715"></a><a name="p8728139172715"></a>获取给定设备的USB设备描述符</p>
</td>
</tr>
<tr id="row117561919273"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p072820912714"><a name="p072820912714"></a><a name="p072820912714"></a>int UsbRawClaimInterface(const UsbRawHandle *devHandle, int interfaceNumber);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p972817914279"><a name="p972817914279"></a><a name="p972817914279"></a>声明给定设备句柄上的接口</p>
</td>
</tr>
<tr id="row87561920275"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p2728191276"><a name="p2728191276"></a><a name="p2728191276"></a>int UsbRawReleaseInterface(const UsbRawHandle *devHandle, int interfaceNumber);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p8728159102710"><a name="p8728159102710"></a><a name="p8728159102710"></a>释放之前声明的接口</p>
</td>
</tr>
<tr id="row375679152710"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p137281192274"><a name="p137281192274"></a><a name="p137281192274"></a>int UsbRawResetDevice(const UsbRawHandle *devHandle);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p107281992272"><a name="p107281992272"></a><a name="p107281992272"></a>复位设备</p>
</td>
</tr>
<tr id="row14756109152719"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p137288914273"><a name="p137288914273"></a><a name="p137288914273"></a>struct UsbRawRequest *UsbRawAllocRequest(const UsbRawHandle *devHandle, int isoPackets, int length);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p27281797274"><a name="p27281797274"></a><a name="p27281797274"></a>分配一个带有指定数量的同步包描述符的传输请求</p>
</td>
</tr>
<tr id="row07560932714"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p2072810912713"><a name="p2072810912713"></a><a name="p2072810912713"></a>int UsbRawFreeRequest(const struct UsbRawRequest *request);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p17281917278"><a name="p17281917278"></a><a name="p17281917278"></a>释放之前分配的传输请求</p>
</td>
</tr>
<tr id="row1775615952717"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1872810915274"><a name="p1872810915274"></a><a name="p1872810915274"></a>int UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p117281090271"><a name="p117281090271"></a><a name="p117281090271"></a>填充批量传输请求所需信息</p>
</td>
</tr>
<tr id="row675659172716"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1272820962719"><a name="p1272820962719"></a><a name="p1272820962719"></a>int UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p177281299278"><a name="p177281299278"></a><a name="p177281299278"></a>填充控制传输设置包所需信息</p>
</td>
</tr>
<tr id="row97563912271"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1372817914277"><a name="p1372817914277"></a><a name="p1372817914277"></a>int UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1372815952715"><a name="p1372815952715"></a><a name="p1372815952715"></a>填充控制传输请求所需信息</p>
</td>
</tr>
<tr id="row117561932712"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p172899112714"><a name="p172899112714"></a><a name="p172899112714"></a>int UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p19728092271"><a name="p19728092271"></a><a name="p19728092271"></a>填充中断传输请求所需信息</p>
</td>
</tr>
<tr id="row075617917271"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p072829132714"><a name="p072829132714"></a><a name="p072829132714"></a>int UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p107281913275"><a name="p107281913275"></a><a name="p107281913275"></a>填充同步传输(Isochronous Transfers)请求所需信息</p>
</td>
</tr>
<tr id="row87564917271"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p16728129152712"><a name="p16728129152712"></a><a name="p16728129152712"></a>int UsbRawSubmitRequest(const struct UsbRawRequest *request);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p187299922718"><a name="p187299922718"></a><a name="p187299922718"></a>提交一个传输请求</p>
</td>
</tr>
<tr id="row975659192711"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p15729099278"><a name="p15729099278"></a><a name="p15729099278"></a>int UsbRawCancelRequest(const struct UsbRawRequest *request);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p872912911274"><a name="p872912911274"></a><a name="p872912911274"></a>取消一个传输请求</p>
</td>
</tr>
<tr id="row1675519932712"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1472929182710"><a name="p1472929182710"></a><a name="p1472929182710"></a>int UsbRawHandleRequests(const UsbRawHandle *devHandle);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p572929102710"><a name="p572929102710"></a><a name="p572929102710"></a>传输请求事件完成处理</p>
</td>
</tr>
</tbody>
</table>
USB驱动模型Device侧开放的API接口功能,参考[图2](#fig8847615103013)
**表 2** USB驱动模型Device侧开放的API接口功能介绍
<a name="table1172315391272"></a>
<table><thead align="left"><tr id="row207231239162719"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.1"><p id="p1472363915270"><a name="p1472363915270"></a><a name="p1472363915270"></a>头文件</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.2"><p id="p672313910271"><a name="p672313910271"></a><a name="p672313910271"></a>头文件</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p524922814284"><a name="p524922814284"></a><a name="p524922814284"></a>功能描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row1526165392716"><td class="cellrowborder" rowspan="3" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p143125320275"><a name="p143125320275"></a><a name="p143125320275"></a>usbfn_device.h</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1644533274"><a name="p1644533274"></a><a name="p1644533274"></a>const struct UsbFnDevice *UsbFnCreateDevice(const char *udcName, const struct UsbFnDescriptorData *descriptor);</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p241853152716"><a name="p241853152716"></a><a name="p241853152716"></a>创建Usb设备</p>
</td>
</tr>
<tr id="row11261453112717"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p741553102715"><a name="p741553102715"></a><a name="p741553102715"></a>int UsbFnRemoveDevice(struct UsbFnDevice *fnDevice);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p5435318271"><a name="p5435318271"></a><a name="p5435318271"></a>删除Usb设备</p>
</td>
</tr>
<tr id="row126205320278"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p9425362716"><a name="p9425362716"></a><a name="p9425362716"></a>const struct UsbFnDevice *UsbFnGetDevice(const char *udcName);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p54135392719"><a name="p54135392719"></a><a name="p54135392719"></a>获取Usb设备</p>
</td>
</tr>
<tr id="row326125314279"><td class="cellrowborder" rowspan="6" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p144653142719"><a name="p144653142719"></a><a name="p144653142719"></a>usbfn_interface.h</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p941453112713"><a name="p941453112713"></a><a name="p941453112713"></a>int UsbFnStartRecvInterfaceEvent(struct UsbFnInterface *interface, uint32_t eventMask, UsbFnEventCallback callback, void *context);</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1341530277"><a name="p1341530277"></a><a name="p1341530277"></a>开始接受Event事件</p>
</td>
</tr>
<tr id="row172613534273"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p124153152713"><a name="p124153152713"></a><a name="p124153152713"></a>int UsbFnStopRecvInterfaceEvent(struct UsbFnInterface *interface);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1441532271"><a name="p1441532271"></a><a name="p1441532271"></a>停止接受Event事件</p>
</td>
</tr>
<tr id="row1026653142717"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p24185317276"><a name="p24185317276"></a><a name="p24185317276"></a>UsbFnInterfaceHandle UsbFnOpenInterface(struct UsbFnInterface *interface);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p142537274"><a name="p142537274"></a><a name="p142537274"></a>打开一个接口</p>
</td>
</tr>
<tr id="row226195362720"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p114175382715"><a name="p114175382715"></a><a name="p114175382715"></a>int UsbFnCloseInterface(UsbFnInterfaceHandle handle);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p124453132715"><a name="p124453132715"></a><a name="p124453132715"></a>关闭一个接口</p>
</td>
</tr>
<tr id="row12605311277"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p3565313278"><a name="p3565313278"></a><a name="p3565313278"></a>int UsbFnGetInterfacePipeInfo(struct UsbFnInterface *interface, uint8_t pipeId, struct UsbFnPipeInfo *info);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p054536274"><a name="p054536274"></a><a name="p054536274"></a>获取管道信息</p>
</td>
</tr>
<tr id="row19261153132716"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1958532275"><a name="p1958532275"></a><a name="p1958532275"></a>int UsbFnSetInterfaceProp(const struct UsbFnInterface *interface, const char *name, const char *value);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p9516538277"><a name="p9516538277"></a><a name="p9516538277"></a>设置自定义属性</p>
</td>
</tr>
<tr id="row3261853202716"><td class="cellrowborder" rowspan="8" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p65453192711"><a name="p65453192711"></a><a name="p65453192711"></a>usbfn_request.h</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p3520539276"><a name="p3520539276"></a><a name="p3520539276"></a>struct UsbFnRequest *UsbFnAllocCtrlRequest(UsbFnInterfaceHandle handle, uint32_t len);</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p5514538278"><a name="p5514538278"></a><a name="p5514538278"></a>申请一个控制请求</p>
</td>
</tr>
<tr id="row18261253112716"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p85115312277"><a name="p85115312277"></a><a name="p85115312277"></a>struct UsbFnRequest *UsbFnAllocRequest(UsbFnInterfaceHandle handle, uint8_t pipe, uint32_t len);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p105105342716"><a name="p105105342716"></a><a name="p105105342716"></a>申请一个数据请求</p>
</td>
</tr>
<tr id="row82665320272"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1461538279"><a name="p1461538279"></a><a name="p1461538279"></a>int UsbFnFreeRequest(struct UsbFnRequest *req);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p26165372718"><a name="p26165372718"></a><a name="p26165372718"></a>释放一个请求</p>
</td>
</tr>
<tr id="row162610537275"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p261653192714"><a name="p261653192714"></a><a name="p261653192714"></a>int UsbFnSubmitRequestAsync(struct UsbFnRequest *req);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p361253112718"><a name="p361253112718"></a><a name="p361253112718"></a>发送异步请求</p>
</td>
</tr>
<tr id="row1326253122711"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p4611536275"><a name="p4611536275"></a><a name="p4611536275"></a>int UsbFnSubmitRequestSync(struct UsbFnRequest *req, uint32_t timeout);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p06853112710"><a name="p06853112710"></a><a name="p06853112710"></a>发送同步请求</p>
</td>
</tr>
<tr id="row15265539272"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p177453102712"><a name="p177453102712"></a><a name="p177453102712"></a>int UsbFnCancelRequest(struct UsbFnRequest *req);</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p13725312275"><a name="p13725312275"></a><a name="p13725312275"></a>取消请求</p>
</td>
</tr>
</tbody>
</table>
## 开发指导<a name="section581mcpsimp"></a>
USB驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同USB器件提供统一的驱动模型。本篇开发指导以串口为例,分别介绍USB Host和USB Device驱动开发。 USB驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同USB器件提供统一的驱动模型。本篇开发指导以串口为例,分别介绍USB Host和USB Device驱动开发。
### 开发步骤<a name="section583mcpsimp"></a>
### Host DDK API驱动开发步骤<a name="section584mcpsimp"></a> ### Host DDK API驱动开发步骤
1. 驱动匹配表配置。 1. 驱动匹配表配置。
2. 初始化Host DDK。 2. 初始化Host DDK。
3. 待步骤2初始化完后获取UsbInterface接口对象。 3. 待步骤2初始化完后获取UsbInterface接口对象。
4. 打开步骤3获取到的UsbInterface接口对象,获取相应接口的UsbInterfaceHandle对象。 4. 打开步骤3获取到的UsbInterface接口对象,获取相应接口的UsbInterfaceHandle对象。
5. 根据步骤4获取到的UsbInterfaceHandle对象,获取指定索引为pipeIndex的pipeInfo信息。 5. 根据步骤4获取到的UsbInterfaceHandle对象,获取指定索引为pipeIndex的pipeInfo信息。
6. 为步骤4获取到的UsbInterfaceHandle预先分配待发送的IO Request对象。 6. 为步骤4获取到的UsbInterfaceHandle预先分配待发送的IO Request对象。
7. 根据输入参数params填充步骤6预先分配的IO Request。 7. 根据输入参数params填充步骤6预先分配的IO Request。
8. 提交IO Request对象,可以选择同步或异步两种模式。 8. 提交IO Request对象,可以选择同步或异步两种模式。
### Host RAW API驱动开发步骤<a name="section594mcpsimp"></a>
### Host RAW API驱动开发步骤
1. 驱动匹配表配置。 1. 驱动匹配表配置。
2. 初始化Host RAW,并打开USB设备,然后获取描述符,通过描述符获取接口、端点信息。 2. 初始化Host RAW,并打开USB设备,然后获取描述符,通过描述符获取接口、端点信息。
3. 分配Request,并根据传输类型使用相应接口对Request进行填充。 3. 分配Request,并根据传输类型使用相应接口对Request进行填充。
4. 提交IO Request对象,可以选择同步或异步两种模式。 4. 提交IO Request对象,可以选择同步或异步两种模式。
### Device DDK API驱动开发步骤<a name="section600mcpsimp"></a>
### Device DDK API驱动开发步骤
1. 构造描述符。 1. 构造描述符。
2. 创建设备,使用步骤1构造的描述符实例化一个USB设备。 2. 创建设备,使用步骤1构造的描述符实例化一个USB设备。
3. 根据创建的设备获取接口(UsbFnDeviceGetInterface),获取Pipe信息(UsbFnInterfaceGetPipeInfo),打开接口获取Handle(UsbFnInterfaceOpen),根据Handle和Pipe号获取Request(UsbFnRequestAlloc)。 3. 根据创建的设备获取接口(UsbFnDeviceGetInterface),获取Pipe信息(UsbFnInterfaceGetPipeInfo),打开接口获取Handle(UsbFnInterfaceOpen),根据Handle和Pipe号获取Request(UsbFnRequestAlloc)。
4. 接收Event事件(UsbFnInterfaceStartRecvEvent)如Enable、Setup等事件,回调函数(UsbFnEventCallback)中对Event事件做出响应。 4. 接收Event事件(UsbFnInterfaceStartRecvEvent)如Enable、Setup等事件,回调函数(UsbFnEventCallback)中对Event事件做出响应。
5. 收发数据,可以选择同步异步发送模式。 5. 收发数据,可以选择同步异步发送模式。
## 开发实例<a name="section607mcpsimp"></a>
## 开发实例
本实例提供USB串口驱动开发示例,并简要对具体关键点进行开发说明。 本实例提供USB串口驱动开发示例,并简要对具体关键点进行开发说明。
### Host DDK API驱动开发<a name="section609mcpsimp"></a>
### Host DDK API驱动开发
``` ```
root { root {
...@@ -492,7 +258,7 @@ static int SerialCtrlMsg(struct AcmDevice *acm, uint8_t request, ...@@ -492,7 +258,7 @@ static int SerialCtrlMsg(struct AcmDevice *acm, uint8_t request,
controlParams.request = request; controlParams.request = request;
controlParams.target = USB_REQUEST_TARGET_INTERFACE; controlParams.target = USB_REQUEST_TARGET_INTERFACE;
controlParams.reqType = USB_REQUEST_TYPE_CLASS; controlParams.reqType = USB_REQUEST_TYPE_CLASS;
controlParams.directon = USB_REQUEST_DIR_TO_DEVICE; controlParams.direction = USB_REQUEST_DIR_TO_DEVICE;
controlParams.value = value; controlParams.value = value;
controlParams.index = index; controlParams.index = index;
controlParams.data = buf; controlParams.data = buf;
...@@ -660,7 +426,7 @@ static int AcmAllocReadRequests(struct AcmDevice *acm) ...@@ -660,7 +426,7 @@ static int AcmAllocReadRequests(struct AcmDevice *acm)
readParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE; readParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE;
readParams.timeout = USB_CTRL_SET_TIMEOUT; readParams.timeout = USB_CTRL_SET_TIMEOUT;
readParams.dataReq.numIsoPackets = 0; readParams.dataReq.numIsoPackets = 0;
readParams.dataReq.directon = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1; readParams.dataReq.direction = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1;
readParams.dataReq.length = acm->readSize; readParams.dataReq.length = acm->readSize;
ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams); //填充待发送的readReq对象 ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParams); //填充待发送的readReq对象
if (HDF_SUCCESS != ret) { if (HDF_SUCCESS != ret) {
...@@ -692,7 +458,7 @@ static int AcmAllocNotifyRequest(struct AcmDevice *acm) ...@@ -692,7 +458,7 @@ static int AcmAllocNotifyRequest(struct AcmDevice *acm)
intParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE; intParams.requestType = USB_REQUEST_PARAMS_DATA_TYPE;
intParams.timeout = USB_CTRL_SET_TIMEOUT; intParams.timeout = USB_CTRL_SET_TIMEOUT;
intParams.dataReq.numIsoPackets = 0; intParams.dataReq.numIsoPackets = 0;
intParams.dataReq.directon = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK; intParams.dataReq.direction = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK;
intParams.dataReq.length = acm->intSize; intParams.dataReq.length = acm->intSize;
ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams); //填充预先分配的中断IO Request ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParams); //填充预先分配的中断IO Request
if (HDF_SUCCESS != ret) { if (HDF_SUCCESS != ret) {
...@@ -1019,7 +785,9 @@ struct HdfDriverEntry g_usbSerialDriverEntry = { ...@@ -1019,7 +785,9 @@ struct HdfDriverEntry g_usbSerialDriverEntry = {
HDF_INIT(g_usbSerialDriverEntry); HDF_INIT(g_usbSerialDriverEntry);
``` ```
### Host RAW API驱动开发<a name="section612mcpsimp"></a>
### Host RAW API驱动开发
``` ```
root { root {
...@@ -1453,9 +1221,11 @@ struct HdfDriverEntry g_usbSerialRawDriverEntry = { ...@@ -1453,9 +1221,11 @@ struct HdfDriverEntry g_usbSerialRawDriverEntry = {
HDF_INIT(g_usbSerialRawDriverEntry); HDF_INIT(g_usbSerialRawDriverEntry);
``` ```
### Device DDK API驱动开发<a name="section615mcpsimp"></a>
USB ACM设备核心代码路径为drivers/peripheral/usb/gadget/function/acm/cdcacm.c,其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。 ### Device DDK API驱动开发
USB ACM设备核心代码路径为drivers\peripheral\usb\gadget\function\acm\cdcacm.c,其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。
``` ```
1、创建设备 1、创建设备
...@@ -1548,4 +1318,3 @@ int32_t ret; ...@@ -1548,4 +1318,3 @@ int32_t ret;
return ret; return ret;
} }
``` ```
# 外设驱动使用<a name="ZH-CN_TOPIC_0000001157319411"></a> # 外设驱动使用
- **[LCD](driver-peripherals-lcd-des.md)** - **[LCD](driver-peripherals-lcd-des.md)**
- **[TOUCHSCREEN](driver-peripherals-touch-des.md)** - **[Touchscreen](driver-peripherals-touch-des.md)**
- **[SENSOR](driver-peripherals-sensor-des.md)** - **[SENSOR](driver-peripherals-sensor-des.md)**
- **[WLAN](driver-peripherals-external-des.md)** - **[WLAN](driver-peripherals-external-des.md)**
- **[AUDIO](driver-peripherals-audio-des.md)** - **[USB](driver-peripherals-usb-des.md)**
\ No newline at end of file \ No newline at end of file
# ADC<a name="ZH-CN_TOPIC_0000001176922482"></a> # ADC
- [概述](#section268031773165048)
- [接口说明](#section752964871810)
- [开发步骤](#section100579767165048)
- [开发实例](#section1745221471165048)
## 概述<a name="section268031773165048"></a> ## 概述
ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备,在HDF框架中,ADC模块接口适配模式采用统一服务模式,这需要一个设备服务来作为ADC模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如ADC可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备,在HDF框架中,ADC模块接口适配模式采用统一服务模式,这需要一个设备服务来作为ADC模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如ADC可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。
**图 1** ADC统一服务模式<a name="fig14423182615525"></a> **图1** ADC统一服务
![](figures/统一服务模式结构图.png "ADC统一服务模式") ![zh-cn_image_0000001177082414](figures/zh-cn_image_0000001177082414.png)
## 接口说明<a name="section752964871810"></a>
## 接口说明
AdcMethod定义: AdcMethod定义:
``` ```
struct AdcMethod { struct AdcMethod {
int32_t (*read)(struct AdcDevice *device, uint32_t channel, uint32_t *val); int32_t (*read)(struct AdcDevice *device, uint32_t channel, uint32_t *val);
...@@ -24,88 +22,41 @@ struct AdcMethod { ...@@ -24,88 +22,41 @@ struct AdcMethod {
}; };
``` ```
**表 1** AdcMethod结构体成员的回调函数功能说明 **表1** AdcMethod结构体成员的回调函数功能说明
<a name="table27410339187"></a> | 函数成员 | 入参 | 出参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row1274333151812"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p1074173315189"><a name="p1074173315189"></a><a name="p1074173315189"></a>函数成员</p> | -------- | -------- | -------- | -------- | -------- |
</th> | read | device:&nbsp;结构体指针,核心层ADC控制器;<br/>channel:uint32_t,传入的通道号; | val:uint32_t指针,要传出的信号数据; | HDF_STATUS相关状态 | 读取ADC采样的信号数据 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p174153361814"><a name="p174153361814"></a><a name="p174153361814"></a>入参</p> | stop | device:&nbsp;结构体指针,核心层ADC控制器; | 无 | HDF_STATUS相关状态 | 关闭ADC设备 |
</th> | start | device:&nbsp;结构体指针,核心层ADC控制器; | 无 | HDF_STATUS相关状态 | 开启ADC设备 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p17741339184"><a name="p17741339184"></a><a name="p17741339184"></a>出参</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p5742332183"><a name="p5742332183"></a><a name="p5742332183"></a>返回值</p> ## 开发步骤
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p27443317185"><a name="p27443317185"></a><a name="p27443317185"></a>功能</p>
</th>
</tr>
</thead>
<tbody><tr id="row774193321812"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p107423318188"><a name="p107423318188"></a><a name="p107423318188"></a>read</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p27463351815"><a name="p27463351815"></a><a name="p27463351815"></a>device: 结构体指针,核心层ADC控制器;channel:uint32_t,传入的通道号;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p19741733111814"><a name="p19741733111814"></a><a name="p19741733111814"></a>val:uint32_t指针,要传出的信号数据;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p167483331812"><a name="p167483331812"></a><a name="p167483331812"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p97419330182"><a name="p97419330182"></a><a name="p97419330182"></a>读取ADC采样的信号数据</p>
</td>
</tr>
<tr id="row27453313184"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p27483314185"><a name="p27483314185"></a><a name="p27483314185"></a>stop</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p3751033111810"><a name="p3751033111810"></a><a name="p3751033111810"></a>device: 结构体指针,核心层ADC控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p975233171819"><a name="p975233171819"></a><a name="p975233171819"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p17751333131814"><a name="p17751333131814"></a><a name="p17751333131814"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1275533131812"><a name="p1275533131812"></a><a name="p1275533131812"></a>关闭ADC设备</p>
</td>
</tr>
<tr id="row1975173311819"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1575123381810"><a name="p1575123381810"></a><a name="p1575123381810"></a>start</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p12754335185"><a name="p12754335185"></a><a name="p12754335185"></a>device: 结构体指针,核心层ADC控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p875163318182"><a name="p875163318182"></a><a name="p875163318182"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p37533311817"><a name="p37533311817"></a><a name="p37533311817"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p675933171813"><a name="p675933171813"></a><a name="p675933171813"></a>开启ADC设备</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section100579767165048"></a>
ADC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 ADC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加adc\_config.hcs器件属性文件。 - 【可选】添加adc_config.hcs器件属性文件。
3. **实例化ADC控制器对象:** 3. **实例化ADC控制器对象:**
- 初始化AdcDevice成员。 - 初始化AdcDevice成员。
- 实例化AdcDevice成员AdcMethod。 - 实例化AdcDevice成员AdcMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化AdcDevice成员AdcMethod,其定义和成员说明见[接口说明](#接口说明)。
>实例化AdcDevice成员AdcMethod,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,信号采集的成功与否等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,信号采集的成功与否等。
## 开发实例<a name="section1745221471165048"></a> ## 开发实例
接下来以 adc\_hi35xx.c 为示例, 展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
接下来以 adc_hi35xx.c 为示例, 展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
ADC驱动入口参考: ADC驱动入口参考:
...@@ -114,6 +65,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -114,6 +65,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
ADC管理器的驱动由核心层实现,厂商不需要关注这部分内容的实现,这个但在实现Init函数的时候需要调用核心层的AdcDeviceAdd函数,它会实现相应功能。 ADC管理器的驱动由核心层实现,厂商不需要关注这部分内容的实现,这个但在实现Init函数的时候需要调用核心层的AdcDeviceAdd函数,它会实现相应功能。
``` ```
static struct HdfDriverEntry g_hi35xxAdcDriverEntry = { static struct HdfDriverEntry g_hi35xxAdcDriverEntry = {
.moduleVersion = 1, .moduleVersion = 1,
...@@ -133,43 +85,19 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -133,43 +85,19 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
HDF_INIT(g_adcManagerEntry); HDF_INIT(g_adcManagerEntry);
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在adc\_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层AdcDevice相关成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在adc_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层AdcDevice相关成员的默认值或限制范围有密切关系。
统一服务模式的特点是device_info文件中第一个设备节点必须为ADC管理器,其各项参数必须如下设置:
统一服务模式的特点是device\_info文件中第一个设备节点必须为ADC管理器,其各项参数必须如下设置: | 成员名 | 值 |
| -------- | -------- |
<a name="table1344068233165048"></a> | moduleName | 固定为&nbsp;HDF_PLATFORM_ADC_MANAGER |
<table><thead align="left"><tr id="row1551612465165048"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1856185125165048p0"><a name="entry1856185125165048p0"></a><a name="entry1856185125165048p0"></a>成员名</p> | serviceName | 无 |
</th> | policy | 具体配置为0,不发布服务 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry720672143165048p0"><a name="entry720672143165048p0"></a><a name="entry720672143165048p0"></a>值</p> | deviceMatchAttr | 没有使用,可忽略 |
</th>
</tr> 从第二个节点开始配置具体ADC控制器信息,此节点并不表示某一路ADC控制器,而是代表一个资源性质设备,用于描述一类ADC控制器的信息。本例只有一个ADC设备,如有多个设备,则需要在device_info文件增加deviceNode信息,以及在adc_config文件中增加对应的器件属性。
</thead>
<tbody><tr id="row583452627165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry747665129165048p0"><a name="entry747665129165048p0"></a><a name="entry747665129165048p0"></a>moduleName</p> - device_info.hcs 配置参考。
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry912596825165048p0"><a name="entry912596825165048p0"></a><a name="entry912596825165048p0"></a>固定为 HDF_PLATFORM_ADC_MANAGER</p>
</td>
</tr>
<tr id="row218211231165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry568759156165048p0"><a name="entry568759156165048p0"></a><a name="entry568759156165048p0"></a>serviceName</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1349637957165048p0"><a name="entry1349637957165048p0"></a><a name="entry1349637957165048p0"></a>无</p>
</td>
</tr>
<tr id="row1166331861165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1142726988165048p0"><a name="entry1142726988165048p0"></a><a name="entry1142726988165048p0"></a>policy</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry781016408165048p0"><a name="entry781016408165048p0"></a><a name="entry781016408165048p0"></a>具体配置为0,不发布服务</p>
</td>
</tr>
<tr id="row1822624516165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry982991296165048p0"><a name="entry982991296165048p0"></a><a name="entry982991296165048p0"></a>deviceMatchAttr</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry367170471165048p0"><a name="entry367170471165048p0"></a><a name="entry367170471165048p0"></a>没有使用,可忽略</p>
</td>
</tr>
</tbody>
</table>
从第二个节点开始配置具体ADC控制器信息,此节点并不表示某一路ADC控制器,而是代表一个资源性质设备,用于描述一类ADC控制器的信息。本例只有一个ADC设备,如有多个设备,则需要在device\_info文件增加deviceNode信息,以及在adc\_config文件中增加对应的器件属性。
- device\_info.hcs 配置参考。
``` ```
root { root {
...@@ -196,8 +124,8 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -196,8 +124,8 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
} }
} }
``` ```
- adc_config.hcs 配置参考。
- adc\_config.hcs 配置参考。
``` ```
root { root {
...@@ -228,7 +156,8 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -228,7 +156,8 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
3. 完成驱动入口注册之后,最后一步就是以核心层AdcDevice对象的初始化为核心,包括初始化厂商自定义结构体(传递参数和数据),实例化AdcDevice成员AdcMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层AdcDevice对象的初始化为核心,包括初始化厂商自定义结构体(传递参数和数据),实例化AdcDevice成员AdcMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考。 - 自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且adc\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层AdcDevice对象,例如设备号、总线号等。 从驱动的角度看,自定义结构体是参数和数据的载体,而且adc_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层AdcDevice对象,例如设备号、总线号等。
``` ```
struct Hi35xxAdcDevice { struct Hi35xxAdcDevice {
...@@ -260,6 +189,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -260,6 +189,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
- AdcDevice成员回调函数结构体AdcMethod的实例化,AdcLockMethod回调函数结构体本例未实现,若要实例化,可参考I2C驱动开发,其他成员在Init函数中初始化。 - AdcDevice成员回调函数结构体AdcMethod的实例化,AdcLockMethod回调函数结构体本例未实现,若要实例化,可参考I2C驱动开发,其他成员在Init函数中初始化。
``` ```
static const struct AdcMethod g_method = { static const struct AdcMethod g_method = {
.read = Hi35xxAdcRead, .read = Hi35xxAdcRead,
...@@ -267,56 +197,24 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -267,56 +197,24 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
.start = Hi35xxAdcStart, .start = Hi35xxAdcStart,
}; };
``` ```
- Init函数参考
- init函数参考
入参: 入参:
HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。
返回值: 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
<a name="table127573104165048"></a> | 状态(值) | 问题描述 |
<table><thead align="left"><tr id="row1932243367165048"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry405408385165048p0"><a name="entry405408385165048p0"></a><a name="entry405408385165048p0"></a>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry407875094165048p0"><a name="entry407875094165048p0"></a><a name="entry407875094165048p0"></a>问题描述</p> | HDF_ERR_INVALID_PARAM | 参数非法 |
</th> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</tr> | HDF_ERR_IO | I/O&nbsp;错误 |
</thead> | HDF_SUCCESS | 传输成功 |
<tbody><tr id="row1845195554165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry144793493165048p0"><a name="entry144793493165048p0"></a><a name="entry144793493165048p0"></a>HDF_ERR_INVALID_OBJECT</p> | HDF_FAILURE | 传输失败 |
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1933449399165048p0"><a name="entry1933449399165048p0"></a><a name="entry1933449399165048p0"></a>控制器对象非法</p>
</td>
</tr>
<tr id="row1203086670165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry766973904165048p0"><a name="entry766973904165048p0"></a><a name="entry766973904165048p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry999036326165048p0"><a name="entry999036326165048p0"></a><a name="entry999036326165048p0"></a>参数非法</p>
</td>
</tr>
<tr id="row1147526196165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry271913224165048p0"><a name="entry271913224165048p0"></a><a name="entry271913224165048p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1349459344165048p0"><a name="entry1349459344165048p0"></a><a name="entry1349459344165048p0"></a>内存分配失败</p>
</td>
</tr>
<tr id="row42206428165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry826579070165048p0"><a name="entry826579070165048p0"></a><a name="entry826579070165048p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry740637684165048p0"><a name="entry740637684165048p0"></a><a name="entry740637684165048p0"></a>I/O 错误</p>
</td>
</tr>
<tr id="row456623770165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry2126491887165048p0"><a name="entry2126491887165048p0"></a><a name="entry2126491887165048p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1585614415165048p0"><a name="entry1585614415165048p0"></a><a name="entry1585614415165048p0"></a>传输成功</p>
</td>
</tr>
<tr id="row2048732992165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry131232818165048p0"><a name="entry131232818165048p0"></a><a name="entry131232818165048p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry42178503165048p0"><a name="entry42178503165048p0"></a><a name="entry42178503165048p0"></a>传输失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
...@@ -370,7 +268,6 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -370,7 +268,6 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
return ret; return ret;
} }
``` ```
- Release 函数参考 - Release 函数参考
入参: 入参:
...@@ -385,6 +282,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -385,6 +282,7 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。
``` ```
static void Hi35xxAdcRelease(struct HdfDeviceObject *device) static void Hi35xxAdcRelease(struct HdfDeviceObject *device)
{ {
...@@ -419,6 +317,3 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -419,6 +317,3 @@ ADC模块适配的三个环节是配置属性文件,实例化驱动入口,
} }
return return
``` ```
# GPIO<a name="ZH-CN_TOPIC_0000001206171135"></a> # GPIO
- [概述](#section1635911016188)
- [接口说明](#section589913442203)
- [使用指导](#section259614242196)
- [使用流程](#section103477714216)
- [确定GPIO管脚号](#section370083272117)
- [使用API操作GPIO管脚](#section13604050132118)
- [使用实例](#section25941262111) ## 概述
## 概述<a name="section1635911016188"></a>
GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。 GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。
GPIO接口定义了操作GPIO管脚的标准方法集合,包括: GPIO接口定义了操作GPIO管脚的标准方法集合,包括:
- 设置管脚方向: 方向可以是输入或者输出\(暂不支持高阻态\) - 设置管脚方向:方向可以是输入或者输出(暂不支持高阻态)
- 读写管脚电平值:电平值可以是低电平或高电平
- 读写管脚电平值: 电平值可以是低电平或高电平
- 设置管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式 - 设置管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式
- 使能和禁止管脚中断:禁止或使能管脚中断 - 使能和禁止管脚中断:禁止或使能管脚中断
## 接口说明<a name="section589913442203"></a>
## 接口说明
**表 1** GPIO驱动API接口功能介绍
**表1** GPIO驱动API接口功能介绍
<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>功能分类</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>接口名</p> | GPIO读写 | -&nbsp;GpioRead:读管脚电平值<br/>-&nbsp;GpioWrite:写管脚电平值 |
</th> | GPIO配置 | -&nbsp;GpioSetDir:设置管脚方向<br/>-&nbsp;GpioGetDir:获取管脚方向 |
<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>描述</p> | GPIO中断设置 | -&nbsp;GpioSetIrq:设置管脚对应的中断服务函数<br/>-&nbsp;GpioUnSetIrq:取消管脚对应的中断服务函数<br/>-&nbsp;GpioEnableIrq:使能管脚中断<br/>-&nbsp;GpioDisableIrq:禁止管脚中断 |
</th>
</tr> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
</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读写</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>读管脚电平值</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> GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如下图所示。
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p396814715219"><a name="p396814715219"></a><a name="p396814715219"></a>写管脚电平值</p> **图1** GPIO使用流程图
</td>
</tr> ![zh-cn_image_0000001206291109](figures/zh-cn_image_0000001206291109.png)
<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配置</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> ### 确定GPIO管脚号
</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>设置管脚方向</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>获取管脚方向</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中断设置</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>设置管脚对应的中断服务函数</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>取消管脚对应的中断服务函数</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>使能管脚中断</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>禁止管脚中断</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
## 使用指导<a name="section259614242196"></a>
### 使用流程<a name="section103477714216"></a>
GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如[图1](#fig16151101653713)所示。
**图 1** GPIO使用流程图<a name="fig16151101653713"></a>
![](figures/GPIO使用流程图.png "GPIO使用流程图")
### 确定GPIO管脚号<a name="section370083272117"></a>
不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。 不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。
- Hi3516DV300 - Hi3516DV300
控制器管理12组GPIO管脚,每组8个。 控制器管理12组GPIO管脚,每组8个。
GPIO号 = GPIO组索引 \(0\~11\) \* 每组GPIO管脚数\(8\) + 组内偏移 GPIO号 = GPIO组索引 (0~11) \* 每组GPIO管脚数(8) + 组内偏移
举例:GPIO10\_3的GPIO号 = 10 \* 8 + 3 = 83 举例:GPIO10_3的GPIO号 = 10 \* 8 + 3 = 83
- Hi3518EV300 - Hi3518EV300
控制器管理10组GPIO管脚,每组10个。 控制器管理10组GPIO管脚,每组10个。
GPIO号 = GPIO组索引 \(0\~9\) \* 每组GPIO管脚数\(10\) + 组内偏移 GPIO号 = GPIO组索引 (0~9) \* 每组GPIO管脚数(10) + 组内偏移
举例:GPIO7\_3的GPIO管脚号 = 7 \* 10 + 3 = 73 举例:GPIO7_3的GPIO管脚号 = 7 \* 10 + 3 = 73
### 使用API操作GPIO管脚<a name="section13604050132118"></a> ### 使用API操作GPIO管脚
- 设置GPIO管脚方向 - 设置GPIO管脚方向
在进行GPIO管脚读写前,需要先通过如下函数设置GPIO管脚方向: 在进行GPIO管脚读写前,需要先通过如下函数设置GPIO管脚方向:
int32\_t GpioSetDir\(uint16\_t gpio, uint16\_t dir\); int32_t GpioSetDir(uint16_t gpio, uint16_t dir);
**表 2** 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="b10652133033813"><a name="b10652133033813"></a><a name="b10652133033813"></a>参数</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p5311454616"><a name="p5311454616"></a><a name="p5311454616"></a><strong id="b4664103014388"><a name="b4664103014388"></a><a name="b4664103014388"></a>参数描述</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管脚号</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>待设置的方向值</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="b1611673413811"><a name="b1611673413811"></a><a name="b1611673413811"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p83111151165"><a name="p83111151165"></a><a name="p83111151165"></a><strong id="b1511720344387"><a name="b1511720344387"></a><a name="b1511720344387"></a>返回值描述</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>设置成功</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>负数</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p153121553610"><a name="p153121553610"></a><a name="p153121553610"></a>设置失败</p>
</td>
</tr>
</tbody>
</table>
**表2** GpioSetDir参数和返回值描述
| **参数**| **参数描述** |
| -------- | -------- |
| gpio | 待设置的GPIO管脚号 |
| dir | 待设置的方向值 |
| **返回值** | **返回值描述** |
| 0 | 设置成功 |
| 负数 | 设置失败 |
- 读写GPIO管脚 - 读写GPIO管脚
如果要读取一个GPIO管脚电平,通过以下函数完成: 如果要读取一个GPIO管脚电平,通过以下函数完成:
int32\_t GpioRead\(uint16\_t gpio, uint16\_t \*val\); int32_t GpioRead(uint16_t gpio, uint16_t \*val);
**表 3** GpioRead参数和返回值描述 **表3** 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="b734894354816"><a name="b734894354816"></a><a name="b734894354816"></a>参数</strong></p> | -------- | -------- |
</td> | gpio | 待读取的GPIO管脚号 |
<td class="cellrowborder" valign="top" width="51.88%"><p id="p134810432488"><a name="p134810432488"></a><a name="p134810432488"></a><strong id="b15348184316484"><a name="b15348184316484"></a><a name="b15348184316484"></a>参数描述</strong></p> | val | 接收读取电平值的指针 |
</td> | **返回值** | **返回值描述** |
</tr> | 0 | 读取成功 |
<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管脚号</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>接收读取电平值的指针</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="b153481443164810"><a name="b153481443164810"></a><a name="b153481443164810"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p434894334814"><a name="p434894334814"></a><a name="p434894334814"></a><strong id="b0348144312481"><a name="b0348144312481"></a><a name="b0348144312481"></a>返回值描述</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>读取成功</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>负数</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p93491343144815"><a name="p93491343144815"></a><a name="p93491343144815"></a>读取失败</p>
</td>
</tr>
</tbody>
</table>
如果要向GPIO管脚写入电平值,通过以下函数完成: 如果要向GPIO管脚写入电平值,通过以下函数完成:
int32\_t GpioWrite\(uint16\_t gpio, uint16\_t val\); int32_t GpioWrite(uint16_t gpio, uint16_t val);
**表 4** GpioWrite参数和返回值描述 **表4** 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="b18592193305318"><a name="b18592193305318"></a><a name="b18592193305318"></a>参数</strong></p> | -------- | -------- |
</td> | gpio | 待写入的GPIO管脚号 |
<td class="cellrowborder" valign="top" width="51.88%"><p id="p16149220145216"><a name="p16149220145216"></a><a name="p16149220145216"></a><strong id="b259293317533"><a name="b259293317533"></a><a name="b259293317533"></a>参数描述</strong></p> | val | 待写入的电平值 |
</td> | **返回值** | **返回值描述** |
</tr> | 0 | 写入成功 |
<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管脚号</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>待写入的电平值</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="b62491230155318"><a name="b62491230155318"></a><a name="b62491230155318"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p1150192015527"><a name="p1150192015527"></a><a name="p1150192015527"></a><strong id="b19249183017531"><a name="b19249183017531"></a><a name="b19249183017531"></a>返回值描述</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>写入成功</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>负数</p>
</td>
<td class="cellrowborder" valign="top" width="51.88%"><p id="p13150320105212"><a name="p13150320105212"></a><a name="p13150320105212"></a>写入失败</p>
</td>
</tr>
</tbody>
</table>
示例代码: 示例代码:
``` ```
int32_t ret; int32_t ret;
uint16_t val; uint16_t val;
...@@ -270,175 +136,74 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流 ...@@ -270,175 +136,74 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流
ret = GpioRead(6, &val); ret = GpioRead(6, &val);
``` ```
- 设置GPIO中断 - 设置GPIO中断
如果要为一个GPIO管脚设置中断响应程序,使用如下函数: 如果要为一个GPIO管脚设置中断响应程序,使用如下函数:
int32\_t GpioSetIrq\(uint16\_t gpio, uint16\_t mode, GpioIrqFunc func, void \*arg\); int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void \*arg);
**表 5** GpioSetIrq参数和返回值描述 **表5** 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="b1937285817588"><a name="b1937285817588"></a><a name="b1937285817588"></a>参数</strong></p> | -------- | -------- |
</td> | gpio | GPIO管脚号 |
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p48041318114619"><a name="p48041318114619"></a><a name="p48041318114619"></a><strong id="b16384758165818"><a name="b16384758165818"></a><a name="b16384758165818"></a>参数描述</strong></p> | mode | 中断触发模式 |
</td> | func | 中断服务程序 |
</tr> | arg | 传递给中断服务程序的入参 |
<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> | 0 | 设置成功 |
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p6805181818461"><a name="p6805181818461"></a><a name="p6805181818461"></a>GPIO管脚号</p> | 负数 | 设置失败 |
</td>
</tr> > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**
<tr id="row1080541817469"><td class="cellrowborder" valign="top" width="48.54%"><p id="p580541864611"><a name="p580541864611"></a><a name="p580541864611"></a>mode</p> > 同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p380511180463"><a name="p380511180463"></a><a name="p380511180463"></a>中断触发模式</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>中断服务程序</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>传递给中断服务程序的入参</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="b13238195920"><a name="b13238195920"></a><a name="b13238195920"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p680441818466"><a name="p680441818466"></a><a name="p680441818466"></a><strong id="b8324161105915"><a name="b8324161105915"></a><a name="b8324161105915"></a>返回值描述</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>设置成功</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>负数</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p18805141884611"><a name="p18805141884611"></a><a name="p18805141884611"></a>设置失败</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-caution.gif) **注意:**
>同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。
当不再需要响应中断服务函数时,使用如下函数取消中断设置: 当不再需要响应中断服务函数时,使用如下函数取消中断设置:
int32\_t GpioUnSetIrq\(uint16\_t gpio\); int32_t GpioUnSetIrq(uint16_t gpio);
**表 6** GpioUnSetIrq参数和返回值描述 **表6** 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="b55727462431"><a name="b55727462431"></a><a name="b55727462431"></a>参数</strong></p> | -------- | -------- |
</td> | gpio | GPIO管脚号 |
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p185721461435"><a name="p185721461435"></a><a name="p185721461435"></a><strong id="b057213467438"><a name="b057213467438"></a><a name="b057213467438"></a>参数描述</strong></p> | **返回值** | **返回值描述** |
</td> | 0 | 取消成功 |
</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管脚号</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="b145738464432"><a name="b145738464432"></a><a name="b145738464432"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p457384611439"><a name="p457384611439"></a><a name="p457384611439"></a><strong id="b17573104618432"><a name="b17573104618432"></a><a name="b17573104618432"></a>返回值描述</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>取消成功</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>负数</p>
</td>
<td class="cellrowborder" valign="top" width="51.459999999999994%"><p id="p6573164613437"><a name="p6573164613437"></a><a name="p6573164613437"></a>取消失败</p>
</td>
</tr>
</tbody>
</table>
在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断: 在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断:
int32\_t GpioEnableIrq\(uint16\_t gpio\); int32_t GpioEnableIrq(uint16_t gpio);
**表 7** GpioEnableIrq参数和返回值描述 **表7** 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="b050110291902"><a name="b050110291902"></a><a name="b050110291902"></a>参数</strong></p> | -------- | -------- |
</td> | gpio | GPIO管脚号 |
<td class="cellrowborder" valign="top" width="50%"><p id="p566613293568"><a name="p566613293568"></a><a name="p566613293568"></a><strong id="b95144291405"><a name="b95144291405"></a><a name="b95144291405"></a>参数描述</strong></p> | **返回值** | **返回值描述** |
</td> | 0 | 使能成功 |
</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> > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**
<td class="cellrowborder" valign="top" width="50%"><p id="p1566632916566"><a name="p1566632916566"></a><a name="p1566632916566"></a>GPIO管脚号</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="b16177133216016"><a name="b16177133216016"></a><a name="b16177133216016"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p966642917562"><a name="p966642917562"></a><a name="p966642917562"></a><strong id="b101898323018"><a name="b101898323018"></a><a name="b101898323018"></a>返回值描述</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>使能成功</p>
</td>
</tr>
<tr id="row1041891720012"><td class="cellrowborder" valign="top" width="50%"><p id="p766642911562"><a name="p766642911562"></a><a name="p766642911562"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1566652995613"><a name="p1566652995613"></a><a name="p1566652995613"></a>使能失败</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-caution.gif) **注意:**
>必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。
如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断: 如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断:
int32\_t GpioDisableIrq\(uint16\_t gpio\); int32_t GpioDisableIrq(uint16_t gpio);
**表 8** GpioDisableIrq参数和返回值描述 **表8** 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="b196681541715"><a name="b196681541715"></a><a name="b196681541715"></a>参数</strong></p> | -------- | -------- |
</td> | gpio | GPIO管脚号 |
<td class="cellrowborder" valign="top" width="50%"><p id="p46681413119"><a name="p46681413119"></a><a name="p46681413119"></a><strong id="b1966817414115"><a name="b1966817414115"></a><a name="b1966817414115"></a>参数描述</strong></p> | **返回值** | **返回值描述** |
</td> | 0 | 禁止成功 |
</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管脚号</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="b9668144120"><a name="b9668144120"></a><a name="b9668144120"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1766974515"><a name="p1766974515"></a><a name="p1766974515"></a><strong id="b466919418114"><a name="b466919418114"></a><a name="b466919418114"></a>返回值描述</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>禁止成功</p>
</td>
</tr>
<tr id="row176691543117"><td class="cellrowborder" valign="top" width="50%"><p id="p7669941716"><a name="p7669941716"></a><a name="p7669941716"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p4669164219"><a name="p4669164219"></a><a name="p4669164219"></a>禁止失败</p>
</td>
</tr>
</tbody>
</table>
示例代码: 示例代码:
``` ```
/* 中断服务函数 /* 中断服务函数*/
*/
int32_t MyCallBackFunc(uint16_t gpio, void *data) int32_t MyCallBackFunc(uint16_t gpio, void *data)
{ {
HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", __func__, gpio, data); HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", __func__, gpio, data);
...@@ -476,13 +241,13 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流 ...@@ -476,13 +241,13 @@ GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流
``` ```
## 使用实例<a name="section25941262111"></a> ## 使用实例
本实例程序中,我们将测试一个GPIO管脚的中断触发:为管脚设置中断服务函数,触发方式为边沿触发,然后通过交替写高低电平到管脚,产生电平波动,制造触发条件,观察中断服务函数的执行。 本实例程序中,我们将测试一个GPIO管脚的中断触发:为管脚设置中断服务函数,触发方式为边沿触发,然后通过交替写高低电平到管脚,产生电平波动,制造触发条件,观察中断服务函数的执行。
首先需要选取一个空闲的GPIO管脚,本例程基于Hi3516DV300某开发板,GPIO管脚选择GPIO10\_3,换算成GPIO号为83。 首先需要选取一个空闲的GPIO管脚,本例程基于Hi3516DV300某开发板,GPIO管脚选择GPIO10_3,换算成GPIO号为83。
读者可以根据自己使用的开发板,参考其原理图,选择一个空闲的GPIO管脚即可。 读者可以根据自己使用的开发板,参考其原理图,选择一个空闲的GPIO管脚即可。
``` ```
#include "gpio_if.h" #include "gpio_if.h"
...@@ -554,4 +319,3 @@ static int32_t TestCaseGpioIrqEdge(void) ...@@ -554,4 +319,3 @@ static int32_t TestCaseGpioIrqEdge(void)
return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE;
} }
``` ```
# GPIO<a name="ZH-CN_TOPIC_0000001222282165"></a> # GPIO
- [概述](#section1826197354103451)
- [接口说明](#section752964871810)
- [开发步骤](#section731175315103451)
- [开发实例](#section800425816103451)
## 概述<a name="section1826197354103451"></a> ## 概述
GPIO(General-purpose input/output)即通用型输入输出,在HDF框架中,GPIO的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 GPIO(General-purpose input/output)即通用型输入输出,在HDF框架中,
**图 1** GPIO无服务模式结构图<a name="fig5511033193814"></a> GPIO的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。
![](figures/无服务模式结构图.png "GPIO无服务模式结构图")
## 接口说明<a name="section752964871810"></a> **图1** GPIO无服务模式结构图
![zh-cn_image_0000001176603952](figures/zh-cn_image_0000001176603952.png)
## 接口说明
GpioMethod定义: GpioMethod定义:
``` ```
struct GpioMethod { struct GpioMethod {
int32_t (*request)(struct GpioCntlr *cntlr, uint16_t local);// 【预留】 int32_t (*request)(struct GpioCntlr *cntlr, uint16_t local);// 【预留】
...@@ -32,143 +32,47 @@ struct GpioMethod { ...@@ -32,143 +32,47 @@ struct GpioMethod {
} }
``` ```
**表 1** GpioMethod结构体成员的回调函数功能说明 **表1** GpioMethod结构体成员的回调函数功能说明
<a name="table105024430564"></a> | 函数成员 | 入参 | 出参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row150394355618"><th class="cellrowborder" align="center" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p650344375617"><a name="p650344375617"></a><a name="p650344375617"></a>函数成员</p> | -------- | -------- | -------- | -------- | -------- |
</th> | write | cntlr:结构体指针,核心层GPIO控制器;<br/>local:uint16_t,GPIO端口标识号&nbsp;<br/>val:uint16_t,电平传入值; | 无 | HDF_STATUS相关状态 | GPIO引脚写入电平值 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p1450394313564"><a name="p1450394313564"></a><a name="p1450394313564"></a>入参</p> | read | cntlr:结构体指针,核心层GPIO控制器;<br/>local:uint16_t,GPIO端口标识; | val:uint16_t&nbsp;指针,用于传出电平值。 | HDF_STATUS相关状态 | GPIO引脚读取电平值 |
</th> | setDir | cntlr:结构体指针,核心层GPIO控制器;<br/>local:uint16_t,GPIO端口标识号&nbsp;<br/>dir:uint16_t,管脚方向传入值; | 无 | HDF_STATUS相关状态 | 设置GPIO引脚输入/输出方向 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p65031243145610"><a name="p65031243145610"></a><a name="p65031243145610"></a>出参</p> | getDir | cntlr:结构体指针,核心层GPIO控制器;<br/>local:uint16_t,GPIO端口标识号; | dir:uint16_t&nbsp;指针,用于传出管脚方向值。 | HDF_STATUS相关状态 | 读GPIO引脚输入/输出方向 |
</th> | setIrq | cntlr:结构体指针,核心层GPIO控制器;<br/>local:uint16_t,GPIO端口标识号;<br/>mode:uint16_t,表示触发模式(边沿或电平);<br/>func:函数指针,中断服务程序;<br/>arg:void指针,中断服务程序入参; | 无 | HDF_STATUS相关状态 | 将GPIO引脚设置为中断模式 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p65030430564"><a name="p65030430564"></a><a name="p65030430564"></a>返回值</p> | unsetIrq | cntlr:结构体指针,核心层GPIO控制器;<br/>local:uint16_t,GPIO端口标识号; | 无 | HDF_STATUS相关状态 | 取消GPIO中断设置 |
</th> | enableIrq | cntlr:结构体指针,核心层GPIO控制器;<br/>local:uint16_t,GPIO端口标识号; | 无 | HDF_STATUS相关状态 | 使能GPIO管脚中断 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p9503104313563"><a name="p9503104313563"></a><a name="p9503104313563"></a>功能</p> | disableIrq | cntlr:结构体指针,核心层GPIO控制器;<br/>local:uint16_t,GPIO端口标识号; | 无 | HDF_STATUS相关状态 | 禁止GPIO管脚中断 |
</th>
</tr>
</thead> ## 开发步骤
<tbody><tr id="row950310439569"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1550310436563"><a name="p1550310436563"></a><a name="p1550310436563"></a>write</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p2503194315613"><a name="p2503194315613"></a><a name="p2503194315613"></a>cntlr:结构体指针,核心层GPIO控制器;</br>local:uint16_t,GPIO端口标识号;</br>val:uint16_t,电平传入值;</p>
</td>
<td class="cellrowborder" align="left" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p105031443205616"><a name="p105031443205616"></a><a name="p105031443205616"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p145035434561"><a name="p145035434561"></a><a name="p145035434561"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p195031043195615"><a name="p195031043195615"></a><a name="p195031043195615"></a>GPIO引脚写入电平值</p>
</td>
</tr>
<tr id="row115036433568"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p155031843135611"><a name="p155031843135611"></a><a name="p155031843135611"></a>read</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p45033436562"><a name="p45033436562"></a><a name="p45033436562"></a>cntlr:结构体指针,核心层GPIO控制器;</br>local:uint16_t,GPIO端口标识;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p9503943165614"><a name="p9503943165614"></a><a name="p9503943165614"></a>val:uint16_t 指针,用于传出电平值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p12504194305619"><a name="p12504194305619"></a><a name="p12504194305619"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p9504943125620"><a name="p9504943125620"></a><a name="p9504943125620"></a>GPIO引脚读取电平值</p>
</td>
</tr>
<tr id="row4504174312563"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p0504174395612"><a name="p0504174395612"></a><a name="p0504174395612"></a>setDir</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p65041043125616"><a name="p65041043125616"></a><a name="p65041043125616"></a>cntlr:结构体指针,核心层GPIO控制器;</br>local:uint16_t,GPIO端口标识号;</br>dir:uint16_t,管脚方向传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p45044436563"><a name="p45044436563"></a><a name="p45044436563"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p175047436561"><a name="p175047436561"></a><a name="p175047436561"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p15504543115611"><a name="p15504543115611"></a><a name="p15504543115611"></a>设置GPIO引脚输入/输出方向</p>
</td>
</tr>
<tr id="row6504174385620"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p10504114325614"><a name="p10504114325614"></a><a name="p10504114325614"></a>getDir</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p15504184375619"><a name="p15504184375619"></a><a name="p15504184375619"></a>cntlr:结构体指针,核心层GPIO控制器;</br>local:uint16_t,GPIO端口标识号;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p5504343135617"><a name="p5504343135617"></a><a name="p5504343135617"></a>dir:uint16_t 指针,用于传出管脚方向值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1450464314563"><a name="p1450464314563"></a><a name="p1450464314563"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p20504104385610"><a name="p20504104385610"></a><a name="p20504104385610"></a>读GPIO引脚输入/输出方向</p>
</td>
</tr>
<tr id="row750419431561"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1950414335619"><a name="p1950414335619"></a><a name="p1950414335619"></a>setIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p115049434567"><a name="p115049434567"></a><a name="p115049434567"></a>cntlr:结构体指针,核心层GPIO控制器;</br>local:uint16_t,GPIO端口标识号;</br>mode:uint16_t,表示触发模式(边沿或电平);</br>func:函数指针,中断服务程序;</br>arg:void指针,中断服务程序入参;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1350414345615"><a name="p1350414345615"></a><a name="p1350414345615"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p10504643145610"><a name="p10504643145610"></a><a name="p10504643145610"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p10504194375613"><a name="p10504194375613"></a><a name="p10504194375613"></a>将GPIO引脚设置为中断模式</p>
</td>
</tr>
<tr id="row35041243125616"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1650413438568"><a name="p1650413438568"></a><a name="p1650413438568"></a>unsetIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1550484310568"><a name="p1550484310568"></a><a name="p1550484310568"></a>cntlr:结构体指针,核心层GPIO控制器;</br>local:uint16_t,GPIO端口标识号;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1850494310566"><a name="p1850494310566"></a><a name="p1850494310566"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p2504134316569"><a name="p2504134316569"></a><a name="p2504134316569"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p150410432569"><a name="p150410432569"></a><a name="p150410432569"></a>取消GPIO中断设置</p>
</td>
</tr>
<tr id="row5504124335615"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1350464365618"><a name="p1350464365618"></a><a name="p1350464365618"></a>enableIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1750414316563"><a name="p1750414316563"></a><a name="p1750414316563"></a>cntlr:结构体指针,核心层GPIO控制器;</br>local:uint16_t,GPIO端口标识号;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p8505104315612"><a name="p8505104315612"></a><a name="p8505104315612"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p135051043175619"><a name="p135051043175619"></a><a name="p135051043175619"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p14505204345619"><a name="p14505204345619"></a><a name="p14505204345619"></a>使能GPIO管脚中断</p>
</td>
</tr>
<tr id="row1250517432566"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p115052430563"><a name="p115052430563"></a><a name="p115052430563"></a>disableIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p165051435567"><a name="p165051435567"></a><a name="p165051435567"></a>cntlr:结构体指针,核心层GPIO控制器;</br>local:uint16_t,GPIO端口标识号;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p750514438565"><a name="p750514438565"></a><a name="p750514438565"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p150544375618"><a name="p150544375618"></a><a name="p150544375618"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p15505154355613"><a name="p15505154355613"></a><a name="p15505154355613"></a>禁止GPIO管脚中断</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section731175315103451"></a>
GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。GPIO控制器分组管理所有管脚,相关参数会在属性文件中有所体现;驱动入口和接口函数的实例化环节是厂商驱动接入HDF的核心环节。 GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。GPIO控制器分组管理所有管脚,相关参数会在属性文件中有所体现;驱动入口和接口函数的实例化环节是厂商驱动接入HDF的核心环节。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加gpio\_config.hcs器件属性文件。 - 【可选】添加gpio_config.hcs器件属性文件。
3. **实例化GPIO控制器对象:** 3. **实例化GPIO控制器对象:**
- 初始化GpioCntlr成员。 - 初始化GpioCntlr成员。
- 实例化GpioCntlr成员GpioMethod。 - 实例化GpioCntlr成员GpioMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化GpioCntlr成员GpioMethod,详见[接口说明](#接口说明)。
>实例化GpioCntlr成员GpioMethod,详见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如GPIO控制状态,中断响应情况等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如GPIO控制状态,中断响应情况等。
## 开发实例<a name="section800425816103451"></a> ## 开发实例
下方将以gpio\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以gpio_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
GPIO 驱动入口参考: GPIO 驱动入口参考:
...@@ -185,11 +89,10 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -185,11 +89,10 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,
HDF_INIT(g_gpioDriverEntry); HDF_INIT(g_gpioDriverEntry);
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 gpio\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层GpioCntlr 成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 gpio_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层GpioCntlr 成员的默认值或限制范围有密切关系。
本例只有一个GPIO控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在gpio_config文件中增加对应的器件属性。
本例只有一个GPIO控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在gpio\_config文件中增加对应的器件属性。
- device\_info.hcs 配置参考。 - device_info.hcs 配置参考。
``` ```
root { root {
...@@ -211,8 +114,7 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -211,8 +114,7 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,
} }
} }
``` ```
- gpio_config.hcs 配置参考。
- gpio\_config.hcs 配置参考。
``` ```
root { root {
...@@ -235,7 +137,8 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -235,7 +137,8 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,
3. 完成驱动入口注册之后,最后一步就是以核心层GpioCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化GpioCntlr成员GpioMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层GpioCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化GpioCntlr成员GpioMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考。 - 自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且gpio\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层GpioCntlr对象,例如索引、管脚数等。 从驱动的角度看,自定义结构体是参数和数据的载体,而且gpio_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层GpioCntlr对象,例如索引、管脚数等。
``` ```
struct Pl061GpioCntlr { struct Pl061GpioCntlr {
...@@ -270,9 +173,9 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -270,9 +173,9 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,
void *priv; void *priv;
}; };
``` ```
- GpioCntlr成员回调函数结构体GpioMethod的实例化,其他成员在Init函数中初始化。 - GpioCntlr成员回调函数结构体GpioMethod的实例化,其他成员在Init函数中初始化。
``` ```
//GpioMethod结构体成员都是回调函数,厂商需要根据表1完成相应的函数功能。 //GpioMethod结构体成员都是回调函数,厂商需要根据表1完成相应的函数功能。
static struct GpioMethod g_method = { static struct GpioMethod g_method = {
...@@ -298,54 +201,24 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -298,54 +201,24 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,
返回值: 返回值:
HDF\_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
**表 2** Init函数说明 **表2** Init函数说明
<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>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p185991854163519"><a name="p185991854163519"></a><a name="p185991854163519"></a>问题描述</p> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</th> | HDF_ERR_INVALID_PARAM | 参数非法 |
</tr> | HDF_ERR_IO | I/O&nbsp;错误 |
</thead> | HDF_SUCCESS | 初始化成功 |
<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> | HDF_FAILURE | 初始化失败 |
</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>控制器对象非法</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>内存分配失败</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>参数非法</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 错误</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>初始化成功</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>初始化失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
初始化自定义结构体对象,初始化GpioCntlr成员,调用核心层GpioCntlrAdd函数,【可选】接入VFS。 初始化自定义结构体对象,初始化GpioCntlr成员,调用核心层GpioCntlrAdd函数,【可选】接入VFS。
``` ```
static int32_t Pl061GpioInit(struct HdfDeviceObject *device) static int32_t Pl061GpioInit(struct HdfDeviceObject *device)
{ {
...@@ -377,7 +250,6 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -377,7 +250,6 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,
... ...
} }
``` ```
- Release 函数参考 - Release 函数参考
入参: 入参:
...@@ -392,6 +264,7 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -392,6 +264,7 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。
``` ```
static void Pl061GpioRelease(struct HdfDeviceObject *device) static void Pl061GpioRelease(struct HdfDeviceObject *device)
{ {
...@@ -411,6 +284,3 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -411,6 +284,3 @@ GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,
pl061->regBase = NULL; pl061->regBase = NULL;
} }
``` ```
# 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所示。
- I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA\(SerialData\)串行数据线以及SCL\(SerialClock\)串行时钟线两根线相连,如[图1 ](#fig1135561232714)所示。
- I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。 - I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。
- I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。 - I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。
- I2C接口定义了完成I2C传输的通用方法集合,包括: - I2C接口定义了完成I2C传输的通用方法集合,包括:
- I2C控制器管理: 打开或关闭I2C控制器 - I2C控制器管理: 打开或关闭I2C控制器
- I2C消息传输:通过消息传输结构体数组进行自定义传输 - I2C消息传输:通过消息传输结构体数组进行自定义传输
**图 1** I2C物理连线示意图<a name="fig1135561232714"></a> **图1** I2C物理连线示意图
![](figures/I2C物理连线示意图.png "I2C物理连线示意图")
![zh-cn_image_0000001160653004](figures/zh-cn_image_0000001160653004.png)
## 接口说明<a name="section545869122317"></a>
## 接口说明
**表 1** I2C驱动API接口功能介绍
**表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> | I2C控制器管理接口 | -&nbsp;I2cOpen:打开I2C控制器<br/>-&nbsp;I2cClose:关闭I2C控制器 |
</th> | I2C消息传输接口 | I2cTransfer:自定义传输 |
<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> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
</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> 使用I2C设备的一般流程如下图所示。
<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> **图2** I2C设备使用流程图
<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> ![zh-cn_image_0000001206291495](figures/zh-cn_image_0000001206291495.png)
</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> ### 打开I2C控制器
<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>
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
## 使用指导<a name="section1695201514281"></a>
### 使用流程<a name="section1338373417288"></a>
使用I2C设备的一般流程如[图2](#fig183017194234)所示。
**图 2** I2C设备使用流程图<a name="fig183017194234"></a>
![](figures/I2C设备使用流程图.png "I2C设备使用流程图")
### 打开I2C控制器<a name="section13751110132914"></a>
在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。 在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。
DevHandle I2cOpen\(int16\_t number\); DevHandle I2cOpen(int16_t number);
**表 2** I2cOpen参数和返回值描述 **表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> | number | I2C控制器号 |
<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> | NULL | 打开I2C控制器失败 |
</tr> | 设备句柄 | 打开的I2C控制器设备句柄 |
</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>
假设系统中存在8个I2C控制器,编号从0到7,那么我们现在获取3号控制器 假设系统中存在8个I2C控制器,编号从0到7,那么我们现在获取3号控制器
``` ```
DevHandle i2cHandle = NULL; /* I2C控制器句柄 / DevHandle i2cHandle = NULL; /* I2C控制器句柄 /
...@@ -125,56 +74,27 @@ if (i2cHandle == NULL) { ...@@ -125,56 +74,27 @@ if (i2cHandle == NULL) {
} }
``` ```
### 进行I2C通信<a name="section9202183372916"></a>
### 进行I2C通信
消息传输 消息传输
int32\_t I2cTransfer\(DevHandle handle, struct I2cMsg \*msgs, int16\_t count\); int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count);
**表 3** I2cTransfer参数和返回值描述 **表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> | handle | I2C控制器设备句柄 |
<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> | msgs | 待传输数据的消息结构体数组 |
</th> | count | 消息数组长度 |
</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>
I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。 I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。
``` ```
int32_t ret; int32_t ret;
uint8_t wbuff[2] = { 0x12, 0x13 }; uint8_t wbuff[2] = { 0x12, 0x13 };
...@@ -196,40 +116,35 @@ if (ret != 2) { ...@@ -196,40 +116,35 @@ if (ret != 2) {
} }
``` ```
>![](../public_sys-resources/icon-caution.gif) **注意:** > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**
>- I2cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。 > - I2cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。
>- 本函数不对消息结构体个数count做限制,其最大个数度由具体I2C控制器决定。 >
>- 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I2C控制器决定。 > - 本函数不对消息结构体个数count做限制,其最大个数度由具体I2C控制器决定。
>- 本函数可能会引起系统休眠,不允许在中断上下文调用 >
> - 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I2C控制器决定。
>
> - 本函数可能会引起系统休眠,不允许在中断上下文调用
### 关闭I2C控制器<a name="section19481164133018"></a>
### 关闭I2C控制器
I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所示: I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所示:
void I2cClose\(DevHandle handle\); void I2cClose(DevHandle handle);
**表 4** I2cClose参数和返回值描述 **表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> | handle | I2C控制器设备句柄 |
<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>
``` ```
I2cClose(i2cHandle); /* 关闭I2C控制器 */ I2cClose(i2cHandle); /* 关闭I2C控制器 */
``` ```
## 使用实例<a name="section5302202015300"></a>
## 使用实例
本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。 本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。
...@@ -243,11 +158,12 @@ I2cClose(i2cHandle); /* 关闭I2C控制器 */ ...@@ -243,11 +158,12 @@ I2cClose(i2cHandle); /* 关闭I2C控制器 */
本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。 本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。
>![](../public_sys-resources/icon-note.gif) **说明:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。 > 本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。
示例如下: 示例如下:
``` ```
#include "i2c_if.h" /* I2C标准接口头文件 */ #include "i2c_if.h" /* I2C标准接口头文件 */
#include "gpio_if.h" /* GPIO标准接口头文件 */ #include "gpio_if.h" /* GPIO标准接口头文件 */
...@@ -420,4 +336,3 @@ static int32_t TestCaseI2c(void) ...@@ -420,4 +336,3 @@ static int32_t TestCaseI2c(void)
return ret; return ret;
} }
``` ```
# I2C<a name="ZH-CN_TOPIC_0000001176922456"></a> # I2C
- [概述](#section2040078630114257)
- [接口说明](#section752964871810)
- [开发步骤](#section1085786591114257)
- [开发实例](#section1773332551114257)
## 概述<a name="section2040078630114257"></a> ## 概述
I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线在HDF框架中,I2C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I2C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I2C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线,在HDF框架中,I2C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I2C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I2C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。
**图 1** I2C统一服务模式结构图<a name="fig17640124912440"></a> **图1** I2C统一服务模式结构图
![](figures/统一服务模式结构图.png "I2C统一服务模式结构图")
## 接口说明<a name="section752964871810"></a> ![zh-cn_image_0000001177082394](figures/zh-cn_image_0000001177082394.png)
## 接口说明
I2cMethod和I2cLockMethod定义: I2cMethod和I2cLockMethod定义:
``` ```
struct I2cMethod { struct I2cMethod {
int32_t (*transfer)(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count); int32_t (*transfer)(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
...@@ -26,66 +25,40 @@ struct I2cLockMethod {//锁机制操作结构体 ...@@ -26,66 +25,40 @@ struct I2cLockMethod {//锁机制操作结构体
}; };
``` ```
**表 1** I2cMethod结构体成员的回调函数功能说明 **表1** I2cMethod结构体成员的回调函数功能说明
<a name="table139121605913"></a> | 函数成员 | 入参 | 出参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row1391101625915"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p11391151619599"><a name="p11391151619599"></a><a name="p11391151619599"></a>函数成员</p> | -------- | -------- | -------- | -------- | -------- |
</th> | transfer | cntlr:结构体指针,核心层I2C控制器。<br>msgs:结构体指针,用户消息。<br>count:uint16_t,消息数量。 | 无 | HDF_STATUS相关状态 | 传递用户消息 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p1539261618596"><a name="p1539261618596"></a><a name="p1539261618596"></a>入参</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p2392416175914"><a name="p2392416175914"></a><a name="p2392416175914"></a>出参</p> ## 开发步骤
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p103926169598"><a name="p103926169598"></a><a name="p103926169598"></a>返回值</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p163921316175917"><a name="p163921316175917"></a><a name="p163921316175917"></a>功能</p>
</th>
</tr>
</thead>
<tbody><tr id="row339221695916"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1392716195914"><a name="p1392716195914"></a><a name="p1392716195914"></a>transfer</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p193923162593"><a name="p193923162593"></a><a name="p193923162593"></a>cntlr:结构体指针,核心层I2C控制器;msgs:结构体指针,用户消息 ;count:uint16_t,消息数量</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1539212165594"><a name="p1539212165594"></a><a name="p1539212165594"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p139291617594"><a name="p139291617594"></a><a name="p139291617594"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p6392121655919"><a name="p6392121655919"></a><a name="p6392121655919"></a>传递用户消息</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section1085786591114257"></a>
I2C模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 I2C模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加i2c\_config.hcs器件属性文件。 - 【可选】添加i2c_config.hcs器件属性文件。
3. **实例化I2C控制器对象:** 3. **实例化I2C控制器对象:**
- 初始化I2cCntlr成员。 - 初始化I2cCntlr成员。
- 实例化I2cCntlr成员I2cMethod和I2cLockMethod。 - 实例化I2cCntlr成员I2cMethod和I2cLockMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化I2cCntlr成员I2cMethod和I2cLockMethod,详见[接口说明](#接口说明)。
>实例化I2cCntlr成员I2cMethod和I2cLockMethod,详见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,消息传输的成功与否等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,消息传输的成功与否等。
## 开发实例<a name="section1773332551114257"></a> ## 开发实例
下方将以i2c\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以i2c_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
I2C驱动入口参考: I2C驱动入口参考:
...@@ -94,6 +67,7 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -94,6 +67,7 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
I2C管理器服务的驱动由核心层实现,厂商不需要关注这部分内容的实现,这个但在实现Init函数的时候需要调用核心层的I2cCntlrAdd函数,它会实现相应功能。 I2C管理器服务的驱动由核心层实现,厂商不需要关注这部分内容的实现,这个但在实现Init函数的时候需要调用核心层的I2cCntlrAdd函数,它会实现相应功能。
``` ```
struct HdfDriverEntry g_i2cDriverEntry = { struct HdfDriverEntry g_i2cDriverEntry = {
.moduleVersion = 1, .moduleVersion = 1,
...@@ -114,45 +88,21 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -114,45 +88,21 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
HDF_INIT(g_i2cManagerEntry); HDF_INIT(g_i2cManagerEntry);
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在i2c\_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层I2cCntlr相关成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在i2c_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层I2cCntlr相关成员的默认值或限制范围有密切关系。
统一服务模式的特点是device_info文件中第一个设备节点必须为I2C管理器,其各项参数必须如表2设置:
统一服务模式的特点是device\_info文件中第一个设备节点必须为I2C管理器,其各项参数必须如[表2](#table96651915911)设置:
**表2** 统一服务模式的特点
**表 2** 统一服务模式的特点
| 成员名 | 值 |
<a name="table96651915911"></a> | -------- | -------- |
<table><thead align="left"><tr id="row96618194915"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1066119790"><a name="p1066119790"></a><a name="p1066119790"></a>成员名</p> | moduleName | 固定为HDF_PLATFORM_I2C_MANAGER |
</th> | serviceName | 固定为HDF_PLATFORM_I2C_MANAGER |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p8674191494"><a name="p8674191494"></a><a name="p8674191494"></a>值</p> | policy | 具体配置为1或2取决于是否对用户态可见 |
</th> | deviceMatchAttr | 没有使用,可忽略 |
</tr>
</thead> 从第二个节点开始配置具体I2C控制器信息,此节点并不表示某一路I2C控制器,而是代表一个资源性质设备,用于描述一类I2C控制器的信息。多个控制器之间相互区分的参数是busID和reg_pbase,这在i2c_config文件中有所体现。
<tbody><tr id="row767111916914"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p46714196920"><a name="p46714196920"></a><a name="p46714196920"></a>moduleName</p> - device_info.hcs 配置参考。
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p36717191292"><a name="p36717191292"></a><a name="p36717191292"></a>固定为 HDF_PLATFORM_I2C_MANAGER</p>
</td>
</tr>
<tr id="row16671119392"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p11671019699"><a name="p11671019699"></a><a name="p11671019699"></a>serviceName</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p86716195912"><a name="p86716195912"></a><a name="p86716195912"></a>固定为 HDF_PLATFORM_I2C_MANAGER</p>
</td>
</tr>
<tr id="row17673191911"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p5673191898"><a name="p5673191898"></a><a name="p5673191898"></a>policy</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p18677191699"><a name="p18677191699"></a><a name="p18677191699"></a>具体配置为1或2取决于是否对用户态可见</p>
</td>
</tr>
<tr id="row8675191894"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p12677191913"><a name="p12677191913"></a><a name="p12677191913"></a>deviceMatchAttr</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1567171918915"><a name="p1567171918915"></a><a name="p1567171918915"></a>没有使用,可忽略</p>
</td>
</tr>
</tbody>
</table>
从第二个节点开始配置具体I2C控制器信息,此节点并不表示某一路I2C控制器,而是代表一个资源性质设备,用于描述一类I2C控制器的信息。多个控制器之间相互区分的参数是busID和reg\_pbase,这在i2c\_config文件中有所体现。
- device\_info.hcs 配置参考。
``` ```
root { root {
...@@ -181,7 +131,8 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -181,7 +131,8 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
} }
``` ```
- i2c\_config.hcs 配置参考。 - i2c_config.hcs 配置参考。
``` ```
root { root {
...@@ -212,7 +163,8 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -212,7 +163,8 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
3. 完成驱动入口注册之后,最后一步就是以核心层I2cCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化I2cCntlr成员I2cMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层I2cCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化I2cCntlr成员I2cMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考 - 自定义结构体参考
从驱动的角度看,自定义结构体是参数和数据的载体,而且i2c\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层I2cCntlr对象,例如设备号、总线号等。 从驱动的角度看,自定义结构体是参数和数据的载体,而且i2c_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层I2cCntlr对象,例如设备号、总线号等。
``` ```
// 厂商自定义功能结构体 // 厂商自定义功能结构体
...@@ -238,9 +190,9 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -238,9 +190,9 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
const struct I2cLockMethod *lockOps; const struct I2cLockMethod *lockOps;
}; };
``` ```
- I2cCntlr成员回调函数结构体I2cMethod的实例化,和锁机制回调函数结构体I2cLockMethod实例化,其他成员在Init函数中初始化。 - I2cCntlr成员回调函数结构体I2cMethod的实例化,和锁机制回调函数结构体I2cLockMethod实例化,其他成员在Init函数中初始化。
``` ```
// i2c_hi35xx.c 中的示例 // i2c_hi35xx.c 中的示例
static const struct I2cMethod g_method = { static const struct I2cMethod g_method = {
...@@ -252,8 +204,7 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -252,8 +204,7 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
.unlock = Hi35xxI2cUnlock,//解锁函数 .unlock = Hi35xxI2cUnlock,//解锁函数
}; };
``` ```
- Init函数参考
- init函数参考
入参: 入参:
...@@ -261,54 +212,24 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -261,54 +212,24 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
返回值: 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
**表 3** init函数入参及返回值参考 **表3** Init函数入参及返回值参考
<a name="table1743073181511"></a> | 状态(值) | 问题描述 |
<table><thead align="left"><tr id="row443033171513"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p34306341517"><a name="p34306341517"></a><a name="p34306341517"></a>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p1243123101510"><a name="p1243123101510"></a><a name="p1243123101510"></a>问题描述</p> | HDF_ERR_INVALID_PARAM | 参数非法 |
</th> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</tr> | HDF_ERR_IO | I/O&nbsp;错误 |
</thead> | HDF_SUCCESS | 传输成功 |
<tbody><tr id="row5431638151"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1043114319156"><a name="p1043114319156"></a><a name="p1043114319156"></a>HDF_ERR_INVALID_OBJECT</p> | HDF_FAILURE | 传输失败 |
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p343173101513"><a name="p343173101513"></a><a name="p343173101513"></a>控制器对象非法</p>
</td>
</tr>
<tr id="row1243143181516"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1443118317154"><a name="p1443118317154"></a><a name="p1443118317154"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p343113341515"><a name="p343113341515"></a><a name="p343113341515"></a>参数非法</p>
</td>
</tr>
<tr id="row1943115391516"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1843143171511"><a name="p1843143171511"></a><a name="p1843143171511"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p943114391515"><a name="p943114391515"></a><a name="p943114391515"></a>内存分配失败</p>
</td>
</tr>
<tr id="row1443183101514"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p54311031157"><a name="p54311031157"></a><a name="p54311031157"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p74315311158"><a name="p74315311158"></a><a name="p74315311158"></a>I/O 错误</p>
</td>
</tr>
<tr id="row3431437158"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8432332158"><a name="p8432332158"></a><a name="p8432332158"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p104329391519"><a name="p104329391519"></a><a name="p104329391519"></a>传输成功</p>
</td>
</tr>
<tr id="row34321136152"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p184325391517"><a name="p184325391517"></a><a name="p184325391517"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1343220319154"><a name="p1343220319154"></a><a name="p1343220319154"></a>传输失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
初始化自定义结构体对象,初始化I2cCntlr成员,调用核心层I2cCntlrAdd函数,【可选】接入VFS。 初始化自定义结构体对象,初始化I2cCntlr成员,调用核心层I2cCntlrAdd函数,【可选】接入VFS。
``` ```
static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device) static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device)
{ {
...@@ -354,7 +275,6 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -354,7 +275,6 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
return ret; return ret;
} }
``` ```
- Release 函数参考 - Release 函数参考
入参: 入参:
...@@ -369,6 +289,7 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -369,6 +289,7 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。
``` ```
static void Hi35xxI2cRelease(struct HdfDeviceObject *device) static void Hi35xxI2cRelease(struct HdfDeviceObject *device)
{ {
...@@ -396,6 +317,3 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -396,6 +317,3 @@ I2C模块适配的三个环节是配置属性文件,实例化驱动入口,
return; return;
} }
``` ```
# MIPI-CSI<a name="title_MIPI_CSIDes"></a> # MIPI CSI<a name="title_MIPI_CSIDes"></a>
- [概述](#section1_MIPI_CSIDes)
- [ComboDevAttr结构体](#section1.1_MIPI_CSIDes)
- [ExtDataType结构体](#section1.2_MIPI_CSIDes)
- [接口说明](#section1.3_MIPI_CSIDes)
- [使用指导](#section2_MIPI_CSIDes)
- [使用流程](#section2.1_MIPI_CSIDes)
- [获取MIPI-CSI控制器操作句柄](#section2.2_MIPI_CSIDes)
- [MIPI-CSI相应配置](#section2.3_MIPI_CSIDes)
- [复位/撤销复位sensor](#section2.4_MIPI_CSIDes)
- [复位/撤销复位MIPI RX](#section2.5_MIPI_CSIDes)
- [使能/关闭MIPI的时钟](#section2.6_MIPI_CSIDes)
- [使能/关闭MIPI上的sensor时钟](#section2.7_MIPI_CSIDes)
- [释放MIPI-CSI控制器操作句柄](#section2.8_MIPI_CSIDes)
- [使用实例](#section3_MIPI_CSIDes)
## 概述<a name="section1_MIPI_CSIDes"></a> ## 概述<a name="section1_MIPI_CSIDes"></a>
...@@ -57,14 +42,14 @@ ...@@ -57,14 +42,14 @@
### 接口说明<a name="section1.3_MIPI_CSIDes"></a> ### 接口说明<a name="section1.3_MIPI_CSIDes"></a>
**表 3** MIPI-CSI API接口功能介绍 **表 3** MIPI CSI API接口功能介绍
<a name="table3_MIPI_CSIDes"></a> <a name="table3_MIPI_CSIDes"></a>
| 功能分类 | 接口名 | | 功能分类 | 接口名 |
| -------- | -------- | | -------- | -------- |
| 获取/释放MIPI-CSI控制器操作句柄 | MipiCsiOpen:获取MIPI-CSI控制器操作句柄<br/>MipiCsiClose:释放MIPI-CSI控制器操作句柄 | | 获取/释放MIPI CSI控制器操作句柄 | MipiCsiOpen:获取MIPI CSI控制器操作句柄<br/>MipiCsiClose:释放MIPI CSI控制器操作句柄 |
| MIPI-CSI相应配置 | MipiCsiSetComboDevAttr:设置MIPI,CMOS或者LVDS相机的参数给控制器,参数包括工作模式,图像区域,图像深度,数据速率和物理通道等<br/>MipiCsiSetExtDataType(可选):设置YUV和RAW数据格式和位深<br/>MipiCsiSetHsMode:设置MIPI&nbsp;RX的Lane分布。根据硬件连接的形式选择具体的mode<br/>MipiCsiSetPhyCmvmode:设置共模电压模式 | | MIPI CSI相应配置 | MipiCsiSetComboDevAttr:设置MIPI,CMOS或者LVDS相机的参数给控制器,参数包括工作模式,图像区域,图像深度,数据速率和物理通道等<br/>MipiCsiSetExtDataType(可选):设置YUV和RAW数据格式和位深<br/>MipiCsiSetHsMode:设置MIPI&nbsp;RX的Lane分布。根据硬件连接的形式选择具体的mode<br/>MipiCsiSetPhyCmvmode:设置共模电压模式 |
| 复位/撤销复位Sensor | MipiCsiResetSensor:复位Sensor<br/>MipiCsiUnresetSensor:撤销复位Sensor | | 复位/撤销复位Sensor | MipiCsiResetSensor:复位Sensor<br/>MipiCsiUnresetSensor:撤销复位Sensor |
| 复位/撤销复位MIPI&nbsp;RX | MipiCsiResetRx:复位MIPI&nbsp;RX。不同的s32WorkingViNum有不同的enSnsType<br/>MipiCsiUnresetRx:撤销复位MIPI&nbsp;RX | | 复位/撤销复位MIPI&nbsp;RX | MipiCsiResetRx:复位MIPI&nbsp;RX。不同的s32WorkingViNum有不同的enSnsType<br/>MipiCsiUnresetRx:撤销复位MIPI&nbsp;RX |
| 使能/关闭MIPI的时钟 | MipiCsiEnableClock:使能MIPI的时钟。根据上层函数电泳传递的enSnsType参数决定是用MIPI还是LVDS<br/>MipiCsiDisableClock:关闭MIPI设备的时钟 | | 使能/关闭MIPI的时钟 | MipiCsiEnableClock:使能MIPI的时钟。根据上层函数电泳传递的enSnsType参数决定是用MIPI还是LVDS<br/>MipiCsiDisableClock:关闭MIPI设备的时钟 |
...@@ -75,16 +60,16 @@ ...@@ -75,16 +60,16 @@
### 使用流程<a name="section2.1_MIPI_CSIDes"></a> ### 使用流程<a name="section2.1_MIPI_CSIDes"></a>
使用MIPI-CSI的一般流程如[图2](#fig2_MIPI_CSIDes)所示。 使用MIPI CSI的一般流程如图2所示。
**图 2** MIPI-CSI使用流程图<a name="fig2_MIPI_CSIDes"></a> **图 2** MIPI CSI使用流程图<a name="fig2_MIPI_CSIDes"></a>
![](figures/MIPI-CSI使用流程图.png) ![](figures/MIPI-CSI使用流程图.png)
### 获取MIPI-CSI控制器操作句柄<a name="section2.2_MIPI_CSIDes"></a> ### 获取MIPI CSI控制器操作句柄<a name="section2.2_MIPI_CSIDes"></a>
在进行MIPI-CSI进行通信前,首先要调用MipiCsiOpen获取控制器操作句柄,该函数会返回指定通道ID的控制器操作句柄。 在进行MIPI CSI进行通信前,首先要调用MipiCsiOpen获取控制器操作句柄,该函数会返回指定通道ID的控制器操作句柄。
```c ```c
DevHandle MipiCsiOpen(uint8_t id); DevHandle MipiCsiOpen(uint8_t id);
...@@ -101,11 +86,11 @@ DevHandle MipiCsiOpen(uint8_t id); ...@@ -101,11 +86,11 @@ DevHandle MipiCsiOpen(uint8_t id);
| NULL | 获取失败 | | NULL | 获取失败 |
| 设备句柄 | 获取到指令通道的控制器操作句柄,类型为DevHandle | | 设备句柄 | 获取到指令通道的控制器操作句柄,类型为DevHandle |
假设系统中的MIPI-CSI通道为0,获取该通道控制器操作句柄的示例如下: 假设系统中的MIPI CSI通道为0,获取该通道控制器操作句柄的示例如下:
```c ```c
DevHandle MipiCsiHandle = NULL; /* 设备句柄 */ DevHandle MipiCsiHandle = NULL; /* 设备句柄 */
id = 0; /* MiPi-Csi通道ID */ id = 0; /* MIPI CSI通道ID */
/* 获取控制器操作句柄 */ /* 获取控制器操作句柄 */
MipiCsiHandle = MipiCsiOpen(id); MipiCsiHandle = MipiCsiOpen(id);
...@@ -115,9 +100,9 @@ if (MipiCsiHandle == NULL) { ...@@ -115,9 +100,9 @@ if (MipiCsiHandle == NULL) {
} }
``` ```
### MIPI-CSI相应配置<a name="section2.3_MIPI_CSIDes"></a> ### MIPI CSI相应配置<a name="section2.3_MIPI_CSIDes"></a>
- 写入MIPI-CSI配置 - 写入MIPI CSI配置
```c ```c
int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr); int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr);
...@@ -130,7 +115,7 @@ if (MipiCsiHandle == NULL) { ...@@ -130,7 +115,7 @@ if (MipiCsiHandle == NULL) {
| 参数 | 参数描述 | | 参数 | 参数描述 |
| ---------- | -------------------------- | | ---------- | -------------------------- |
| handle | 控制器操作句柄 | | handle | 控制器操作句柄 |
| pAttr | MIPI-CSI相应配置结构体指针 | | pAttr | MIPI CSI相应配置结构体指针 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 设置成功 | | 0 | 设置成功 |
| 负数 | 设置失败 | | 负数 | 设置失败 |
...@@ -528,9 +513,9 @@ if (MipiCsiHandle == NULL) { ...@@ -528,9 +513,9 @@ if (MipiCsiHandle == NULL) {
} }
``` ```
### 释放MIPI-CSI控制器操作句柄<a name="section2.8_MIPI_CSIDes"></a> ### 释放MIPI CSI控制器操作句柄<a name="section2.8_MIPI_CSIDes"></a>
MIPI-CSI使用完成之后,需要释放控制器操作句柄,释放句柄的函数如下所示: MIPI CSI使用完成之后,需要释放控制器操作句柄,释放句柄的函数如下所示:
```c ```c
void MipiCsiClose(DevHandle handle); void MipiCsiClose(DevHandle handle);
...@@ -544,15 +529,15 @@ void MipiCsiClose(DevHandle handle); ...@@ -544,15 +529,15 @@ void MipiCsiClose(DevHandle handle);
| 参数 | 参数描述 | | 参数 | 参数描述 |
| ------------ | ------------------------------------------------ | | ------------ | ------------------------------------------------ |
| handle | MIPI-CSI控制器操作句柄 | | handle | MIPI CSI控制器操作句柄 |
```c ```c
MipiCsiClose(MIPIHandle); /* 释放掉MIPI-CSI控制器操作句柄 */ MipiCsiClose(MIPIHandle); /* 释放掉MIPI CSI控制器操作句柄 */
``` ```
## 使用实例<a name="section3_MIPI_CSIDes"></a> ## 使用实例<a name="section3_MIPI_CSIDes"></a>
MIPI-CSI完整的使用示例如下所示: MIPI CSI完整的使用示例如下所示:
```c ```c
#include "hdf.h" #include "hdf.h"
......
# MIPI-CSI<a name="title_MIPI_CSIDevelop"></a> # MIPI CSI
- [概述](#section1_MIPI_CSIDevelop)
- [接口说明](#section2_MIPI_CSIDevelop)
- [开发步骤](#section3_MIPI_CSIDevelop)
- [开发实例](#section4_MIPI_CSIDevelop)
## 概述 <a name="section1_MIPI_CSIDevelop"></a> ## 概述 <a name="section1_MIPI_CSIDevelop"></a>
CSI(Camera Serial Interface)是由MIPI(Mobile Industry Processor Interface )联盟下Camera工作组指定的接口标准。在HDF框架中,MIPI-CSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,MIPI-CSI的接口关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 CSI(Camera Serial Interface)是由MIPI(Mobile Industry Processor Interface )联盟下Camera工作组指定的接口标准。在HDF框架中,MIPI CSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,MIPI CSI的接口关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。
图 1 无服务模式结构图 图 1 无服务模式结构图
![image1](figures/无服务模式结构图.png) ![image1](figures/无服务模式结构图.png)
## 接口说明 <a name="section2_MIPI_CSIDevelop"></a> ## 接口说明 <a name="section2_MIPI_CSIDevelop"></a>
...@@ -35,7 +31,7 @@ struct MipiCsiCntlrMethod { ...@@ -35,7 +31,7 @@ struct MipiCsiCntlrMethod {
表1 MipiCsiCntlrMethod成员的回调函数功能说明 表1 MipiCsiCntlrMethod成员的回调函数功能说明
| 成员函数 | 入参 | 出参 | 返回状态 | 功能 | | 成员函数 | 入参 | 出参 | 返回状态 | 功能 |
| ------------------ | ------------------------------------------------------------ | ---- | ------------------ | -------------------------- | | ------------------ | ------------------------------------------------------------ | ---- | ------------------ | -------------------------- |
| setComboDevAttr | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**pAttr**:结构体指针,MIPI-CSI相应配置结构体指针 | 无 | HDF_STATUS相关状态 | 写入MIPI-CSI配置 | | setComboDevAttr | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**pAttr**:结构体指针,MIPI CSI相应配置结构体指针 | 无 | HDF_STATUS相关状态 | 写入MIPI CSI配置 |
| setPhyCmvmode | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**devno**:uint8_t,设备编号;<br>**cmvMode**:枚举类型,共模电压模式参数 | 无 | HDF_STATUS相关状态 | 设置共模电压模式 | | setPhyCmvmode | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**devno**:uint8_t,设备编号;<br>**cmvMode**:枚举类型,共模电压模式参数 | 无 | HDF_STATUS相关状态 | 设置共模电压模式 |
| setExtDataType | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**dataType**:结构体指针,定义YUV和原始数据格式以及位深度 | 无 | HDF_STATUS相关状态 | 设置YUV和RAW数据格式和位深 | | setExtDataType | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**dataType**:结构体指针,定义YUV和原始数据格式以及位深度 | 无 | HDF_STATUS相关状态 | 设置YUV和RAW数据格式和位深 |
| setHsMode | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**laneDivideMode**:枚举类型,lane模式参数 | 无 | HDF_STATUS相关状态 | 设置MIPI RX的Lane分布 | | setHsMode | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**laneDivideMode**:枚举类型,lane模式参数 | 无 | HDF_STATUS相关状态 | 设置MIPI RX的Lane分布 |
...@@ -50,7 +46,7 @@ struct MipiCsiCntlrMethod { ...@@ -50,7 +46,7 @@ struct MipiCsiCntlrMethod {
## 开发步骤 <a name="section3_MIPI_CSIDevelop"></a> ## 开发步骤 <a name="section3_MIPI_CSIDevelop"></a>
MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、以及实例化核心层接口函数。 MIPI CSI模块适配的三个环节是配置属性文件、实例化驱动入、以及实例化核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
...@@ -107,7 +103,7 @@ MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、 ...@@ -107,7 +103,7 @@ MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、
一般在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
- MIPI-CSI驱动入口参考 - MIPI CSI驱动入口参考
```c ```c
struct HdfDriverEntry g_mipiCsiDriverEntry = { struct HdfDriverEntry g_mipiCsiDriverEntry = {
...@@ -123,7 +119,7 @@ MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、 ...@@ -123,7 +119,7 @@ MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、
- 自定义结构体参考 - 自定义结构体参考
> 从驱动的角度看,自定义结构体是参数和数据的载体,一般来说,config文件中的数值也会用来初始化结构体成员,本例的mipicsi器件属性在源文件中,故基本成员结构与MipiCsiCntlr无太大差异。 从驱动的角度看,自定义结构体是参数和数据的载体,一般来说,config文件中的数值也会用来初始化结构体成员,本例的mipicsi器件属性在源文件中,故基本成员结构与MipiCsiCntlr无太大差异。
```c ```c
typedef struct { typedef struct {
...@@ -199,23 +195,25 @@ MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、 ...@@ -199,23 +195,25 @@ MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、
- **Init函数参考** - **Init函数参考**
> **入参:** **入参:**
> HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息
>
> **返回值:** **返回值:**
> HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)
>
> | 状态(值) | 问题描述 |
> | :--------------------- | :----------: | | 状态(值) | 问题描述 |
> | HDF_ERR_INVALID_OBJECT | 无效对象 | | :--------------------- | :----------: |
> | HDF_ERR_MALLOC_FAIL | 内存分配失败 | | HDF_ERR_INVALID_OBJECT | 无效对象 |
> | HDF_ERR_INVALID_PARAM | 无效参数 | | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
> | HDF_ERR_IO | I/O 错误 | | HDF_ERR_INVALID_PARAM | 无效参数 |
> | HDF_SUCCESS | 执行成功 | | HDF_ERR_IO | I/O 错误 |
> | HDF_FAILURE | 执行失败 | | HDF_SUCCESS | 执行成功 |
> | HDF_FAILURE | 执行失败 |
> **函数说明:**
> MipiCsiCntlrMethod的实例化对象的挂载,调用MipiCsiRegisterCntlr,以及其他厂商自定义初始化操作。 **函数说明:**
MipiCsiCntlrMethod的实例化对象的挂载,调用MipiCsiRegisterCntlr,以及其他厂商自定义初始化操作。
```c ```c
static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device) static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device)
...@@ -282,14 +280,14 @@ MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、 ...@@ -282,14 +280,14 @@ MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、
- **Release函数参考** - **Release函数参考**
> **入参:** **入参:**
> HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。
>
> **返回值:** **返回值:**
>
>
> **函数说明:** **函数说明:**
> 该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源,该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源,该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。
```c ```c
static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device) static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device)
......
# MIPI DSI<a name="ZH-CN_TOPIC_0000001160971534"></a> # MIPI DSI
- [概述](#section16806142183217)
- [接口说明](#section12720125432316)
- [使用指导](#section037231715335)
- [使用流程](#section49299119344)
- [获取MIPI-DSI操作句柄](#section5126155683811)
- [MIPI-DSI相应配置](#section201164274344)
- [发送/回读控制指令](#section199401342173415)
- [释放MIPI-DSI操作句柄](#section161011610357)
- [使用实例](#section17470126123520) ## 概述
## 概述<a name="section16806142183217"></a> - DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设(通常是LCD或者类似的显示设备),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。
- DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设\(通常是LCD或者类似的显示设备\),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议 - MIPI DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号
- MIPI-DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。
- 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。 - 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。
**图 1** DSI发送、接收接口<a name="fig1122611461203"></a> **图1** DSI发送、接收接口
![](figures/DSI发送-接收接口.png "DSI发送-接收接口")
![zh-cn_image_0000001243192721](figures/zh-cn_image_0000001243192721.png)
## 接口说明<a name="section12720125432316"></a>
## 接口说明
**表 1** MIPI-DSI API接口功能介绍
**表1** MIPI DSI API接口功能介绍
<a name="table4199102313245"></a>
<table><thead align="left"><tr id="row1619910238244"><th class="cellrowborder" valign="top" width="26.619999999999997%" id="mcps1.2.4.1.1"><p id="p141991023182411"><a name="p141991023182411"></a><a name="p141991023182411"></a>功能分类</p> | 功能分类 | 接口名 |
</th> | -------- | -------- |
<th class="cellrowborder" valign="top" width="28.910000000000004%" id="mcps1.2.4.1.2"><p id="p1199102315247"><a name="p1199102315247"></a><a name="p1199102315247"></a>接口名</p> | 设置/获取当前MIPI&nbsp;DSI相关配置 | -&nbsp;MipiDsiSetCfg:设置MIPI&nbsp;DSI相关配置<br/>-&nbsp;MipiDsiGetCfg:获取当前MIPI&nbsp;DSI相关配置 |
</th> | 获取/释放MIPI&nbsp;DSI操作句柄 | -&nbsp;MipiDsiOpen:获取MIPI&nbsp;DSI操作句柄<br/>-&nbsp;MipiDsiClose:释放MIPI&nbsp;DSI操作句柄 |
<th class="cellrowborder" valign="top" width="44.47%" id="mcps1.2.4.1.3"><p id="p719918232240"><a name="p719918232240"></a><a name="p719918232240"></a>描述</p> | 设置MIPI&nbsp;DSI进入Low&nbsp;power模式/High&nbsp;speed模式 | -&nbsp;MipiDsiSetLpMode:设置MIPI&nbsp;DSI进入Low&nbsp;power模式<br/>-&nbsp;MipiDsiSetHsMode:设置MIPI&nbsp;DSI进入High&nbsp;speed模式 |
</th> | MIPI&nbsp;DSI发送/回读指令 | -&nbsp;MipiDsiTx:MIPI&nbsp;DSI发送相应指令的接口<br/>-&nbsp;MipiDsiRx:MIPI&nbsp;DSI按期望长度回读的接口 |
</tr>
</thead> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
<tbody><tr id="row15199023172414"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p919902312413"><a name="p919902312413"></a><a name="p919902312413"></a>设置/获取当前MIPI-DSI相关配置</p> > 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
</td>
<td class="cellrowborder" valign="top" width="28.910000000000004%" headers="mcps1.2.4.1.2 "><p id="p21995232243"><a name="p21995232243"></a><a name="p21995232243"></a>MipiDsiSetCfg</p>
</td> ## 使用指导
<td class="cellrowborder" valign="top" width="44.47%" headers="mcps1.2.4.1.3 "><p id="p919911233240"><a name="p919911233240"></a><a name="p919911233240"></a>设置MIPI-DSI相关配置</p>
</td>
</tr> ### 使用流程
<tr id="row171996232248"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p7199623152412"><a name="p7199623152412"></a><a name="p7199623152412"></a>MipiDsiGetCfg</p>
</td> 使用MIPI DSI的一般流程如下图所示。
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1119919235248"><a name="p1119919235248"></a><a name="p1119919235248"></a>获取当前MIPI-DSI相关配置</p>
</td> **图2** MIPI DSI使用流程图
</tr>
<tr id="row91994239242"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p101998233245"><a name="p101998233245"></a><a name="p101998233245"></a>获取/释放MIPI-DSI操作句柄</p> ![zh-cn_image_0000001198152838](figures/zh-cn_image_0000001198152838.png)
</td>
<td class="cellrowborder" valign="top" width="28.910000000000004%" headers="mcps1.2.4.1.2 "><p id="p51991323112415"><a name="p51991323112415"></a><a name="p51991323112415"></a>MipiDsiOpen</p>
</td> ### 获取MIPI DSI操作句柄
<td class="cellrowborder" valign="top" width="44.47%" headers="mcps1.2.4.1.3 "><p id="p11991623182415"><a name="p11991623182415"></a><a name="p11991623182415"></a>获取MIPI-DSI操作句柄</p>
</td> 在进行MIPI DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。
</tr>
<tr id="row12199192352411"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p131991123172412"><a name="p131991123172412"></a><a name="p131991123172412"></a>MipiDsiClose</p>
</td> ```
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p520062313249"><a name="p520062313249"></a><a name="p520062313249"></a>释放MIPI-DSI操作句柄</p> DevHandle MipiDsiOpen(uint8_t id);
</td> ```
</tr>
<tr id="row7200152382417"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p8200202312241"><a name="p8200202312241"></a><a name="p8200202312241"></a>设置MIPI-DSI进入Low power模式/High speed模式</p> **表2** MipiDsiOpen的参数和返回值描述
</td>
<td class="cellrowborder" valign="top" width="28.910000000000004%" headers="mcps1.2.4.1.2 "><p id="p6200192318247"><a name="p6200192318247"></a><a name="p6200192318247"></a>MipiDsiSetLpMode</p> | **参数** | **参数描述** |
</td> | -------- | -------- |
<td class="cellrowborder" valign="top" width="44.47%" headers="mcps1.2.4.1.3 "><p id="p16200192319240"><a name="p16200192319240"></a><a name="p16200192319240"></a>设置MIPI-DSI进入Low power模式</p> | id | MIPI&nbsp;DSI通道ID |
</td> | **返回值** | **返回值描述** |
</tr> | NULL | 获取失败 |
<tr id="row122001523182417"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p22009236249"><a name="p22009236249"></a><a name="p22009236249"></a>MipiDsiSetHsMode</p> | 设备句柄 | 获取到指令通道的操作句柄,&nbsp;类型为DevHandle |
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p22001423192418"><a name="p22001423192418"></a><a name="p22001423192418"></a>设置MIPI-DSI进入High speed模式</p> 假设系统中的MIPI DSI通道为0,获取该通道操作句柄的示例如下:
</td>
</tr>
<tr id="row52002237248"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p10200162332412"><a name="p10200162332412"></a><a name="p10200162332412"></a>MIPI-DSI发送/回读指令</p>
</td>
<td class="cellrowborder" valign="top" width="28.910000000000004%" headers="mcps1.2.4.1.2 "><p id="p19200142315249"><a name="p19200142315249"></a><a name="p19200142315249"></a>MipiDsiTx</p>
</td>
<td class="cellrowborder" valign="top" width="44.47%" headers="mcps1.2.4.1.3 "><p id="p1020082319243"><a name="p1020082319243"></a><a name="p1020082319243"></a>MIPI-DSI发送相应指令的接口</p>
</td>
</tr>
<tr id="row6200162372416"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p18200112392417"><a name="p18200112392417"></a><a name="p18200112392417"></a>MipiDsiRx</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p9200102312249"><a name="p9200102312249"></a><a name="p9200102312249"></a>MIPI-DSI按期望长度回读的接口</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用
## 使用指导<a name="section037231715335"></a>
### 使用流程<a name="section49299119344"></a>
使用MIPI-DSI的一般流程如[图2](#fig129103491241)所示。
**图 2** MIPI-DSI使用流程图<a name="fig129103491241"></a>
![](figures/MIPI-DSI使用流程图.png)
### 获取MIPI-DSI操作句柄<a name="section5126155683811"></a>
在进行MIPI-DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。
DevHandle MipiDsiOpen\(uint8\_t id\);
**表 2** MipiDsiOpen的参数和返回值描述
<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="row960361918383"><td class="cellrowborder" valign="top" width="20.66%" headers="mcps1.2.3.1.1 "><p id="p8603161903818"><a name="p8603161903818"></a><a name="p8603161903818"></a>id</p>
</td>
<td class="cellrowborder" valign="top" width="79.34%" headers="mcps1.2.3.1.2 "><p id="p19603111916381"><a name="p19603111916381"></a><a name="p19603111916381"></a>MIPI DSI通道ID</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>获取失败</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>获取到指令通道的操作句柄, 类型为DevHandle</p>
</td>
</tr>
</tbody>
</table>
假设系统中的MIPI-DSI通道为0,获取该通道操作句柄的示例如下:
``` ```
DevHandle mipiDsiHandle = NULL; /* 设备句柄 */ DevHandle mipiDsiHandle = NULL; /* 设备句柄 */
chnId = 0; /* MIPI-DSI通道ID */ chnId = 0; /* MIPI DSI通道ID */
/* 获取操作句柄 */ /* 获取操作句柄 */
mipiDsiHandle = MipiDsiOpen(chnId); mipiDsiHandle = MipiDsiOpen(chnId);
...@@ -150,310 +74,204 @@ if (mipiDsiHandle == NULL) { ...@@ -150,310 +74,204 @@ if (mipiDsiHandle == NULL) {
} }
``` ```
### MIPI-DSI相应配置<a name="section201164274344"></a>
- 写入MIPI-DSI配置
int32\_t MipiDsiSetCfg\(DevHandle handle, struct MipiCfg \*cfg\);
**表 3** MipiDsiSetCfg的参数和返回值描述
<a name="table10692555281"></a>
<table><thead align="left"><tr id="row116914559288"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1169195516288"><a name="p1169195516288"></a><a name="p1169195516288"></a><strong id="b106965519281"><a name="b106965519281"></a><a name="b106965519281"></a>参数</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p769125512286"><a name="p769125512286"></a><a name="p769125512286"></a><strong id="b969105516280"><a name="b969105516280"></a><a name="b969105516280"></a>参数描述</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row4691155142812"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p66935515288"><a name="p66935515288"></a><a name="p66935515288"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p863714348217"><a name="p863714348217"></a><a name="p863714348217"></a>操作句柄</p>
</td>
</tr>
<tr id="row469145572817"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p46915519287"><a name="p46915519287"></a><a name="p46915519287"></a>cfg</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p76995518289"><a name="p76995518289"></a><a name="p76995518289"></a>MIPI-DSI相应配置buf 指针</p>
</td>
</tr>
<tr id="row16913554284"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16955512812"><a name="p16955512812"></a><a name="p16955512812"></a><strong id="b17691155152810"><a name="b17691155152810"></a><a name="b17691155152810"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p206945502813"><a name="p206945502813"></a><a name="p206945502813"></a><strong id="b196955572818"><a name="b196955572818"></a><a name="b196955572818"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row146914556283"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p669175582818"><a name="p669175582818"></a><a name="p669175582818"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p169205511283"><a name="p169205511283"></a><a name="p169205511283"></a>设置成功</p>
</td>
</tr>
<tr id="row5694558283"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p269175516286"><a name="p269175516286"></a><a name="p269175516286"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p11691554280"><a name="p11691554280"></a><a name="p11691554280"></a>设置失败</p>
</td>
</tr>
</tbody>
</table>
``` ### MIPI DSI相应配置
int32_t ret;
struct MipiCfg cfg = {0}; - 写入MIPI DSI配置
/* 当前对接的屏幕配置如下 */ ```
cfg.lane = DSI_4_LANES; int32_t MipiDsiSetCfg(DevHandle handle, struct MipiCfg *cfg);
cfg.mode = DSI_CMD_MODE; ```
cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS;
cfg.format = FORMAT_RGB_24_BIT; **表3** MipiDsiSetCfg的参数和返回值描述
cfg.pixelClk = 174;
cfg.phyDataRate = 384; | **参数** | **参数描述** |
cfg.timingInfo.hsaPixels = 50; | -------- | -------- |
cfg.timingInfo.hbpPixels = 55; | handle | 操作句柄 |
cfg.timingInfo.hlinePixels = 1200; | cfg | MIPI&nbsp;DSI相应配置buf&nbsp;指针 |
cfg.timingInfo.yResLines = 1800; | **返回值** | **返回值描述** |
cfg.timingInfo.vbpLines = 33; | 0 | 设置成功 |
cfg.timingInfo.vsaLines = 76; | 负数 | 设置失败 |
cfg.timingInfo.vfpLines = 120;
cfg.timingInfo.xResPixels = 1342;
/* 写入配置数据 */ ```
ret = MipiDsiSetCfg(mipiDsiHandle, &cfg); int32_t ret;
if (ret != 0) { struct MipiCfg cfg = {0};
/* 当前对接的屏幕配置如下 */
cfg.lane = DSI_4_LANES;
cfg.mode = DSI_CMD_MODE;
cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS;
cfg.format = FORMAT_RGB_24_BIT;
cfg.pixelClk = 174;
cfg.phyDataRate = 384;
cfg.timingInfo.hsaPixels = 50;
cfg.timingInfo.hbpPixels = 55;
cfg.timingInfo.hlinePixels = 1200;
cfg.timingInfo.yResLines = 1800;
cfg.timingInfo.vbpLines = 33;
cfg.timingInfo.vsaLines = 76;
cfg.timingInfo.vfpLines = 120;
cfg.timingInfo.xResPixels = 1342;
/* 写入配置数据 */
ret = MipiDsiSetCfg(mipiDsiHandle, &cfg);
if (ret != 0) {
HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret);
return -1; return -1;
} }
``` ```
- 获取当前MIPI-DSI的配置 - 获取当前MIPI DSI的配置
int32\_t MipiDsiGetCfg\(DevHandle handle, struct MipiCfg \*cfg\);
**表 4** MipiDsiGetCfg的参数和返回值描述
<a name="table7709554280"></a>
<table><thead align="left"><tr id="row670115515282"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p470205515287"><a name="p470205515287"></a><a name="p470205515287"></a><strong id="b1770105522820"><a name="b1770105522820"></a><a name="b1770105522820"></a>参数</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p270755162817"><a name="p270755162817"></a><a name="p270755162817"></a><strong id="b170165512817"><a name="b170165512817"></a><a name="b170165512817"></a>参数描述</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row57014555286"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p11701155172815"><a name="p11701155172815"></a><a name="p11701155172815"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p57015510283"><a name="p57015510283"></a><a name="p57015510283"></a>操作句柄</p>
</td>
</tr>
<tr id="row1870155192815"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p137115572815"><a name="p137115572815"></a><a name="p137115572815"></a>cfg</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p771195522818"><a name="p771195522818"></a><a name="p771195522818"></a>MIPI-DSI相应配置buf 指针</p>
</td>
</tr>
<tr id="row12718555283"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1871175515289"><a name="p1871175515289"></a><a name="p1871175515289"></a><strong id="b871185592819"><a name="b871185592819"></a><a name="b871185592819"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p771955182813"><a name="p771955182813"></a><a name="p771955182813"></a><strong id="b147175532813"><a name="b147175532813"></a><a name="b147175532813"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row1071155582812"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p6718551282"><a name="p6718551282"></a><a name="p6718551282"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p171195516285"><a name="p171195516285"></a><a name="p171195516285"></a>获取成功</p>
</td>
</tr>
<tr id="row97135519282"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p11711355162815"><a name="p11711355162815"></a><a name="p11711355162815"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p77116555286"><a name="p77116555286"></a><a name="p77116555286"></a>获取失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t MipiDsiGetCfg(DevHandle handle, struct MipiCfg *cfg);
struct MipiCfg cfg; ```
memset(&cfg, 0, sizeof(struct MipiCfg));
ret = MipiDsiGetCfg(mipiDsiHandle, &cfg); **表4** MipiDsiGetCfg的参数和返回值描述
if (ret != HDF_SUCCESS) {
| **参数** | **参数描述** |
| -------- | -------- |
| handle | 操作句柄 |
| cfg | MIPI&nbsp;DSI相应配置buf&nbsp;指针 |
| **返回值** | **返回值描述** |
| 0 | 获取成功 |
| 负数 | 获取失败 |
```
int32_t ret;
struct MipiCfg cfg;
memset(&cfg, 0, sizeof(struct MipiCfg));
ret = MipiDsiGetCfg(mipiDsiHandle, &cfg);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: GetMipiCfg fail!\n", __func__); HDF_LOGE("%s: GetMipiCfg fail!\n", __func__);
return HDF_FAILURE; return HDF_FAILURE;
} }
``` ```
### 发送/回读控制指令<a name="section199401342173415"></a> ### 发送/回读控制指令
- 发送指令 - 发送指令
int32\_t MipiDsiTx\(PalHandle handle, struct DsiCmdDesc \*cmd\); ```
int32_t MipiDsiTx(PalHandle handle, struct DsiCmdDesc *cmd);
**表 5** MipiDsiTx的参数和返回值描述 ```
<a name="table1018490043"></a>
<table><thead align="left"><tr id="row31848013417"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1415816132411"><a name="p1415816132411"></a><a name="p1415816132411"></a><strong id="b129796117337"><a name="b129796117337"></a><a name="b129796117337"></a>参数</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p11158111316410"><a name="p11158111316410"></a><a name="p11158111316410"></a><strong id="b1699118123314"><a name="b1699118123314"></a><a name="b1699118123314"></a>参数描述</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row10184701945"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p104891871157"><a name="p104891871157"></a><a name="p104891871157"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p204891671156"><a name="p204891671156"></a><a name="p204891671156"></a>操作句柄</p>
</td>
</tr>
<tr id="row928111518418"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p4282955412"><a name="p4282955412"></a><a name="p4282955412"></a>cmd</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p7282752412"><a name="p7282752412"></a><a name="p7282752412"></a>需要发送的指令数据指针</p>
</td>
</tr>
<tr id="row17393154515328"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8158313248"><a name="p8158313248"></a><a name="p8158313248"></a><strong id="b18542051332"><a name="b18542051332"></a><a name="b18542051332"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p161591413741"><a name="p161591413741"></a><a name="p161591413741"></a><strong id="b45520523313"><a name="b45520523313"></a><a name="b45520523313"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row339324593215"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p103191916578"><a name="p103191916578"></a><a name="p103191916578"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1231981611712"><a name="p1231981611712"></a><a name="p1231981611712"></a>发送成功</p>
</td>
</tr>
<tr id="row15393184519323"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p531916166716"><a name="p531916166716"></a><a name="p531916166716"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p93191161174"><a name="p93191161174"></a><a name="p93191161174"></a>发送失败</p>
</td>
</tr>
</tbody>
</table>
``` **表5** MipiDsiTx的参数和返回值描述
int32_t ret;
struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); | **参数** | **参数描述** |
if (cmd == NULL) { | -------- | -------- |
| handle | 操作句柄 |
| cmd | 需要发送的指令数据指针 |
| **返回值** | **返回值描述** |
| 0 | 发送成功 |
| 负数 | 发送失败 |
```
int32_t ret;
struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc));
if (cmd == NULL) {
return HDF_FAILURE; return HDF_FAILURE;
} }
cmd->dtype = DTYPE_DCS_WRITE; cmd->dtype = DTYPE_DCS_WRITE;
cmd->dlen = 1; cmd->dlen = 1;
cmd->payload = OsalMemCalloc(sizeof(uint8_t)); cmd->payload = OsalMemCalloc(sizeof(uint8_t));
if (cmd->payload == NULL) { if (cmd->payload == NULL) {
HdfFree(cmd); HdfFree(cmd);
return HDF_FAILURE; return HDF_FAILURE;
} }
*(cmd->payload) = DTYPE_GEN_LWRITE; *(cmd->payload) = DTYPE_GEN_LWRITE;
MipiDsiSetLpMode(mipiHandle); MipiDsiSetLpMode(mipiHandle);
ret = MipiDsiTx(mipiHandle, cmd); ret = MipiDsiTx(mipiHandle, cmd);
MipiDsiSetHsMode(mipiHandle); MipiDsiSetHsMode(mipiHandle);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: PalMipiDsiTx fail! ret=%d\n", __func__, ret); HDF_LOGE("%s: PalMipiDsiTx fail! ret=%d\n", __func__, ret);
HdfFree(cmd->payload); HdfFree(cmd->payload);
HdfFree(cmd); HdfFree(cmd);
return HDF_FAILURE; return HDF_FAILURE;
} }
HdfFree(cmd->payload); HdfFree(cmd->payload);
HdfFree(cmd); HdfFree(cmd);
``` ```
- 回读指令 - 回读指令
int32\_t MipiDsiRx\(DevHandle handle, struct DsiCmdDesc \*cmd, uint32\_t readLen, uint8\_t \*out\); ```
int32_t MipiDsiRx(DevHandle handle, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out);
**表 6** MipiDsiRx的参数和返回值描述 ```
<a name="table223910318361"></a>
<table><thead align="left"><tr id="row924033173613"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p16240143143611"><a name="p16240143143611"></a><a name="p16240143143611"></a><strong id="b1724033112363"><a name="b1724033112363"></a><a name="b1724033112363"></a>参数</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p32401031113610"><a name="p32401031113610"></a><a name="p32401031113610"></a><strong id="b1324013111363"><a name="b1324013111363"></a><a name="b1324013111363"></a>参数描述</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row024043193619"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16231153542520"><a name="p16231153542520"></a><a name="p16231153542520"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p122311535122518"><a name="p122311535122518"></a><a name="p122311535122518"></a>操作句柄</p>
</td>
</tr>
<tr id="row192401331163613"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8706172453614"><a name="p8706172453614"></a><a name="p8706172453614"></a>cmd</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p0706424183610"><a name="p0706424183610"></a><a name="p0706424183610"></a>需要回读的指令数据指针</p>
</td>
</tr>
<tr id="row12646535173616"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16465359364"><a name="p16465359364"></a><a name="p16465359364"></a>readLen</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p564617356360"><a name="p564617356360"></a><a name="p564617356360"></a>期望回读的数据长度</p>
</td>
</tr>
<tr id="row919916426361"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p11199942153616"><a name="p11199942153616"></a><a name="p11199942153616"></a>out</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p91991042143618"><a name="p91991042143618"></a><a name="p91991042143618"></a>回读的数据buf指针</p>
</td>
</tr>
<tr id="row14240133143619"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1723253542518"><a name="p1723253542518"></a><a name="p1723253542518"></a><strong id="b4232173517256"><a name="b4232173517256"></a><a name="b4232173517256"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p223217356253"><a name="p223217356253"></a><a name="p223217356253"></a><strong id="b7232103510259"><a name="b7232103510259"></a><a name="b7232103510259"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row424093120369"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1123203518257"><a name="p1123203518257"></a><a name="p1123203518257"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p62324353251"><a name="p62324353251"></a><a name="p62324353251"></a>获取成功</p>
</td>
</tr>
<tr id="row18241531153610"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p42321635122517"><a name="p42321635122517"></a><a name="p42321635122517"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p323283510252"><a name="p323283510252"></a><a name="p323283510252"></a>获取失败</p>
</td>
</tr>
</tbody>
</table>
``` **表6** MipiDsiRx的参数和返回值描述
int32_t ret;
uint8_t readVal = 0; | **参数** | **参数描述** |
| -------- | -------- |
| handle | 操作句柄 |
| cmd | 需要回读的指令数据指针 |
| readLen | 期望回读的数据长度 |
| out | 回读的数据buf指针 |
| **返回值** | **返回值描述** |
| 0 | 获取成功 |
| 负数 | 获取失败 |
```
int32_t ret;
uint8_t readVal = 0;
struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc));
if (cmdRead == NULL) { if (cmdRead == NULL) {
return HDF_FAILURE; return HDF_FAILURE;
} }
cmdRead->dtype = DTYPE_DCS_READ; cmdRead->dtype = DTYPE_DCS_READ;
cmdRead->dlen = 1; cmdRead->dlen = 1;
cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); cmdRead->payload = OsalMemCalloc(sizeof(uint8_t));
if (cmdRead->payload == NULL) { if (cmdRead->payload == NULL) {
HdfFree(cmdRead); HdfFree(cmdRead);
return HDF_FAILURE; return HDF_FAILURE;
} }
*(cmdRead->payload) = DDIC_REG_STATUS; *(cmdRead->payload) = DDIC_REG_STATUS;
MipiDsiSetLpMode(mipiDsiHandle); MipiDsiSetLpMode(mipiDsiHandle);
ret = MipiDsiRx(mipiDsiHandle, cmdRead, sizeof(readVal), &readVal); ret = MipiDsiRx(mipiDsiHandle, cmdRead, sizeof(readVal), &readVal);
MipiDsiSetHsMode(mipiDsiHandle); MipiDsiSetHsMode(mipiDsiHandle);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret);
HdfFree(cmdRead->payload); HdfFree(cmdRead->payload);
HdfFree(cmdRead); HdfFree(cmdRead);
return HDF_FAILURE; return HDF_FAILURE;
} }
HdfFree(cmdRead->payload); HdfFree(cmdRead->payload);
HdfFree(cmdRead); HdfFree(cmdRead);
``` ```
### 释放MIPI-DSI操作句柄<a name="section161011610357"></a>
MIPI-DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示: ### 释放MIPI DSI操作句柄
void MipiDsiClose\(DevHandle handle\); MIPI DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示:
```
void MipiDsiClose(DevHandle handle);
```
该函数会释放掉由MipiDsiOpen申请的资源。 该函数会释放掉由MipiDsiOpen申请的资源。
**表 7** MipiDsiClose的参数和返回值描述 **表7** MipiDsiClose的参数和返回值描述
<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> | handle | MIPI&nbsp;DSI操作句柄 |
<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="p132442255912"><a name="p132442255912"></a><a name="p132442255912"></a>MIPI-DSI操作句柄</p>
</td>
</tr>
</tbody>
</table>
``` ```
MipiDsiClose(mipiHandle); /* 释放掉MIPI-DSI操作句柄 */ MipiDsiClose(mipiHandle); /* 释放掉MIPI DSI操作句柄 */
``` ```
## 使用实例<a name="section17470126123520"></a>
MIPI-DSI完整的使用示例如下所示: ## 使用实例
MIPI DSI完整的使用示例如下所示:
``` ```
#include "hdf.h" #include "hdf.h"
...@@ -548,4 +366,3 @@ void PalMipiDsiTestSample(void) ...@@ -548,4 +366,3 @@ void PalMipiDsiTestSample(void)
MipiDsiClose(handle); MipiDsiClose(handle);
} }
``` ```
# MIPI-DSI<a name="ZH-CN_TOPIC_0000001222082237"></a> # MIPI DSI
- [概述](#section1266787503161538)
- [接口说明](#section752964871810)
- [开发步骤](#section545182932161538)
- [开发实例](#section1167576616161538)
## 概述<a name="section1266787503161538"></a> ## 概述
DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范。在HDF框架中,MIPI-DSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范。在HDF框架中,MIPI DSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。
**图 1** DSI无服务模式结构图<a name="fig207610236189"></a> **图1** DSI无服务模式结构图
![](figures/无服务模式结构图.png "DSI无服务模式结构图")
## 接口说明<a name="section752964871810"></a> ![zh-cn_image_0000001176603960](figures/zh-cn_image_0000001176603960.png)
## 接口说明
MipiDsiCntlrMethod定义: MipiDsiCntlrMethod定义:
``` ```
struct MipiDsiCntlrMethod { // 核心层结构体的成员函数 struct MipiDsiCntlrMethod { // 核心层结构体的成员函数
int32_t (*setCntlrCfg)(struct MipiDsiCntlr *cntlr); int32_t (*setCntlrCfg)(struct MipiDsiCntlr *cntlr);
...@@ -30,113 +29,48 @@ struct MipiDsiCntlrMethod { // 核心层结构体的成员函数 ...@@ -30,113 +29,48 @@ struct MipiDsiCntlrMethod { // 核心层结构体的成员函数
}; };
``` ```
**表 1** MipiDsiCntlrMethod成员的回调函数功能说明 **表1** MipiDsiCntlrMethod成员的回调函数功能说明
<a name="table49321701800"></a> | 成员函数 | 入参 | 出参 | 返回状态 | 功能 |
<table><thead align="left"><tr id="row129321407019"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p1793219014017"><a name="p1793219014017"></a><a name="p1793219014017"></a>成员函数</p> | -------- | -------- | -------- | -------- | -------- |
</th> | setCntlrCfg | cntlr:结构体指针,MipiDsi控制器&nbsp; | 无 | HDF_STATUS相关状态 | 设置控制器参数 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p11932130705"><a name="p11932130705"></a><a name="p11932130705"></a>入参</p> | setCmd | cntlr:结构体指针,MipiDsi控制器;<br>cmd:结构体指针,指令传入值; | 无 | HDF_STATUS相关状态 | 向显示设备发送指令 |
</th> | getCmd | cntlr:结构体指针,MipiDsi控制器;<br>cmd:传入的命令描述结构体指针;<br>readLen:读取的数据大小; | out:结构体指针,用于存储读取的数据。 | HDF_STATUS相关状态 | 通过发送指令读取数据 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p1493216019019"><a name="p1493216019019"></a><a name="p1493216019019"></a>出参</p> | toHs | cntlr:&nbsp;结构体指针,MipiDsi控制器&nbsp;; | 无 | HDF_STATUS相关状态 | 设置为高速模式 |
</th> | toLp | cntlr:&nbsp;结构体指针,MipiDsi控制器&nbsp;; | 无 | HDF_STATUS相关状态 | 设置为低电模式 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p12932400019"><a name="p12932400019"></a><a name="p12932400019"></a>返回状态</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p89322010019"><a name="p89322010019"></a><a name="p89322010019"></a>功能</p> ## 开发步骤
</th>
</tr> MIPI DSI模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。
</thead>
<tbody><tr id="row093219016016"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p9932209019"><a name="p9932209019"></a><a name="p9932209019"></a>setCntlrCfg</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p199321001705"><a name="p199321001705"></a><a name="p199321001705"></a>cntlr: 结构体指针,MipiDsi控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p093210106"><a name="p093210106"></a><a name="p093210106"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p16932701709"><a name="p16932701709"></a><a name="p16932701709"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p3932130702"><a name="p3932130702"></a><a name="p3932130702"></a>设置控制器参数</p>
</td>
</tr>
<tr id="row593211015010"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p169331101014"><a name="p169331101014"></a><a name="p169331101014"></a>setCmd</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p189338015011"><a name="p189338015011"></a><a name="p189338015011"></a>cntlr: 结构体指针,MipiDsi控制器 ;cmd: 结构体指针,指令传入值</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p493300204"><a name="p493300204"></a><a name="p493300204"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p49332011019"><a name="p49332011019"></a><a name="p49332011019"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p17933801808"><a name="p17933801808"></a><a name="p17933801808"></a>向显示设备发送指令</p>
</td>
</tr>
<tr id="row793312013010"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p13933120708"><a name="p13933120708"></a><a name="p13933120708"></a>getCmd</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p199331906010"><a name="p199331906010"></a><a name="p199331906010"></a>cntlr: 结构体指针,MipiDsi控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p139331001602"><a name="p139331001602"></a><a name="p139331001602"></a>cmd: 结构体指针,用于传出指令值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p993390900"><a name="p993390900"></a><a name="p993390900"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1933901007"><a name="p1933901007"></a><a name="p1933901007"></a>从显示设备读取信息指令</p>
</td>
</tr>
<tr id="row10933004013"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p493311019014"><a name="p493311019014"></a><a name="p493311019014"></a>toHs</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p189330016013"><a name="p189330016013"></a><a name="p189330016013"></a>cntlr: 结构体指针,MipiDsi控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p149338013010"><a name="p149338013010"></a><a name="p149338013010"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p2933309015"><a name="p2933309015"></a><a name="p2933309015"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p8933709019"><a name="p8933709019"></a><a name="p8933709019"></a>设置为高速模式</p>
</td>
</tr>
<tr id="row99331502001"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p993311018016"><a name="p993311018016"></a><a name="p993311018016"></a>toLp</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p79337011013"><a name="p79337011013"></a><a name="p79337011013"></a>cntlr: 结构体指针,MipiDsi控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p169331301201"><a name="p169331301201"></a><a name="p169331301201"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p39331407020"><a name="p39331407020"></a><a name="p39331407020"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p19933190507"><a name="p19933190507"></a><a name="p19933190507"></a>设置为低电模式</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section545182932161538"></a>
MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加mipidsi\_config.hcs器件属性文件。 - 【可选】添加mipidsi_config.hcs器件属性文件。
3. **实例化MIPIDSI控制器对象:** 3. **实例化MIPIDSI控制器对象:**
- 初始化MipiDsiCntlr成员。 - 初始化MipiDsiCntlr成员。
- 实例化MipiDsiCntlr成员MipiDsiCntlrMethod。 - 实例化MipiDsiCntlr成员MipiDsiCntlrMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化MipiDsiCntlr成员MipiDsiCntlrMethod,其定义和成员说明见[接口说明](#接口说明)。
>实例化MipiDsiCntlr成员MipiDsiCntlrMethod,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,数据传输的成功与否等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,数据传输的成功与否等。
## 开发实例<a name="section1167576616161538"></a> ## 开发实例
下方将以mipi\_tx\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以mipi_tx_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 一般来说,驱动开发首先需要在 xx\_config.hcs 中配置器件属性,并在device\_info.hcs文件中添加deviceNode描述。器件属性值与核心层MipiDsiCntlr 成员的默认值或限制范围有密切关系,deviceNode信息与驱动入口注册相关。 1. 一般来说,驱动开发首先需要在 xx_config.hcs 中配置器件属性,并在device_info.hcs文件中添加deviceNode描述。器件属性值与核心层MipiDsiCntlr 成员的默认值或限制范围有密切关系,deviceNode信息与驱动入口注册相关。
但本例中MIPI控制器无需配置额外属性,如有厂商需要,则需要在device\_info文件的deviceNode增加deviceMatchAttr信息,以及增加mipidsi\_config文件。 但本例中MIPI控制器无需配置额外属性,如有厂商需要,则需要在device_info文件的deviceNode增加deviceMatchAttr信息,以及增加mipidsi_config文件。
device\_info.hcs 配置参考: device_info.hcs 配置参考:
``` ```
root { root {
...@@ -159,11 +93,10 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口 ...@@ -159,11 +93,10 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口
} }
``` ```
2. 完成器件属性文件的配置之后,下一步请实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HdfDriverEntry结构体的函数指针成员会被厂商操作函数填充,HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组,方便调用。 2. 完成器件属性文件的配置之后,下一步请实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HdfDriverEntry结构体的函数指针成员会被厂商操作函数填充,HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组,方便调用。
一般在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
- MIPI-DSI驱动入口参考。 - MIPI DSI驱动入口参考。
``` ```
struct HdfDriverEntry g_mipiTxDriverEntry = { struct HdfDriverEntry g_mipiTxDriverEntry = {
...@@ -180,6 +113,7 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口 ...@@ -180,6 +113,7 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口
从驱动的角度看,自定义结构体是参数和数据的载体,一般来说,config文件中的数值也会用来初始化结构体成员,但本例的mipidsi无器件属性文件,故基本成员结构与MipiDsiCntlr无太大差异。 从驱动的角度看,自定义结构体是参数和数据的载体,一般来说,config文件中的数值也会用来初始化结构体成员,但本例的mipidsi无器件属性文件,故基本成员结构与MipiDsiCntlr无太大差异。
``` ```
typedef struct { typedef struct {
unsigned int devno; // 设备号 unsigned int devno; // 设备号
...@@ -203,9 +137,9 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口 ...@@ -203,9 +137,9 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口
void *priv; void *priv;
}; };
``` ```
- MipiDsiCntlr成员回调函数结构体MipiDsiCntlrMethod的实例化,其他成员在Init函数中初始化。 - MipiDsiCntlr成员回调函数结构体MipiDsiCntlrMethod的实例化,其他成员在Init函数中初始化。
``` ```
static struct MipiDsiCntlrMethod g_method = { static struct MipiDsiCntlrMethod g_method = {
.setCntlrCfg = Hi35xxSetCntlrCfg, .setCntlrCfg = Hi35xxSetCntlrCfg,
...@@ -215,7 +149,6 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口 ...@@ -215,7 +149,6 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口
.toLp = Hi35xxToLp, .toLp = Hi35xxToLp,
}; };
``` ```
- Init函数参考 - Init函数参考
入参: 入参:
...@@ -224,52 +157,23 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口 ...@@ -224,52 +157,23 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口
返回值: 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
<a name="table344041707161538"></a>
<table><thead align="left"><tr id="row1205250994161538"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1646623665161538p0"><a name="entry1646623665161538p0"></a><a name="entry1646623665161538p0"></a>状态(值)</p> | 状态(值) | 问题描述 |
</th> | -------- | -------- |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry36551796161538p0"><a name="entry36551796161538p0"></a><a name="entry36551796161538p0"></a>问题描述</p> | HDF_ERR_INVALID_OBJECT | 无效对象 |
</th> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</tr> | HDF_ERR_INVALID_PARAM | 无效参数 |
</thead> | HDF_ERR_IO | I/O&nbsp;错误 |
<tbody><tr id="row1245832689161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry635453137161538p0"><a name="entry635453137161538p0"></a><a name="entry635453137161538p0"></a>HDF_ERR_INVALID_OBJECT</p> | HDF_SUCCESS | 执行成功 |
</td> | HDF_FAILURE | 执行失败 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1681554112161538p0"><a name="entry1681554112161538p0"></a><a name="entry1681554112161538p0"></a>无效对象</p>
</td>
</tr>
<tr id="row86233502161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry2128705324161538p0"><a name="entry2128705324161538p0"></a><a name="entry2128705324161538p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1664050443161538p0"><a name="entry1664050443161538p0"></a><a name="entry1664050443161538p0"></a>内存分配失败</p>
</td>
</tr>
<tr id="row230078441161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry325107899161538p0"><a name="entry325107899161538p0"></a><a name="entry325107899161538p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry754791216161538p0"><a name="entry754791216161538p0"></a><a name="entry754791216161538p0"></a>无效参数</p>
</td>
</tr>
<tr id="row20758403161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1970333605161538p0"><a name="entry1970333605161538p0"></a><a name="entry1970333605161538p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1122658595161538p0"><a name="entry1122658595161538p0"></a><a name="entry1122658595161538p0"></a>I/O 错误</p>
</td>
</tr>
<tr id="row1425117417161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1844298129161538p0"><a name="entry1844298129161538p0"></a><a name="entry1844298129161538p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry712326009161538p0"><a name="entry712326009161538p0"></a><a name="entry712326009161538p0"></a>执行成功</p>
</td>
</tr>
<tr id="row1899574933161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1964112434161538p0"><a name="entry1964112434161538p0"></a><a name="entry1964112434161538p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1481231483161538p0"><a name="entry1481231483161538p0"></a><a name="entry1481231483161538p0"></a>执行失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
MipiDsiCntlrMethod的实例化对象的挂载,调用MipiDsiRegisterCntlr,以及其他厂商自定义初始化操作。 MipiDsiCntlrMethod的实例化对象的挂载,调用MipiDsiRegisterCntlr,以及其他厂商自定义初始化操作。
``` ```
static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device) static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device)
{ {
...@@ -305,7 +209,6 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口 ...@@ -305,7 +209,6 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口
return HDF_FAILURE; return HDF_FAILURE;
} }
``` ```
- Release函数参考 - Release函数参考
入参: 入参:
...@@ -320,6 +223,7 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口 ...@@ -320,6 +223,7 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口
该函数需要在驱动入口结构体中赋值给 Release 接口, 当 HDF 框架调用 Init 函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。 该函数需要在驱动入口结构体中赋值给 Release 接口, 当 HDF 框架调用 Init 函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。
``` ```
static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device) static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device)
{ {
...@@ -334,6 +238,3 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口 ...@@ -334,6 +238,3 @@ MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口
HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__); HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__);
} }
``` ```
# MMC<a name="ZH-CN_TOPIC_0000001222282171"></a> # MMC
- [概述](#section1846388309162704)
- [接口说明](#section752964871810)
- [开发步骤](#section1617495117162704)
- [开发实例](#section1220893490162704)
## 概述<a name="section1846388309162704"></a> ## 概述
MMC(MultiMedia Card),即多媒体卡,在HDF框架中,MMC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 MMC(MultiMedia Card),即多媒体卡,在HDF框架中,MMC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
**图 1** MMC独立服务模式结构图<a name="fig19517114132810"></a> **图1** MMC独立服务模式结构图
![](figures/独立服务模式结构图.png "MMC独立服务模式结构图") ![zh-cn_image_0000001176603968](figures/zh-cn_image_0000001176603968.png)
## 接口说明<a name="section752964871810"></a>
## 接口说明
MmcCntlrOps定义: MmcCntlrOps定义:
``` ```
struct MmcCntlrOps { struct MmcCntlrOps {
int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd); int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
...@@ -36,187 +34,54 @@ struct MmcCntlrOps { ...@@ -36,187 +34,54 @@ struct MmcCntlrOps {
}; };
``` ```
**表 1** MmcCntlrOps结构体成员的回调函数功能说明 **表1** MmcCntlrOps结构体成员的回调函数功能说明
<a name="table99129433019"></a> | 成员函数 | 入参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row1891214163012"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p79129483017"><a name="p79129483017"></a><a name="p79129483017"></a>成员函数</p> | -------- | -------- | -------- | -------- |
</th> | doRequest | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;;cmd:&nbsp;结构体指针,传入命令值 | HDF_STATUS相关状态 | request相应处理 |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p1591213403019"><a name="p1591213403019"></a><a name="p1591213403019"></a>入参</p> | setClock | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;;clock:&nbsp;时钟传入值 | HDF_STATUS相关状态 | 设置时钟频率 |
</th> | setPowerMode | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;;mode:&nbsp;枚举值(见MmcPowerMode定义),功耗模式 | HDF_STATUS相关状态 | 设置功耗模式 |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p491312483012"><a name="p491312483012"></a><a name="p491312483012"></a>返回值</p> | setBusWidth | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;;width:&nbsp;枚举值(见MmcBusWidth定义),总线带宽 | HDF_STATUS相关状态 | 设置总线带宽 |
</th> | setBusTiming | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;;timing:&nbsp;枚举值(见MmcBusTiming定义),总线时序 | HDF_STATUS相关状态 | 设置总线时序 |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p8913144203017"><a name="p8913144203017"></a><a name="p8913144203017"></a>功能</p> | setSdioIrq | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;;enable:&nbsp;布尔值,控制中断 | HDF_STATUS相关状态 | 使能/去使能SDIO中断 |
</th> | hardwareReset | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;; | HDF_STATUS相关状态 | 复位硬件 |
</tr> | systemInit | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;; | HDF_STATUS相关状态 | 系统初始化 |
</thead> | setEnhanceSrobe | cntlr:&nbsp;核心层结构体指针,mmc控制器&nbsp;;enable:&nbsp;布尔值,设置功能 | HDF_STATUS相关状态 | 设置增强选通 |
<tbody><tr id="row4913844307"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p17913149309"><a name="p17913149309"></a><a name="p17913149309"></a>doRequest</p> | switchVoltage | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;;volt:&nbsp;枚举值,电压值(3.3,1.8,1.2V); | HDF_STATUS相关状态 | 设置电压值 |
</td> | devReadOnly | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;; | 布尔值 | 检验设备是否只读 |
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p159131449308"><a name="p159131449308"></a><a name="p159131449308"></a>cntlr: 核心层结构体指针;mmc控制器 ;cmd: 结构体指针,传入命令值</p> | cardPluged | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;; | 布尔值 | 检验设备是否拔出 |
</td> | devBusy | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;; | 布尔值 | 检验设备是否忙碌 |
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1291519413308"><a name="p1291519413308"></a><a name="p1291519413308"></a>HDF_STATUS相关状态</p> | tune | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;;cmdCode:&nbsp;uint32_t,命令代码; | HDF_STATUS相关状态 | 调谐 |
</td> | rescanSdioDev | cntlr:&nbsp;核心层结构体指针;mmc控制器&nbsp;; | HDF_STATUS相关状态 | 扫描并添加SDIO设备 |
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p3915048309"><a name="p3915048309"></a><a name="p3915048309"></a>request相应处理</p>
</td>
</tr> ## 开发步骤
<tr id="row17915124113014"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p69152416307"><a name="p69152416307"></a><a name="p69152416307"></a>setClock</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p119153413013"><a name="p119153413013"></a><a name="p119153413013"></a>cntlr: 核心层结构体指针;mmc控制器 ;clock: 时钟传入值</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p79153417302"><a name="p79153417302"></a><a name="p79153417302"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1291614183010"><a name="p1291614183010"></a><a name="p1291614183010"></a>设置时钟频率</p>
</td>
</tr>
<tr id="row19168433011"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1391614416305"><a name="p1391614416305"></a><a name="p1391614416305"></a>setPowerMode</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p99161341305"><a name="p99161341305"></a><a name="p99161341305"></a>cntlr: 核心层结构体指针;mmc控制器 ;mode: 枚举值(见MmcPowerMode定义),功耗模式</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1091674183020"><a name="p1091674183020"></a><a name="p1091674183020"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1191617420307"><a name="p1191617420307"></a><a name="p1191617420307"></a>设置功耗模式</p>
</td>
</tr>
<tr id="row291620463018"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p291612453018"><a name="p291612453018"></a><a name="p291612453018"></a>setBusWidth</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p11916245309"><a name="p11916245309"></a><a name="p11916245309"></a>cntlr: 核心层结构体指针;mmc控制器 ;width: 枚举值(见MmcBusWidth定义),总线带宽</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1491610415305"><a name="p1491610415305"></a><a name="p1491610415305"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p19916147304"><a name="p19916147304"></a><a name="p19916147304"></a>设置总线带宽</p>
</td>
</tr>
<tr id="row1916742301"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p3916104143014"><a name="p3916104143014"></a><a name="p3916104143014"></a>setBusTiming</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p591710419302"><a name="p591710419302"></a><a name="p591710419302"></a>cntlr: 核心层结构体指针;mmc控制器 ;timing: 枚举值(见MmcBusTiming定义),总线时序</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p14917154123017"><a name="p14917154123017"></a><a name="p14917154123017"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1991814443016"><a name="p1991814443016"></a><a name="p1991814443016"></a>设置总线时序</p>
</td>
</tr>
<tr id="row199186423012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p991810414305"><a name="p991810414305"></a><a name="p991810414305"></a>setSdioIrq</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p16918844305"><a name="p16918844305"></a><a name="p16918844305"></a>cntlr: 核心层结构体指针;mmc控制器 ;enable: 布尔值,控制中断</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p17918204193011"><a name="p17918204193011"></a><a name="p17918204193011"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1191813416305"><a name="p1191813416305"></a><a name="p1191813416305"></a>使能/去使能SDIO中断</p>
</td>
</tr>
<tr id="row139181453012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p491874193011"><a name="p491874193011"></a><a name="p491874193011"></a>hardwareReset</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p12918114163011"><a name="p12918114163011"></a><a name="p12918114163011"></a>cntlr: 核心层结构体指针;mmc控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p4918244309"><a name="p4918244309"></a><a name="p4918244309"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p11919243306"><a name="p11919243306"></a><a name="p11919243306"></a>复位硬件</p>
</td>
</tr>
<tr id="row169195410309"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p89191746303"><a name="p89191746303"></a><a name="p89191746303"></a>systemInit</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p8919441302"><a name="p8919441302"></a><a name="p8919441302"></a>cntlr: 核心层结构体指针;mmc控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p199191941307"><a name="p199191941307"></a><a name="p199191941307"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p391919473014"><a name="p391919473014"></a><a name="p391919473014"></a>系统初始化</p>
</td>
</tr>
<tr id="row159191423012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p189194417307"><a name="p189194417307"></a><a name="p189194417307"></a>setEnhanceSrobe</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1191910419304"><a name="p1191910419304"></a><a name="p1191910419304"></a>cntlr: 核心层结构体指针,mmc控制器 ;enable: 布尔值,设置功能</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p69194473011"><a name="p69194473011"></a><a name="p69194473011"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p091904143019"><a name="p091904143019"></a><a name="p091904143019"></a>设置增强选通</p>
</td>
</tr>
<tr id="row109197416305"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p791917443010"><a name="p791917443010"></a><a name="p791917443010"></a>switchVoltage</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1591912415304"><a name="p1591912415304"></a><a name="p1591912415304"></a>cntlr: 核心层结构体指针;mmc控制器 ;volt: 枚举值,电压值(3.3,1.8,1.2V);</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p59196416307"><a name="p59196416307"></a><a name="p59196416307"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p169207416301"><a name="p169207416301"></a><a name="p169207416301"></a>设置电压值</p>
</td>
</tr>
<tr id="row1992015417301"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1892014463010"><a name="p1892014463010"></a><a name="p1892014463010"></a>devReadOnly</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1392011411309"><a name="p1392011411309"></a><a name="p1392011411309"></a>cntlr: 核心层结构体指针;mmc控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p89207418304"><a name="p89207418304"></a><a name="p89207418304"></a>布尔值</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p7920847301"><a name="p7920847301"></a><a name="p7920847301"></a>检验设备是否只读</p>
</td>
</tr>
<tr id="row1092019483018"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1092034103011"><a name="p1092034103011"></a><a name="p1092034103011"></a>cardPluged</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p2920144123010"><a name="p2920144123010"></a><a name="p2920144123010"></a>cntlr: 核心层结构体指针;mmc控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p2092014411305"><a name="p2092014411305"></a><a name="p2092014411305"></a>布尔值</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1892094153017"><a name="p1892094153017"></a><a name="p1892094153017"></a>检验设备是否拔出</p>
</td>
</tr>
<tr id="row892018413013"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p39201146309"><a name="p39201146309"></a><a name="p39201146309"></a>devBusy</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p9920124193013"><a name="p9920124193013"></a><a name="p9920124193013"></a>cntlr: 核心层结构体指针;mmc控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1992112419305"><a name="p1992112419305"></a><a name="p1992112419305"></a>布尔值</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p69211417302"><a name="p69211417302"></a><a name="p69211417302"></a>检验设备是否忙碌</p>
</td>
</tr>
<tr id="row71064053613"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1511114015361"><a name="p1511114015361"></a><a name="p1511114015361"></a>tune</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p5116409364"><a name="p5116409364"></a><a name="p5116409364"></a>cntlr: 核心层结构体指针;mmc控制器 ;cmdCode: uint32_t,命令代码;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p711440123610"><a name="p711440123610"></a><a name="p711440123610"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1411184011368"><a name="p1411184011368"></a><a name="p1411184011368"></a>调谐</p>
</td>
</tr>
<tr id="row1559214410366"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1559364493618"><a name="p1559364493618"></a><a name="p1559364493618"></a>rescanSdioDev</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p165931944133618"><a name="p165931944133618"></a><a name="p165931944133618"></a>cntlr: 核心层结构体指针;mmc控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p15593184493610"><a name="p15593184493610"></a><a name="p15593184493610"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p359384473615"><a name="p359384473615"></a><a name="p359384473615"></a>扫描并添加SDIO设备</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section1617495117162704"></a>
MMC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 MMC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加mmc\_config.hcs器件属性文件。 - 【可选】添加mmc_config.hcs器件属性文件。
3. **实例化MMC控制器对象:** 3. **实例化MMC控制器对象:**
- 初始化MmcCntlr成员。 - 初始化MmcCntlr成员。
- 实例化MmcCntlr成员MmcCntlrOps。 - 实例化MmcCntlr成员MmcCntlrOps。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化MmcCntlr成员MmcCntlrOps,其定义和成员说明见[接口说明](#接口说明)。
>实例化MmcCntlr成员MmcCntlrOps,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,设备启动是否成功等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,设备启动是否成功等。
## 开发实例<a name="section1220893490162704"></a> ## 开发实例
下方将以himci.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以himci.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
...@@ -233,11 +98,10 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -233,11 +98,10 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
HDF_INIT(g_mmcDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 HDF_INIT(g_mmcDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在mmc\_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层MmcCntlr成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在mmc_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层MmcCntlr成员的默认值或限制范围有密切关系。
如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在mmc_config文件中增加对应的器件属性**。**
- device_info.hcs 配置参考。
如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在mmc\_config文件中增加对应的器件属性**。**
- device\_info.hcs 配置参考。
``` ```
root { root {
...@@ -277,7 +141,8 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -277,7 +141,8 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
} }
``` ```
- mmc\_config.hcs 配置参考。 - mmc_config.hcs 配置参考。
``` ```
root { root {
...@@ -333,7 +198,8 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -333,7 +198,8 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
3. 完成驱动入口注册之后,最后一步就是以核心层MmcCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化MmcCntlr成员MmcCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层MmcCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化MmcCntlr成员MmcCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考。 - 自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且mmc\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员 ,一些重要数值也会传递给核心层对象。 从驱动的角度看,自定义结构体是参数和数据的载体,而且mmc_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员 ,一些重要数值也会传递给核心层对象。
``` ```
struct HimciHost { struct HimciHost {
...@@ -387,6 +253,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -387,6 +253,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
- MmcCntlr成员回调函数结构体MmcCntlrOps的实例化,其他成员在Bind函数中初始化。 - MmcCntlr成员回调函数结构体MmcCntlrOps的实例化,其他成员在Bind函数中初始化。
``` ```
static struct MmcCntlrOps g_himciHostOps = { static struct MmcCntlrOps g_himciHostOps = {
.request = HimciDoRequest, .request = HimciDoRequest,
...@@ -406,7 +273,6 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -406,7 +273,6 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
.rescanSdioDev = HimciRescanSdioDev, .rescanSdioDev = HimciRescanSdioDev,
}; };
``` ```
- Bind函数参考 - Bind函数参考
入参**:** 入参**:**
...@@ -415,52 +281,22 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -415,52 +281,22 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
返回值: 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
<a name="table1428218958162704"></a> | 状态(值) | 问题描述 |
<table><thead align="left"><tr id="row1723943104162704"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry136979408162704p0"><a name="entry136979408162704p0"></a><a name="entry136979408162704p0"></a>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry1590766658162704p0"><a name="entry1590766658162704p0"></a><a name="entry1590766658162704p0"></a>问题描述</p> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</th> | HDF_ERR_INVALID_PARAM | 参数非法 |
</tr> | HDF_ERR_IO | I/O&nbsp;错误 |
</thead> | HDF_SUCCESS | 初始化成功 |
<tbody><tr id="row408410040162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1337150412162704p0"><a name="entry1337150412162704p0"></a><a name="entry1337150412162704p0"></a>HDF_ERR_INVALID_OBJECT</p> | HDF_FAILURE | 初始化失败 |
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2061632106162704p0"><a name="entry2061632106162704p0"></a><a name="entry2061632106162704p0"></a>控制器对象非法</p>
</td>
</tr>
<tr id="row160841211162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1173668571162704p0"><a name="entry1173668571162704p0"></a><a name="entry1173668571162704p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry74350097162704p0"><a name="entry74350097162704p0"></a><a name="entry74350097162704p0"></a>内存分配失败</p>
</td>
</tr>
<tr id="row1596857798162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry190784255162704p0"><a name="entry190784255162704p0"></a><a name="entry190784255162704p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1070501269162704p0"><a name="entry1070501269162704p0"></a><a name="entry1070501269162704p0"></a>参数非法</p>
</td>
</tr>
<tr id="row1645995958162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry741922133162704p0"><a name="entry741922133162704p0"></a><a name="entry741922133162704p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2094504256162704p0"><a name="entry2094504256162704p0"></a><a name="entry2094504256162704p0"></a>I/O 错误</p>
</td>
</tr>
<tr id="row733220922162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1177794681162704p0"><a name="entry1177794681162704p0"></a><a name="entry1177794681162704p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry540896959162704p0"><a name="entry540896959162704p0"></a><a name="entry540896959162704p0"></a>初始化成功</p>
</td>
</tr>
<tr id="row1890064939162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry118676812162704p0"><a name="entry118676812162704p0"></a><a name="entry118676812162704p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2078272728162704p0"><a name="entry2078272728162704p0"></a><a name="entry2078272728162704p0"></a>初始化失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
MmcCntlr,HimciHost,HdfDeviceObject之间互相赋值,方便其他函数可以相互转化,初始化自定义结构体HimciHost对象,初始化MmcCntlr成员,调用核心层MmcCntlrAdd函数。 MmcCntlr,HimciHost,HdfDeviceObject之间互相赋值,方便其他函数可以相互转化,初始化自定义结构体HimciHost对象,初始化MmcCntlr成员,调用核心层MmcCntlrAdd函数。
``` ```
static int32_t HimciMmcBind(struct HdfDeviceObject *obj) static int32_t HimciMmcBind(struct HdfDeviceObject *obj)
{ {
...@@ -501,12 +337,13 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -501,12 +337,13 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
返回值: 返回值:
HDF\_STATUS相关状态。 HDF_STATUS相关状态。
函数说明: 函数说明:
实现ProcMciInit。 实现ProcMciInit。
``` ```
static int32_t HimciMmcInit(struct HdfDeviceObject *obj) static int32_t HimciMmcInit(struct HdfDeviceObject *obj)
{ {
...@@ -522,7 +359,6 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -522,7 +359,6 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
- Release函数参考 - Release函数参考
入参: 入参:
...@@ -537,6 +373,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -537,6 +373,7 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
释放内存和删除控制器等操作,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用 Release释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 释放内存和删除控制器等操作,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用 Release释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。
``` ```
static void HimciMmcRelease(struct HdfDeviceObject *obj) static void HimciMmcRelease(struct HdfDeviceObject *obj)
{ {
...@@ -547,6 +384,3 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口, ...@@ -547,6 +384,3 @@ MMC模块适配的三个环节是配置属性文件,实例化驱动入口,
HimciDeleteHost((struct HimciHost *)cntlr->priv);//厂商自定义的内存释放函数,这里有MmcCntlr到HimciHost的强制转化 HimciDeleteHost((struct HimciHost *)cntlr->priv);//厂商自定义的内存释放函数,这里有MmcCntlr到HimciHost的强制转化
} }
``` ```
# PWM<a name="title_PWM_des"></a> # PWM
- [概述](#section1_PWM_des)
- [PwmConfig结构体](#section1.1_PWM_des)
- [接口说明](#section2_PWM_des)
- [使用指导](#section3_PWM_des)
- [使用流程](#section3.1_PWM_des)
- [获取PWM设备句柄](#section3.2_PWM_des)
- [销毁PWM设备句柄](#section3.3_PWM_des)
- [使能](#section3.4_PWM_des)
- [禁用](#section3.5_PWM_des)
- [设置PWM设备周期](#section3.6_PWM_des)
- [设置PWM设备占空时间](#section3.7_PWM_des)
- [设置PWM设备极性](#section3.8_PWM_des)
- [设置PWM设备参数](#section3.9_PWM_des)
- [获取PWM设备参数](#section3.10_PWM_des)
- [使用实例](#section3_PWM_des) ## 概述
## 概述<a name="section1_PWM_des"></a> PWM是脉冲宽度调制(Pulse Width Modulation)的缩写,是一种对模拟信号电平进行数字编码并将其转换为脉冲的技术。常用于马达控制、背光亮度调节等。
- PWM是脉冲宽度调制(Pulse Width Modulation)的缩写,是一种对模拟信号电平进行数字编码,转换为脉冲的一种技术。常用于马达控制、背光亮度调节等。 PWM接口定义了操作PWM设备的通用方法集合,包括:
- PWM设备句柄获取和释放。
- PWM接口定义了操作PWM设备的通用方法集合,包括: - PWM周期、占空比、极性的设置。
- PWM设备句柄获取和销毁。
- PWM周期、占空比、极性的设置。
- PWM使能和关闭。
- PWM配置信息的获取和设置
### PwmConfig结构体<a name="section1.1_PWM_des"></a> - PWM使能和关闭。
**表1** PwmConfig结构体介绍 - PWM配置信息的获取和设置。
<a name="table1_PWM_des"></a>
### PwmConfig结构体
**表1** PwmConfig结构体介绍
| 名称 | 描述 | | 名称 | 描述 |
| -------- | ------------------------------------------------------------ | | -------- | -------- |
| duty | 占空时间,以纳秒为单位 | | duty | 占空时间,以纳秒为单位。 |
| period | PWM周期,以纳秒为单位 | | period | PWM周期,以纳秒为单位。 |
| number | 要生成的方波数。正值表示将生成指定数量的方波,<b>0</b>表示方波将不断产生 | | number | 要生成的方波数。<br/>-&nbsp;正值:表示将生成指定数量的方波,<br/>-&nbsp;0:表示方波将不断产生。 |
| polarity | 极性:正极性/反极性 | | polarity | 极性:正极性/反极性。 |
| status | 状态:启用状态/禁用状态 | | status | 状态:启用状态/禁用状态。 |
## 接口说明<a name="section2_PWM_des"></a>
## 接口说明
**表2** PWM设备API接口功能介绍
**表2** PWM驱动API接口功能介绍
<a name="table2_PWM_des"></a>
| 功能分类 | 接口描述 |
<table border="0" cellpadding="0" cellspacing="0" width="800" style="border-collapse: | -------- | -------- |
collapse;table-layout:fixed;width:700pt"> | PWM句柄操作 | -&nbsp;PwmOpen:获取PWM设备驱动句柄<br/>-&nbsp;PwmClose:释放PWM设备驱动句柄 |
<tbody><tr height="19" style="height:14.25pt"> | 使能/禁用PWM | -&nbsp;PwmEnable:使能PWM<br/>-&nbsp;PwmDisable:禁用PWM |
<td height="19" class="xl66" width="300" style="height:14.25pt;width:300pt">功能分类</td> | PWM配置操作 | -&nbsp;PwmSetPeriod:设置PWM周期<br/>-&nbsp;PwmSetDuty:设置PWM占空时间<br/>-&nbsp;PwmSetPolarity:设置PWM极性 |
<td class="xl67" width="250" style="width:250pt">接口名</td> | 设置/获取PWM配置信息 | -&nbsp;PwmSetConfig:设置PWM设备参数<br/>-&nbsp;PwmGetConfig:获取PWM设备参数 |
<td class="xl67" width="300" style="width:300pt">描述</td>
</tr> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
<tr height="19" style="height:14.25pt"> > 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">PWM句柄操作</td>
<td>PwmOpen</td>
<td>获取PWM设备驱动句柄</td> ## 使用指导
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmClose</td> ### 使用流程
<td>释放PWM设备驱动句柄</td>
</tr> 使用PWM的一般流程如下图所示。
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">使能/禁用PWM</td> **图1** PWM使用流程图
<td>PwmEnable</td>
<td>使能PWM</td> ![zh-cn_image_0000001206372673](figures/zh-cn_image_0000001206372673.png)
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmDisable</td> ### 获取PWM设备句柄
<td>禁用PWM</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="3" height="57" class="xl65" style="height:42.75pt">PWM配置操作</td>
<td>PwmSetPeriod</td>
<td>设置PWM周期</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmSetDuty</td>
<td>设置PWM占空时间</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmSetPolarity</td>
<td>设置PWM极性</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">设置/获取PWM配置信息</td>
<td>PwmSetConfig</td>
<td>设置PWM设备参数</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmGetConfig</td>
<td>获取PWM设备参数</td>
</tr>
</tbody></table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>PWM当前仅限内核态使用,不支持在用户态使用。
## 使用指导<a name="section3_PWM_des"></a>
### 使用流程<a name="section3.1_PWM_des"></a>
在操作系统启动过程中,驱动管理模块根据配置文件加载PWM驱动,PWM驱动会检测PWM器件并初始化驱动。
使用PWM设备的一般流程如[图1](#fig1_PWM_des)所示。
**图 1** PWM设备使用流程图<a name="fig1_PWM_des"></a>
![](figures/PWM设备使用流程图.png)
### 获取PWM设备句柄<a name="section3.2_PWM_des"></a>
在操作PWM设备时,首先要调用PwmOpen获取PWM设备句柄,该函数会返回指定设备号的PWM设备句柄。 在操作PWM设备时,首先要调用PwmOpen获取PWM设备句柄,该函数会返回指定设备号的PWM设备句柄。
```c
```
DevHandle PwmOpen(uint32_t num); DevHandle PwmOpen(uint32_t num);
``` ```
**表3** PwmOpen参数和返回值描述 **表3** PwmOpen参数和返回值描述
<a name="table3_PWM_des"></a> | **参数** | **参数描述** |
| -------- | -------- |
| 参数 | 参数描述 |
| ---------- | ----------------------- |
| num | PWM设备编号 | | num | PWM设备编号 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| handle | 获取成功返回PWM设备句柄 | | handle | 获取成功返回PWM设备句柄 |
| NULL | 获取失败 | | NULL | 获取失败 |
假设系统中的PWM设备号为0,获取该PWM设备句柄的示例如下:
```c ```
uint32_t num = 0; /* PWM设备号 */ uint32_t num = 0; /* PWM设备号 */
DevHandle handle = NULL; DevHandle handle = NULL;
...@@ -145,48 +87,49 @@ if (handle == NULL) { ...@@ -145,48 +87,49 @@ if (handle == NULL) {
} }
``` ```
### 销毁PWM设备句柄<a name="section3.3_PWM_des"></a>
### 销毁PWM设备句柄
关闭PWM设备,系统释放对应的资源。 关闭PWM设备,系统释放对应的资源。
```c
void PwmClose(DevHandle handle);
```
**表4** PwmClose参数描述 ```
voidPwmClose(DevHandle handle);
```
<a name="table4_PWM_des"></a> **表4** PwmClose参数描述
| 参数 | 参数描述 | | **参数** | **参数描述** |
| ------ | ----------- | | -------- | -------- |
| handle | PWM设备句柄 | | handle | PWM设备句柄 |
```c ```
/* 销毁PWM设备句柄 */ /* 销毁PWM设备句柄 */
PwmClose(handle); PwmClose(handle);
``` ```
### 使能<a name="section3.4_PWM_des"></a>
### 使能
启用PWM设备。 启用PWM设备。
```c
```
int32_t PwmEnable(DevHandle handle); int32_t PwmEnable(DevHandle handle);
``` ```
**表5** PwmEnable参数描述 **表5** PwmEnable参数和返回值描述
<a name="table5_PWM_des"></a>
| 参数 | 参数描述 | | **参数** | **参数描述** |
| ---------- | -------------- | | -------- | -------- |
| handle | PWM设备句柄 | | handle | PWM设备句柄 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 使能成功 | | 0 | 使能成功 |
| 负数 | 使能失败 | | 负数 | 使能失败 |
```c
```
int32_t ret; int32_t ret;
/*启用PWM设备*/ /*启用PWM设备*/
...@@ -196,26 +139,27 @@ if (ret != 0) { ...@@ -196,26 +139,27 @@ if (ret != 0) {
} }
``` ```
### 禁用<a name="section3.5_PWM_des"></a>
### 禁用
禁用PWM设备。 禁用PWM设备。
```c
```
int32_t PwmDisable(DevHandle handle); int32_t PwmDisable(DevHandle handle);
``` ```
**表6** PwmDisable参数描述 **表6** PwmDisable参数和返回值描述
<a name="table6_PWM_des"></a>
| 参数 | 参数描述 | | **参数** | **参数描述** |
| ---------- | -------------- | | -------- | -------- |
| handle | PWM设备句柄 | | handle | PWM设备句柄 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 禁用成功 | | 0 | 禁用成功 |
| 负数 | 禁用失败 | | 负数 | 禁用失败 |
```c
```
int32_t ret; int32_t ret;
/*禁用PWM设备*/ /*禁用PWM设备*/
...@@ -225,27 +169,28 @@ if (ret != 0) { ...@@ -225,27 +169,28 @@ if (ret != 0) {
} }
``` ```
### 设置PWM设备周期<a name="section3.6_PWM_des"></a>
### 设置PWM设备周期
设置PWM设备周期。 设置PWM设备周期。
```c
```
int32_t PwmSetPeriod(DevHandle handle, uint32_t period); int32_t PwmSetPeriod(DevHandle handle, uint32_t period);
``` ```
**表7** PwmSetPeriod参数描述 **表7** PwmSetPeriod参数和返回值描述
<a name="table7_PWM_des"></a> | **参数** | **参数描述** |
| -------- | -------- |
| 参数 | 参数描述 |
| ---------- | ------------------------ |
| handle | PWM设备句柄 | | handle | PWM设备句柄 |
| period | 要设置的周期,单位为纳秒 | | period | 要设置的周期,单位为纳秒 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 设置成功 | | 0 | 设置成功 |
| 负数 | 设置失败 | | 负数 | 设置失败 |
```c
```
int32_t ret; int32_t ret;
/*设置周期为50000000纳秒*/ /*设置周期为50000000纳秒*/
...@@ -254,27 +199,29 @@ if (ret != 0) { ...@@ -254,27 +199,29 @@ if (ret != 0) {
/*错误处理*/ /*错误处理*/
} }
``` ```
### 设置PWM设备占空时间<a name="section3.7_PWM_des"></a>
### 设置设备占空时间
设置PWM设备占空时间。 设置PWM设备占空时间。
```c
```
int32_t PwmSetDuty(DevHandle handle, uint32_t duty); int32_t PwmSetDuty(DevHandle handle, uint32_t duty);
``` ```
**表8** PwmSetDuty参数描述 **表8** PwmSetDuty参数和返回值描述
<a name="table8_PWM_des"></a> | **参数** | **参数描述** |
| -------- | -------- |
| 参数 | 参数描述 |
| ---------- | ---------------------------- |
| handle | PWM设备句柄 | | handle | PWM设备句柄 |
| duty | 要设置的占空时间,单位为纳秒 | | duty | 要设置的占空时间,单位为纳秒 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 设置成功 | | 0 | 设置成功 |
| 负数 | 设置失败 | | 负数 | 设置失败 |
```c
```
int32_t ret; int32_t ret;
/*设置占空时间为25000000纳秒*/ /*设置占空时间为25000000纳秒*/
...@@ -283,27 +230,29 @@ if (ret != 0) { ...@@ -283,27 +230,29 @@ if (ret != 0) {
/*错误处理*/ /*错误处理*/
} }
``` ```
### 设置PWM设备极性<a name="section3.8_PWM_des"></a>
### 设置PWM设备极性
设置PWM设备极性。 设置PWM设备极性。
```c
```
int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity); int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity);
``` ```
**表9** PwmSetPolarity参数描述 **表9** PwmSetPolarity参数和返回值描述
<a name="table9_PWM_des"></a>
| 参数 | 参数描述 | | **参数** | **参数描述** |
| ---------- | ------------------- | | -------- | -------- |
| handle | PWM设备句柄 | | handle | PWM设备句柄 |
| polarity | 要设置的极性,正/反 | | polarity | 要设置的极性,正/反 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 设置成功 | | 0 | 设置成功 |
| 负数 | 设置失败 | | 负数 | 设置失败 |
```c
```
int32_t ret; int32_t ret;
/*设置极性为反*/ /*设置极性为反*/
...@@ -314,27 +263,27 @@ if (ret != 0) { ...@@ -314,27 +263,27 @@ if (ret != 0) {
``` ```
### 设置PWM设备参数<a name="section3.9_PWM_des"></a> ### 设置PWM设备参数
设置PWM设备参数。 设置PWM设备参数。
```c
```
int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config); int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config);
``` ```
**表10** PwmSetConfig参数描述 **表10** PwmSetConfig参数和返回值描述
<a name="table10_PWM_des"></a>
| 参数 | 参数描述 | | **参数** | **参数描述** |
| ---------- | -------------- | | -------- | -------- |
| handle | PWM设备句柄 | | handle | PWM设备句柄 |
| *config | 参数指针 | | \*config | 参数指针 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 设置成功 | | 0 | 设置成功 |
| 负数 | 设置失败 | | 负数 | 设置失败 |
```c
```
int32_t ret; int32_t ret;
struct PwmConfig pcfg; struct PwmConfig pcfg;
pcfg.duty = 25000000; /*占空时间为25000000纳秒*/ pcfg.duty = 25000000; /*占空时间为25000000纳秒*/
...@@ -350,27 +299,28 @@ if (ret != 0) { ...@@ -350,27 +299,28 @@ if (ret != 0) {
} }
``` ```
### 获取PWM设备参数<a name="section3.10_PWM_des"></a>
### 获取PWM设备参数
获取PWM设备参数。 获取PWM设备参数。
```c
```
int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config); int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config);
``` ```
**表11** PwmGetConfig参数描述 **表11** PwmGetConfig参数和返回值描述
<a name="table11_PWM_des"></a>
| 参数 | 参数描述 | | **参数** | **参数描述** |
| ---------- | -------------- | | -------- | -------- |
| handle | PWM设备句柄 | | handle | PWM设备句柄 |
| *config | 参数指针 | | \*config | 参数指针 |
| **返回值** | **返回值描述** | | **返回值** | **返回值描述** |
| 0 | 获取成功 | | 0 | 获取成功 |
| 负数 | 获取失败 | | 负数 | 获取失败 |
```c
```
int32_t ret; int32_t ret;
struct PwmConfig pcfg; struct PwmConfig pcfg;
...@@ -381,10 +331,12 @@ if (ret != 0) { ...@@ -381,10 +331,12 @@ if (ret != 0) {
} }
``` ```
## 使用实例<a name="section4_PWM_des"></a>
## 使用实例
PWM设备完整的使用示例如下所示,首先获取PWM设备句柄,然后设置设备周期、占空时间、极性,获取设备参数。使能,设置设备参数,禁用,最后销毁PWM设备句柄。 PWM设备完整的使用示例如下所示,首先获取PWM设备句柄,然后设置设备周期、占空时间、极性,获取设备参数。使能,设置设备参数,禁用,最后销毁PWM设备句柄。
``` ```
void PwmTestSample(void) void PwmTestSample(void)
{ {
......
# PWM<a name="ZH-CN_TOPIC_0000001222082217"></a> # PWM
- [概述](#section1591602238164144)
- [接口说明](#section752964871810)
- [开发步骤](#section967396342164144)
- [开发实例](#section1883877829164144)
## 概述<a name="section1591602238164144"></a> ## 概述
PWM(Pulse Width Modulator)即脉冲宽度调节器,在HDF框架中,PWM的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 PWM(Pulse Width Modulator)即脉冲宽度调节器,在HDF框架中,PWM的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
**图 1** PWM独立服务模式结构图<a name="fig983655084219"></a> **图1** PWM独立服务模式结构图
![](figures/独立服务模式结构图.png "PWM独立服务模式结构图") ![zh-cn_image_0000001176603944](figures/zh-cn_image_0000001176603944.png)
## 接口说明<a name="section752964871810"></a>
## 接口说明
PwmMethod定义: PwmMethod定义:
``` ```
struct PwmMethod { struct PwmMethod {
int32_t (*setConfig)(struct PwmDev *pwm, struct PwmConfig *config); int32_t (*setConfig)(struct PwmDev *pwm, struct PwmConfig *config);
...@@ -24,80 +22,42 @@ struct PwmMethod { ...@@ -24,80 +22,42 @@ struct PwmMethod {
}; };
``` ```
**表 1** PwmMethod结构体成员的回调函数功能说明 **表1** PwmMethod结构体成员的回调函数功能说明
<a name="table11173154124311"></a> | 成员函数 | 入参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row2173441164311"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p17174144144310"><a name="p17174144144310"></a><a name="p17174144144310"></a>成员函数</p> | -------- | -------- | -------- | -------- |
</th> | setConfig | **pwm**:&nbsp;&nbsp;结构体指针,核心层PWM控制器;<br/>**config**:&nbsp;&nbsp;结构体指针,属性传入值; | HDF_STATUS相关状态 | 配置属性 |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p21751441154318"><a name="p21751441154318"></a><a name="p21751441154318"></a>入参</p> | open | **pwm**:&nbsp;&nbsp;结构体指针,核心层PWM控制器; | HDF_STATUS相关状态 | 打开设备 |
</th> | close | **pwm**:&nbsp;&nbsp;结构体指针,核心层PWM控制器; | HDF_STATUS相关状态 | 关闭设备 |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p191751741144313"><a name="p191751741144313"></a><a name="p191751741144313"></a>返回值</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p5175641154315"><a name="p5175641154315"></a><a name="p5175641154315"></a>功能</p> ## 开发步骤
</th>
</tr>
</thead>
<tbody><tr id="row7175154144311"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p3900552134317"><a name="p3900552134317"></a><a name="p3900552134317"></a>setConfig</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p422655084417"><a name="p422655084417"></a><a name="p422655084417"></a><strong id="b10227650134413"><a name="b10227650134413"></a><a name="b10227650134413"></a>pwm</strong>: 结构体指针,核心层PWM控制器;</p>
<p id="p02275502443"><a name="p02275502443"></a><a name="p02275502443"></a><strong id="b322719508445"><a name="b322719508445"></a><a name="b322719508445"></a>config</strong>: 结构体指针,属性传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p18176184112433"><a name="p18176184112433"></a><a name="p18176184112433"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p5176124164314"><a name="p5176124164314"></a><a name="p5176124164314"></a>配置属性</p>
</td>
</tr>
<tr id="row217654124312"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p121761041144314"><a name="p121761041144314"></a><a name="p121761041144314"></a>open</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p2176941144314"><a name="p2176941144314"></a><a name="p2176941144314"></a><strong id="b137308954516"><a name="b137308954516"></a><a name="b137308954516"></a>pwm</strong>: 结构体指针,核心层PWM控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1317694119435"><a name="p1317694119435"></a><a name="p1317694119435"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p376133118453"><a name="p376133118453"></a><a name="p376133118453"></a>打开设备</p>
</td>
</tr>
<tr id="row8176174110439"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p017684174314"><a name="p017684174314"></a><a name="p017684174314"></a>close</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1217694118437"><a name="p1217694118437"></a><a name="p1217694118437"></a><strong id="b44731616124513"><a name="b44731616124513"></a><a name="b44731616124513"></a>pwm</strong>: 结构体指针,核心层PWM控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p16176104115437"><a name="p16176104115437"></a><a name="p16176104115437"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p10893332114514"><a name="p10893332114514"></a><a name="p10893332114514"></a>关闭设备</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section967396342164144"></a>
PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加pwm\_config.hcs器件属性文件。 - 【可选】添加pwm_config.hcs器件属性文件。
3. **实例化PWM控制器对象:** 3. **实例化PWM控制器对象:**
- 初始化PwmDev成员。 - 初始化PwmDev成员。
- 实例化PwmDev成员PwmMethod。 - 实例化PwmDev成员PwmMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化PwmDev成员PwmMethod,其定义和成员说明见[接口说明](#接口说明)。
>实例化PwmDev成员PwmMethod,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如PWM控制状态,中断响应情况等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如PWM控制状态,中断响应情况等。
## 开发实例<a name="section1883877829164144"></a> ## 开发实例
下方将以pwm\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以pwm_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
...@@ -115,8 +75,9 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -115,8 +75,9 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动
HDF_INIT(g_hdfPwm); HDF_INIT(g_hdfPwm);
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 pwm\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层PwmDev成员的默认值或限制范围有密切关系。 如有更多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在pwm\_config文件中增加对应的器件属性**。** 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 pwm_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层PwmDev成员的默认值或限制范围有密切关系。 如有更多个器件信息,则需要在device_info文件增加deviceNode信息,以及在pwm_config文件中增加对应的器件属性**。**
- device\_info.hcs 配置参考。 - device_info.hcs 配置参考。
``` ```
root { root {
...@@ -147,8 +108,8 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -147,8 +108,8 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动
} }
} }
``` ```
- pwm_config.hcs 配置参考。
- pwm\_config.hcs 配置参考。
``` ```
root { root {
...@@ -176,7 +137,8 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -176,7 +137,8 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动
3. 完成驱动入口注册之后,最后一步就是以核心层PwmDev对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化PwmDev成员PwmMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层PwmDev对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化PwmDev成员PwmMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考。 - 自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且pwm\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号等。 从驱动的角度看,自定义结构体是参数和数据的载体,而且pwm_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号等。
``` ```
struct HiPwm { struct HiPwm {
...@@ -215,13 +177,13 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -215,13 +177,13 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动
- PwmDev成员回调函数结构体PwmMethod的实例化,其他成员在Init函数中初始化。 - PwmDev成员回调函数结构体PwmMethod的实例化,其他成员在Init函数中初始化。
``` ```
// pwm_hi35xx.c 中的示例:钩子函数的填充 // pwm_hi35xx.c 中的示例:钩子函数的填充
struct PwmMethod g_pwmOps = { struct PwmMethod g_pwmOps = {
.setConfig = HiPwmSetConfig,//配置属性 .setConfig = HiPwmSetConfig,//配置属性
}; };
``` ```
- Init函数参考 - Init函数参考
入参: 入参:
...@@ -230,52 +192,22 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -230,52 +192,22 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动
返回值: 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
<a name="table1057438215164144"></a> | 状态(值) | 问题描述 |
<table><thead align="left"><tr id="row31521027164144"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1990732428164144p0"><a name="entry1990732428164144p0"></a><a name="entry1990732428164144p0"></a>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry2123581292164144p0"><a name="entry2123581292164144p0"></a><a name="entry2123581292164144p0"></a>问题描述</p> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</th> | HDF_ERR_INVALID_PARAM | 参数非法 |
</tr> | HDF_ERR_IO | I/O&nbsp;错误 |
</thead> | HDF_SUCCESS | 初始化成功 |
<tbody><tr id="row1749271383164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry202330388164144p0"><a name="entry202330388164144p0"></a><a name="entry202330388164144p0"></a>HDF_ERR_INVALID_OBJECT</p> | HDF_FAILURE | 初始化失败 |
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1717598064164144p0"><a name="entry1717598064164144p0"></a><a name="entry1717598064164144p0"></a>控制器对象非法</p>
</td>
</tr>
<tr id="row1715354988164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry450625221164144p0"><a name="entry450625221164144p0"></a><a name="entry450625221164144p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry361497788164144p0"><a name="entry361497788164144p0"></a><a name="entry361497788164144p0"></a>内存分配失败</p>
</td>
</tr>
<tr id="row1202091366164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry370837906164144p0"><a name="entry370837906164144p0"></a><a name="entry370837906164144p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry353311523164144p0"><a name="entry353311523164144p0"></a><a name="entry353311523164144p0"></a>参数非法</p>
</td>
</tr>
<tr id="row602018308164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1984036607164144p0"><a name="entry1984036607164144p0"></a><a name="entry1984036607164144p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1221756048164144p0"><a name="entry1221756048164144p0"></a><a name="entry1221756048164144p0"></a>I/O 错误</p>
</td>
</tr>
<tr id="row47997479164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1220816374164144p0"><a name="entry1220816374164144p0"></a><a name="entry1220816374164144p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1903499126164144p0"><a name="entry1903499126164144p0"></a><a name="entry1903499126164144p0"></a>初始化成功</p>
</td>
</tr>
<tr id="row2031856197164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry463793674164144p0"><a name="entry463793674164144p0"></a><a name="entry463793674164144p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry516362874164144p0"><a name="entry516362874164144p0"></a><a name="entry516362874164144p0"></a>初始化失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
初始化自定义结构体对象,初始化PwmDev成员,调用核心层PwmDeviceAdd函数。 初始化自定义结构体对象,初始化PwmDev成员,调用核心层PwmDeviceAdd函数。
``` ```
//此处bind函数为空函数,可与init函数结合,也可根据厂商需要实现相关操作 //此处bind函数为空函数,可与init函数结合,也可根据厂商需要实现相关操作
static int32_t HdfPwmBind(struct HdfDeviceObject *obj) static int32_t HdfPwmBind(struct HdfDeviceObject *obj)
...@@ -320,7 +252,6 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -320,7 +252,6 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
- Release 函数参考 - Release 函数参考
入参: 入参:
...@@ -335,6 +266,7 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -335,6 +266,7 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。
``` ```
static void HdfPwmRelease(struct HdfDeviceObject *obj) static void HdfPwmRelease(struct HdfDeviceObject *obj)
{ {
...@@ -346,6 +278,3 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -346,6 +278,3 @@ PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动
HiPwmRemove(hp); //释放HiPwm HiPwmRemove(hp); //释放HiPwm
} }
``` ```
# RTC<a name="ZH-CN_TOPIC_0000001206373007"></a> # RTC
- [概述](#section104842041574)
- [接口说明](#section20331159102519) ## 概述
- [使用指导](#section20636145604113)
- [使用流程](#section16919828134215) RTC(real-time clock)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。
- [创建RTC设备句柄](#section1131212144310)
- [销毁RTC设备句柄](#section10744117144314)
- [注册RTC定时报警回调函数](#section14839440184320) ## 接口说明
- [操作RTC](#section161927578433)
**表1** RTC设备API接口功能介绍
- [使用实例](#section1186111020456)
| 功能分类 | 接口名 | 描述 |
## 概述<a name="section104842041574"></a> | -------- | -------- | -------- |
| RTC句柄操作 | RtcOpen:获取RTC设备驱动句柄<br/>RtcClose:释放RTC设备驱动句柄 | 获取RTC设备驱动句柄 |
RTC\(real-time clock\)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。 | RTC时间操作接口 | RtcReadTime | 读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 |
| RtcWriteTime | 写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 |
## 接口说明<a name="section20331159102519"></a> | RTC报警操作接口 | RtcReadAlarm | 读RTC报警时间信息 |
| RtcWriteAlarm | 写RTC报警时间信息 |
**表 1** RTC设备API接口功能介绍 | RtcRegisterAlarmCallback | 注册报警超时回调函数 |
| RtcAlarmInterruptEnable | 使能/去使能RTC报警中断 |
<a name="table1731550155318"></a> | RTC配置操作 | RtcGetFreq | 读RTC外接晶振频率 |
<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" valign="top" width="21.902190219021904%" id="mcps1.2.4.1.1"><p id="p641050105320"><a name="p641050105320"></a><a name="p641050105320"></a>功能分类</p> | RtcSetFreq | 配置RTC外接晶振频率 |
</th> | RtcReset | RTC复位 |
<th class="cellrowborder" valign="top" width="24.98249824982498%" id="mcps1.2.4.1.2"><p id="p54150165315"><a name="p54150165315"></a><a name="p54150165315"></a>接口名</p> | 读写用户定义寄存器 | RtcReadReg | 读用户自定义寄存器 |
</th> | RtcWriteReg | 写用户自定义寄存器 |
<th class="cellrowborder" valign="top" width="53.11531153115312%" id="mcps1.2.4.1.3"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>描述</p>
</th> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
</tr> > 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
</thead>
<tbody><tr id="row17550163418501"><td class="cellrowborder" rowspan="2" valign="top" width="21.902190219021904%" headers="mcps1.2.4.1.1 "><p id="p11670643205012"><a name="p11670643205012"></a><a name="p11670643205012"></a>RTC句柄操作</p>
</td> ## 使用指导
<td class="cellrowborder" valign="top" width="24.98249824982498%" headers="mcps1.2.4.1.2 "><p id="p16550143465015"><a name="p16550143465015"></a><a name="p16550143465015"></a>RtcOpen</p>
</td>
<td class="cellrowborder" valign="top" width="53.11531153115312%" headers="mcps1.2.4.1.3 "><p id="p9550103415015"><a name="p9550103415015"></a><a name="p9550103415015"></a>获取RTC设备驱动句柄</p> ### 使用流程
</td>
</tr>
<tr id="row1879052755020"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1479062716506"><a name="p1479062716506"></a><a name="p1479062716506"></a>RtcClose</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1579142745012"><a name="p1579142745012"></a><a name="p1579142745012"></a>释放RTC设备驱动句柄</p>
</td>
</tr>
<tr id="row34145016535"><td class="cellrowborder" rowspan="2" valign="top" width="21.902190219021904%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>RTC时间操作接口</p>
</td>
<td class="cellrowborder" valign="top" width="24.98249824982498%" headers="mcps1.2.4.1.2 "><p id="p19389143041518"><a name="p19389143041518"></a><a name="p19389143041518"></a>RtcReadTime</p>
</td>
<td class="cellrowborder" valign="top" width="53.11531153115312%" headers="mcps1.2.4.1.3 "><p id="p8738101941716"><a name="p8738101941716"></a><a name="p8738101941716"></a>读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒</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>RtcWriteTime</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p573815197171"><a name="p573815197171"></a><a name="p573815197171"></a>写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒</p>
</td>
</tr>
<tr id="row1468016592416"><td class="cellrowborder" rowspan="4" valign="top" width="21.902190219021904%" headers="mcps1.2.4.1.1 "><p id="p36817591648"><a name="p36817591648"></a><a name="p36817591648"></a>RTC报警操作接口</p>
</td>
<td class="cellrowborder" valign="top" width="24.98249824982498%" headers="mcps1.2.4.1.2 "><p id="p968116598418"><a name="p968116598418"></a><a name="p968116598418"></a>RtcReadAlarm</p>
</td>
<td class="cellrowborder" valign="top" width="53.11531153115312%" headers="mcps1.2.4.1.3 "><p id="p768110592416"><a name="p768110592416"></a><a name="p768110592416"></a>读RTC报警时间信息</p>
</td>
</tr>
<tr id="row19313155514"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p73141951155"><a name="p73141951155"></a><a name="p73141951155"></a>RtcWriteAlarm</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p15314656511"><a name="p15314656511"></a><a name="p15314656511"></a>写RTC报警时间信息</p>
</td>
</tr>
<tr id="row138283422555"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p2829142165513"><a name="p2829142165513"></a><a name="p2829142165513"></a>RtcRegisterAlarmCallback</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p118291242155518"><a name="p118291242155518"></a><a name="p118291242155518"></a>注册报警超时回调函数</p>
</td>
</tr>
<tr id="row13344113914568"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p2344103915616"><a name="p2344103915616"></a><a name="p2344103915616"></a>RtcAlarmInterruptEnable</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p034415397565"><a name="p034415397565"></a><a name="p034415397565"></a>使能/去使能RTC报警中断</p>
</td>
</tr>
<tr id="row11801203517565"><td class="cellrowborder" rowspan="3" valign="top" width="21.902190219021904%" headers="mcps1.2.4.1.1 "><p id="p17261458942"><a name="p17261458942"></a><a name="p17261458942"></a>RTC配置操作</p>
</td>
<td class="cellrowborder" valign="top" width="24.98249824982498%" headers="mcps1.2.4.1.2 "><p id="p15801153515561"><a name="p15801153515561"></a><a name="p15801153515561"></a>RtcGetFreq</p>
</td>
<td class="cellrowborder" valign="top" width="53.11531153115312%" headers="mcps1.2.4.1.3 "><p id="p980133515566"><a name="p980133515566"></a><a name="p980133515566"></a>读RTC外接晶振频率</p>
</td>
</tr>
<tr id="row111502322563"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1615073225618"><a name="p1615073225618"></a><a name="p1615073225618"></a>RtcSetFreq</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p10150832165613"><a name="p10150832165613"></a><a name="p10150832165613"></a>配置RTC外接晶振频率</p>
</td>
</tr>
<tr id="row21771259145618"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1717725916562"><a name="p1717725916562"></a><a name="p1717725916562"></a>RtcReset</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p517712598569"><a name="p517712598569"></a><a name="p517712598569"></a>RTC复位</p>
</td>
</tr>
<tr id="row917116425716"><td class="cellrowborder" rowspan="2" valign="top" width="21.902190219021904%" headers="mcps1.2.4.1.1 "><p id="p144765201754"><a name="p144765201754"></a><a name="p144765201754"></a>读写用户定义寄存器</p>
</td>
<td class="cellrowborder" valign="top" width="24.98249824982498%" headers="mcps1.2.4.1.2 "><p id="p1117110418570"><a name="p1117110418570"></a><a name="p1117110418570"></a>RtcReadReg</p>
</td>
<td class="cellrowborder" valign="top" width="53.11531153115312%" headers="mcps1.2.4.1.3 "><p id="p1517114410578"><a name="p1517114410578"></a><a name="p1517114410578"></a>读用户自定义寄存器</p>
</td>
</tr>
<tr id="row46738190576"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1567331910573"><a name="p1567331910573"></a><a name="p1567331910573"></a>RtcWriteReg</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1967391913576"><a name="p1967391913576"></a><a name="p1967391913576"></a>写用户自定义寄存器</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
## 使用指导<a name="section20636145604113"></a>
### 使用流程<a name="section16919828134215"></a>
在操作系统启动过程中,驱动管理模块根据配置文件加载RTC驱动,RTC驱动会检测RTC器件并初始化驱动。 在操作系统启动过程中,驱动管理模块根据配置文件加载RTC驱动,RTC驱动会检测RTC器件并初始化驱动。
使用RTC设备的一般流程如[图1](#fig1610020107333)所示。 使用RTC设备的一般流程如下图所示。
**图 1** RTC设备使用流程图<a name="fig1610020107333"></a> **图1** RTC设备使用流程图
![](figures/RTC设备使用流程图.png "RTC设备使用流程图") ![zh-cn_image_0000001160971552](figures/zh-cn_image_0000001160971552.png)
### 创建RTC设备句柄<a name="section1131212144310"></a>
### 创建RTC设备句柄
RTC驱动加载成功后,驱动开发者使用驱动框架提供的查询接口并调用RTC设备驱动接口。 RTC驱动加载成功后,驱动开发者使用驱动框架提供的查询接口并调用RTC设备驱动接口。
>![](../public_sys-resources/icon-note.gif) **说明:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>当前操作系统支持一个RTC设备。 > 当前操作系统支持一个RTC设备。
DevHandle RtcOpen\(void\); DevHandle RtcOpen(void);
**表 2** RtcOpen参数和返回值描述 **表2** RtcOpen参数和返回值描述
<a name="table1380712985611"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row580722985616"><td class="cellrowborder" valign="top" width="21.45%"><p id="p1280722911565"><a name="p1280722911565"></a><a name="p1280722911565"></a><strong id="b4807829175617"><a name="b4807829175617"></a><a name="b4807829175617"></a>参数</strong></p> | -------- | -------- |
</td> | void | NA |
<td class="cellrowborder" valign="top" width="78.55%"><p id="p5807112965618"><a name="p5807112965618"></a><a name="p5807112965618"></a><strong id="b11807172912564"><a name="b11807172912564"></a><a name="b11807172912564"></a>参数描述</strong></p> | **返回值** | **返回值描述** |
</td> | handle | 操作成功返回&nbsp;&nbsp;指针类型 |
</tr> | NULL | 操作失败 |
<tr id="row17807112935611"><td class="cellrowborder" valign="top" width="21.45%"><p id="p13807132915565"><a name="p13807132915565"></a><a name="p13807132915565"></a>void</p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p15807429185612"><a name="p15807429185612"></a><a name="p15807429185612"></a>NA</p>
</td>
</tr>
<tr id="row1980782911567"><td class="cellrowborder" valign="top" width="21.45%"><p id="p0807529165613"><a name="p0807529165613"></a><a name="p0807529165613"></a><strong id="b2807132925619"><a name="b2807132925619"></a><a name="b2807132925619"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p9808162935612"><a name="p9808162935612"></a><a name="p9808162935612"></a><strong id="b1808152910566"><a name="b1808152910566"></a><a name="b1808152910566"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row2808192935615"><td class="cellrowborder" valign="top" width="21.45%"><p id="p380852915567"><a name="p380852915567"></a><a name="p380852915567"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p26881319114110"><a name="p26881319114110"></a><a name="p26881319114110"></a>操作成功返回 指针类型</p>
</td>
</tr>
<tr id="row4808142945615"><td class="cellrowborder" valign="top" width="21.45%"><p id="p188084291561"><a name="p188084291561"></a><a name="p188084291561"></a>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p780852912566"><a name="p780852912566"></a><a name="p780852912566"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
DevHandle handle = NULL; DevHandle handle = NULL;
...@@ -170,82 +71,44 @@ if (handle == NULL) { ...@@ -170,82 +71,44 @@ if (handle == NULL) {
} }
``` ```
### 销毁RTC设备句柄<a name="section10744117144314"></a>
### 销毁RTC设备句柄
销毁RTC设备句柄,系统释放对应的资源。 销毁RTC设备句柄,系统释放对应的资源。
void RtcClose\(DevHandle handle\); void RtcClose(DevHandle handle);
**表 3** RtcClose参数描述 **表3** RtcClose参数描述
| **参数** | **参数描述** |
| -------- | -------- |
| handle | RTC设备句柄 |
<a name="table37525421510"></a>
<table><tbody><tr id="row10752134216114"><td class="cellrowborder" valign="top" width="21.45%"><p id="p1075217421019"><a name="p1075217421019"></a><a name="p1075217421019"></a><strong id="b1575214428111"><a name="b1575214428111"></a><a name="b1575214428111"></a>参数</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p117531421411"><a name="p117531421411"></a><a name="p117531421411"></a><strong id="b37535425119"><a name="b37535425119"></a><a name="b37535425119"></a>参数描述</strong></p>
</td>
</tr>
<tr id="row57531442914"><td class="cellrowborder" valign="top" width="21.45%"><p id="p8753164210119"><a name="p8753164210119"></a><a name="p8753164210119"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p17533425113"><a name="p17533425113"></a><a name="p17533425113"></a>RTC设备句柄</p>
</td>
</tr>
</tbody>
</table>
``` ```
/* 销毁RTC句柄 */ /* 销毁RTC句柄 */
RtcClose(handle); RtcClose(handle);
``` ```
### 注册RTC定时报警回调函数<a name="section14839440184320"></a>
### 注册RTC定时报警回调函数
系统启动后需要注册RTC定时报警回调函数,报警超时后触发回调函数。 系统启动后需要注册RTC定时报警回调函数,报警超时后触发回调函数。
int32\_t RtcRegisterAlarmCallback\(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb\); int32_t RtcRegisterAlarmCallback(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb);
**表 4** RtcRegisterAlarmCallback参数和返回值描述 **表4** RtcRegisterAlarmCallback参数和返回值描述
<a name="table7603619123820"></a> | **参数** | **参数描述** |
<table><thead align="left"><tr id="row1060351914386"><th class="cellrowborder" valign="top" width="21.36%" 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> | handle | RTC设备句柄 |
<th class="cellrowborder" valign="top" width="78.64%" 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> | alarmIndex | 报警索引 |
</th> | cb | 定时报警回调函数 |
</tr> | **返回值** | **返回值描述** |
</thead> | 0 | 操作成功 |
<tbody><tr id="row1181618191115"><td class="cellrowborder" valign="top" width="21.36%" headers="mcps1.2.3.1.1 "><p id="p131811218131116"><a name="p131811218131116"></a><a name="p131811218131116"></a>handle</p> | 负数 | 操作失败 |
</td>
<td class="cellrowborder" valign="top" width="78.64%" headers="mcps1.2.3.1.2 "><p id="p6181191851111"><a name="p6181191851111"></a><a name="p6181191851111"></a>RTC设备句柄</p> 注册RTC_ALARM_INDEX_A的定时报警处理函数, 示例如下:
</td>
</tr>
<tr id="row960361918383"><td class="cellrowborder" valign="top" width="21.36%" headers="mcps1.2.3.1.1 "><p id="p1775535165418"><a name="p1775535165418"></a><a name="p1775535165418"></a>alarmIndex</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%" headers="mcps1.2.3.1.2 "><p id="p137551851185412"><a name="p137551851185412"></a><a name="p137551851185412"></a>报警索引</p>
</td>
</tr>
<tr id="row1960431983813"><td class="cellrowborder" valign="top" width="21.36%" headers="mcps1.2.3.1.1 "><p id="p3604719123817"><a name="p3604719123817"></a><a name="p3604719123817"></a>cb</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%" headers="mcps1.2.3.1.2 "><p id="p1560441923818"><a name="p1560441923818"></a><a name="p1560441923818"></a>定时报警回调函数</p>
</td>
</tr>
<tr id="row11410612183019"><td class="cellrowborder" valign="top" width="21.36%" 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="78.64%" 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="21.36%" headers="mcps1.2.3.1.1 "><p id="p133081510112813"><a name="p133081510112813"></a><a name="p133081510112813"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%" headers="mcps1.2.3.1.2 "><p id="p530813107289"><a name="p530813107289"></a><a name="p530813107289"></a>操作成功</p>
</td>
</tr>
<tr id="row1241081213303"><td class="cellrowborder" valign="top" width="21.36%" headers="mcps1.2.3.1.1 "><p id="p1123362173010"><a name="p1123362173010"></a><a name="p1123362173010"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%" headers="mcps1.2.3.1.2 "><p id="p1723362153010"><a name="p1723362153010"></a><a name="p1723362153010"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
注册RTC\_ALARM\_INDEX\_A的定时报警处理函数, 示例如下:
``` ```
/* 用户注册RTC定时报警回调函数的方法 */ /* 用户注册RTC定时报警回调函数的方法 */
...@@ -268,49 +131,25 @@ if (ret != 0) { ...@@ -268,49 +131,25 @@ if (ret != 0) {
} }
``` ```
### 操作RTC<a name="section161927578433"></a>
### 操作RTC
- 读取RTC时间。 - 读取RTC时间。
系统从RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒,则可以通过以下函数完成: 系统从RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒,则可以通过以下函数完成:
int32\_t RtcReadTime\(DevHandle handle, struct RtcTime \*time\); int32_t RtcReadTime(DevHandle handle, struct RtcTime \*time);
**表 5** RtcReadTime参数和返回值描述 **表5** RtcReadTime参数和返回值描述
<a name="table1018490043"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row31848013417"><td class="cellrowborder" valign="top" width="21.45%"><p id="p1415816132411"><a name="p1415816132411"></a><a name="p1415816132411"></a><strong id="b129796117337"><a name="b129796117337"></a><a name="b129796117337"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.55%"><p id="p11158111316410"><a name="p11158111316410"></a><a name="p11158111316410"></a><strong id="b1699118123314"><a name="b1699118123314"></a><a name="b1699118123314"></a>参数描述</strong></p> | time | RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒 |
</td> | **返回值** | **返回值描述** |
</tr> | 0 | 操作成功 |
<tr id="row1246615200297"><td class="cellrowborder" valign="top" width="21.45%"><p id="p188871821142917"><a name="p188871821142917"></a><a name="p188871821142917"></a>handle</p> | 负数 | 操作失败 |
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p1788742182910"><a name="p1788742182910"></a><a name="p1788742182910"></a>RTC设备句柄</p>
</td>
</tr>
<tr id="row10184701945"><td class="cellrowborder" valign="top" width="21.45%"><p id="p104891871157"><a name="p104891871157"></a><a name="p104891871157"></a>time</p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p204891671156"><a name="p204891671156"></a><a name="p204891671156"></a>RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒</p>
</td>
</tr>
<tr id="row17393154515328"><td class="cellrowborder" valign="top" width="21.45%"><p id="p8158313248"><a name="p8158313248"></a><a name="p8158313248"></a><strong id="b18542051332"><a name="b18542051332"></a><a name="b18542051332"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p161591413741"><a name="p161591413741"></a><a name="p161591413741"></a><strong id="b45520523313"><a name="b45520523313"></a><a name="b45520523313"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row339324593215"><td class="cellrowborder" valign="top" width="21.45%"><p id="p139599615287"><a name="p139599615287"></a><a name="p139599615287"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p1895911611284"><a name="p1895911611284"></a><a name="p1895911611284"></a>操作成功</p>
</td>
</tr>
<tr id="row15393184519323"><td class="cellrowborder" valign="top" width="21.45%"><p id="p13521182309"><a name="p13521182309"></a><a name="p13521182309"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.55%"><p id="p1035216186309"><a name="p1035216186309"></a><a name="p1035216186309"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -327,46 +166,21 @@ if (ret != 0) { ...@@ -327,46 +166,21 @@ if (ret != 0) {
设置RTC时间,则可以通过以下函数完成: 设置RTC时间,则可以通过以下函数完成:
int32\_t RtcWriteTime\(DevHandle handle, struct RtcTime \*time\); int32_t RtcWriteTime(DevHandle handle, struct RtcTime \*time);
**表 6** RtcWriteTime参数和返回值描述 **表6** RtcWriteTime参数和返回值描述
<a name="table223910318361"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row924033173613"><td class="cellrowborder" valign="top" width="21.54%"><p id="p16240143143611"><a name="p16240143143611"></a><a name="p16240143143611"></a><strong id="b1724033112363"><a name="b1724033112363"></a><a name="b1724033112363"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.46%"><p id="p32401031113610"><a name="p32401031113610"></a><a name="p32401031113610"></a><strong id="b1324013111363"><a name="b1324013111363"></a><a name="b1324013111363"></a>参数描述</strong></p> | time | 写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 |
</td> | **返回值** | **返回值描述** |
</tr> | 0 | 操作成功 |
<tr id="row148011248153018"><td class="cellrowborder" valign="top" width="21.54%"><p id="p189641849113018"><a name="p189641849113018"></a><a name="p189641849113018"></a>handle</p> | 负数 | 操作失败 |
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p20964249123013"><a name="p20964249123013"></a><a name="p20964249123013"></a>RTC设备句柄</p> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
</td> > RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。
</tr>
<tr id="row024043193619"><td class="cellrowborder" valign="top" width="21.54%"><p id="p157679281384"><a name="p157679281384"></a><a name="p157679281384"></a>time</p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p167675286381"><a name="p167675286381"></a><a name="p167675286381"></a>写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒</p>
</td>
</tr>
<tr id="row424093120369"><td class="cellrowborder" valign="top" width="21.54%"><p id="p1240143114366"><a name="p1240143114366"></a><a name="p1240143114366"></a><strong id="b0240173133615"><a name="b0240173133615"></a><a name="b0240173133615"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p18241173133619"><a name="p18241173133619"></a><a name="p18241173133619"></a><strong id="b7241153112361"><a name="b7241153112361"></a><a name="b7241153112361"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row18241531153610"><td class="cellrowborder" valign="top" width="21.54%"><p id="p8550174182810"><a name="p8550174182810"></a><a name="p8550174182810"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p145503417284"><a name="p145503417284"></a><a name="p145503417284"></a>操作成功</p>
</td>
</tr>
<tr id="row024153123616"><td class="cellrowborder" valign="top" width="21.54%"><p id="p5602191619300"><a name="p5602191619300"></a><a name="p5602191619300"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p12602131643015"><a name="p12602131643015"></a><a name="p12602131643015"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。
``` ```
int32_t ret; int32_t ret;
...@@ -391,48 +205,19 @@ if (ret != 0) { ...@@ -391,48 +205,19 @@ if (ret != 0) {
如果需要读取定时报警时间,则可以通过以下函数完成: 如果需要读取定时报警时间,则可以通过以下函数完成:
int32\_t RtcReadAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); int32_t RtcReadAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time);
**表 7** RtcReadAlarm参数和返回值描述 **表7** RtcReadAlarm参数和返回值描述
<a name="table11342203111420"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row133429310140"><td class="cellrowborder" valign="top" width="21.54%"><p id="p9886411201416"><a name="p9886411201416"></a><a name="p9886411201416"></a><strong id="b38861211101412"><a name="b38861211101412"></a><a name="b38861211101412"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.46%"><p id="p2886411171417"><a name="p2886411171417"></a><a name="p2886411171417"></a><strong id="b158861411141411"><a name="b158861411141411"></a><a name="b158861411141411"></a>参数描述</strong></p> | alarmIndex | 报警索引 |
</td> | time | RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒 |
</tr> | **返回值** | **返回值描述** |
<tr id="row13835647114113"><td class="cellrowborder" valign="top" width="21.54%"><p id="p1183011486412"><a name="p1183011486412"></a><a name="p1183011486412"></a>handle</p> | 0 | 操作成功 |
</td> | 负数 | 操作失败 |
<td class="cellrowborder" valign="top" width="78.46%"><p id="p1583074815413"><a name="p1583074815413"></a><a name="p1583074815413"></a>RTC设备句柄</p>
</td>
</tr>
<tr id="row113439391410"><td class="cellrowborder" valign="top" width="21.54%"><p id="p132281120194318"><a name="p132281120194318"></a><a name="p132281120194318"></a>alarmIndex</p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p1022852034315"><a name="p1022852034315"></a><a name="p1022852034315"></a>报警索引</p>
</td>
</tr>
<tr id="row193431836147"><td class="cellrowborder" valign="top" width="21.54%"><p id="p1926195164011"><a name="p1926195164011"></a><a name="p1926195164011"></a>time</p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p112695144013"><a name="p112695144013"></a><a name="p112695144013"></a>RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒</p>
</td>
</tr>
<tr id="row43438361419"><td class="cellrowborder" valign="top" width="21.54%"><p id="p388715117143"><a name="p388715117143"></a><a name="p388715117143"></a><strong id="b9887011121415"><a name="b9887011121415"></a><a name="b9887011121415"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p088719117143"><a name="p088719117143"></a><a name="p088719117143"></a><strong id="b1788714110146"><a name="b1788714110146"></a><a name="b1788714110146"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row17169595467"><td class="cellrowborder" valign="top" width="21.54%"><p id="p107751111283"><a name="p107751111283"></a><a name="p107751111283"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p87751917289"><a name="p87751917289"></a><a name="p87751917289"></a>操作成功</p>
</td>
</tr>
<tr id="row016911915461"><td class="cellrowborder" valign="top" width="21.54%"><p id="p6833213133013"><a name="p6833213133013"></a><a name="p6833213133013"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.46%"><p id="p168341213143015"><a name="p168341213143015"></a><a name="p168341213143015"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -449,51 +234,22 @@ if (ret != 0) { ...@@ -449,51 +234,22 @@ if (ret != 0) {
根据报警索引设置RTC报警时间,通过以下函数完成: 根据报警索引设置RTC报警时间,通过以下函数完成:
int32\_t RtcWriteAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); int32_t RtcWriteAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time);
**表 8** RtcWriteAlarm参数和返回值描述 **表8** RtcWriteAlarm参数和返回值描述
<a name="table107922162179"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row14793316131710"><td class="cellrowborder" valign="top" width="21.62%"><p id="p1891718412183"><a name="p1891718412183"></a><a name="p1891718412183"></a><strong id="b11841849174820"><a name="b11841849174820"></a><a name="b11841849174820"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p891712461814"><a name="p891712461814"></a><a name="p891712461814"></a><strong id="b985314916480"><a name="b985314916480"></a><a name="b985314916480"></a>参数描述</strong></p> | alarmIndex | 报警索引 |
</td> | time | RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒 |
</tr> | **返回值** | **返回值描述** |
<tr id="row18419611133117"><td class="cellrowborder" valign="top" width="21.62%"><p id="p075881210314"><a name="p075881210314"></a><a name="p075881210314"></a>handle</p> | 0 | 操作成功 |
</td> | 负数 | 操作失败 |
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p975811215317"><a name="p975811215317"></a><a name="p975811215317"></a>RTC设备句柄</p>
</td> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
</tr> > RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。
<tr id="row11793151613176"><td class="cellrowborder" valign="top" width="21.62%"><p id="p562522145215"><a name="p562522145215"></a><a name="p562522145215"></a>alarmIndex</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p126257215217"><a name="p126257215217"></a><a name="p126257215217"></a>报警索引</p>
</td>
</tr>
<tr id="row37932016201720"><td class="cellrowborder" valign="top" width="21.62%"><p id="p26269212527"><a name="p26269212527"></a><a name="p26269212527"></a>time</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p462602125211"><a name="p462602125211"></a><a name="p462602125211"></a>RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒</p>
</td>
</tr>
<tr id="row586915225485"><td class="cellrowborder" valign="top" width="21.62%"><p id="p591712441810"><a name="p591712441810"></a><a name="p591712441810"></a><strong id="b1992335254811"><a name="b1992335254811"></a><a name="b1992335254811"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p1591720461810"><a name="p1591720461810"></a><a name="p1591720461810"></a><strong id="b792425244814"><a name="b792425244814"></a><a name="b792425244814"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row19869122210483"><td class="cellrowborder" valign="top" width="21.62%"><p id="p10798105812717"><a name="p10798105812717"></a><a name="p10798105812717"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p1179817586276"><a name="p1179817586276"></a><a name="p1179817586276"></a>操作成功</p>
</td>
</tr>
<tr id="row1686918225483"><td class="cellrowborder" valign="top" width="21.62%"><p id="p16246181033012"><a name="p16246181033012"></a><a name="p16246181033012"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p3246111019309"><a name="p3246111019309"></a><a name="p3246111019309"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。
``` ```
int32_t ret; int32_t ret;
...@@ -518,48 +274,19 @@ if (ret != 0) { ...@@ -518,48 +274,19 @@ if (ret != 0) {
在启动报警操作前,需要先设置报警中断使能,报警超时后会触发告警回调函数,可以通过以下函数完成: 在启动报警操作前,需要先设置报警中断使能,报警超时后会触发告警回调函数,可以通过以下函数完成:
int32\_t RtcAlarmInterruptEnable\(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8\_t enable\); int32_t RtcAlarmInterruptEnable(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8_t enable);
**表 9** RtcAlarmInterruptEnable参数和返回值描述 **表9** RtcAlarmInterruptEnable参数和返回值描述
<a name="table1934615314159"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row5346853171519"><td class="cellrowborder" valign="top" width="21.36%"><p id="p143464533153"><a name="p143464533153"></a><a name="p143464533153"></a><strong id="b63463534157"><a name="b63463534157"></a><a name="b63463534157"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.64%"><p id="p113461853171514"><a name="p113461853171514"></a><a name="p113461853171514"></a><strong id="b153461253191513"><a name="b153461253191513"></a><a name="b153461253191513"></a>参数描述</strong></p> | alarmIndex | 报警索引 |
</td> | enable | RTC报警中断配置,1:使能,0:去使能 |
</tr> | **返回值** | **返回值描述** |
<tr id="row2125652144213"><td class="cellrowborder" valign="top" width="21.36%"><p id="p3150105313422"><a name="p3150105313422"></a><a name="p3150105313422"></a>handle</p> | 0 | 操作成功 |
</td> | 负数 | 操作失败 |
<td class="cellrowborder" valign="top" width="78.64%"><p id="p9151653144212"><a name="p9151653144212"></a><a name="p9151653144212"></a>RTC设备句柄</p>
</td>
</tr>
<tr id="row153794518293"><td class="cellrowborder" valign="top" width="21.36%"><p id="p4259165518294"><a name="p4259165518294"></a><a name="p4259165518294"></a>alarmIndex</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p725985522917"><a name="p725985522917"></a><a name="p725985522917"></a>报警索引</p>
</td>
</tr>
<tr id="row19346653141518"><td class="cellrowborder" valign="top" width="21.36%"><p id="p6346253101516"><a name="p6346253101516"></a><a name="p6346253101516"></a>enable</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p234655341511"><a name="p234655341511"></a><a name="p234655341511"></a>RTC报警中断配置,1:使能,0:去使能</p>
</td>
</tr>
<tr id="row18346953111513"><td class="cellrowborder" valign="top" width="21.36%"><p id="p53460537156"><a name="p53460537156"></a><a name="p53460537156"></a><strong id="b23461553171512"><a name="b23461553171512"></a><a name="b23461553171512"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p4346153171510"><a name="p4346153171510"></a><a name="p4346153171510"></a><strong id="b1834675316154"><a name="b1834675316154"></a><a name="b1834675316154"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row1234685314151"><td class="cellrowborder" valign="top" width="21.36%"><p id="p8947195310279"><a name="p8947195310279"></a><a name="p8947195310279"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p99471953152712"><a name="p99471953152712"></a><a name="p99471953152712"></a>操作成功</p>
</td>
</tr>
<tr id="row2347115321514"><td class="cellrowborder" valign="top" width="21.36%"><p id="p324855163018"><a name="p324855163018"></a><a name="p324855163018"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p7248857302"><a name="p7248857302"></a><a name="p7248857302"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -575,43 +302,18 @@ if (ret != 0) { ...@@ -575,43 +302,18 @@ if (ret != 0) {
读取RTC外接晶体振荡频率,可以通过以下函数完成: 读取RTC外接晶体振荡频率,可以通过以下函数完成:
int32\_t RtcGetFreq\(DevHandle handle, uint32\_t \*freq\); int32_t RtcGetFreq(DevHandle handle, uint32_t \*freq);
**表 10** RtcGetFreq参数和返回值描述 **表10** RtcGetFreq参数和返回值描述
<a name="table125881625185"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row1458811241816"><td class="cellrowborder" valign="top" width="21.36%"><p id="p658820241813"><a name="p658820241813"></a><a name="p658820241813"></a><strong id="b1358817216185"><a name="b1358817216185"></a><a name="b1358817216185"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.64%"><p id="p758812261820"><a name="p758812261820"></a><a name="p758812261820"></a><strong id="b2588922188"><a name="b2588922188"></a><a name="b2588922188"></a>参数描述</strong></p> | freq | RTC的外接晶体振荡频率,单位(HZ) |
</td> | **返回值** | **返回值描述** |
</tr> | 0 | 操作成功 |
<tr id="row831259124219"><td class="cellrowborder" valign="top" width="21.36%"><p id="p171541407431"><a name="p171541407431"></a><a name="p171541407431"></a>handle</p> | 负数 | 操作失败 |
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p715413094314"><a name="p715413094314"></a><a name="p715413094314"></a>RTC设备句柄</p>
</td>
</tr>
<tr id="row1358842171820"><td class="cellrowborder" valign="top" width="21.36%"><p id="p258814210188"><a name="p258814210188"></a><a name="p258814210188"></a>freq</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p165888211810"><a name="p165888211810"></a><a name="p165888211810"></a>RTC的外接晶体振荡频率,单位(HZ)</p>
</td>
</tr>
<tr id="row2058818281817"><td class="cellrowborder" valign="top" width="21.36%"><p id="p458872151810"><a name="p458872151810"></a><a name="p458872151810"></a><strong id="b658814210189"><a name="b658814210189"></a><a name="b658814210189"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p155880251819"><a name="p155880251819"></a><a name="p155880251819"></a><strong id="b558816211182"><a name="b558816211182"></a><a name="b558816211182"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row35883213183"><td class="cellrowborder" valign="top" width="21.36%"><p id="p8133145211272"><a name="p8133145211272"></a><a name="p8133145211272"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p13133352202719"><a name="p13133352202719"></a><a name="p13133352202719"></a>操作成功</p>
</td>
</tr>
<tr id="row135892261811"><td class="cellrowborder" valign="top" width="21.36%"><p id="p152692538292"><a name="p152692538292"></a><a name="p152692538292"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p327015313294"><a name="p327015313294"></a><a name="p327015313294"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -628,43 +330,18 @@ if (ret != 0) { ...@@ -628,43 +330,18 @@ if (ret != 0) {
配置RTC外接晶体振荡频率,可以通过以下函数完成: 配置RTC外接晶体振荡频率,可以通过以下函数完成:
int32\_t RtcSetFreq\(DevHandle handle, uint32\_t freq\); int32_t RtcSetFreq(DevHandle handle, uint32_t freq);
**表 11** RtcSetFreq参数和返回值描述 **表11** RtcSetFreq参数和返回值描述
<a name="table1170124316209"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row270119432202"><td class="cellrowborder" valign="top" width="21.36%"><p id="p127011343132010"><a name="p127011343132010"></a><a name="p127011343132010"></a><strong id="b970114382014"><a name="b970114382014"></a><a name="b970114382014"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.64%"><p id="p7701184372013"><a name="p7701184372013"></a><a name="p7701184372013"></a><strong id="b11701743182010"><a name="b11701743182010"></a><a name="b11701743182010"></a>参数描述</strong></p> | freq | RTC的外接晶体振荡频率,单位(HZ) |
</td> | **返回值** | **返回值描述** |
</tr> | 0 | 操作成功 |
<tr id="row36067554319"><td class="cellrowborder" valign="top" width="21.36%"><p id="p881511716433"><a name="p881511716433"></a><a name="p881511716433"></a>handle</p> | 负数 | 操作失败 |
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p188157714432"><a name="p188157714432"></a><a name="p188157714432"></a>RTC设备句柄</p>
</td>
</tr>
<tr id="row127019437204"><td class="cellrowborder" valign="top" width="21.36%"><p id="p27019438207"><a name="p27019438207"></a><a name="p27019438207"></a>freq</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p167021043182011"><a name="p167021043182011"></a><a name="p167021043182011"></a>RTC的外接晶体振荡频率,单位(HZ)</p>
</td>
</tr>
<tr id="row97022434205"><td class="cellrowborder" valign="top" width="21.36%"><p id="p1770218431208"><a name="p1770218431208"></a><a name="p1770218431208"></a><strong id="b107021743132010"><a name="b107021743132010"></a><a name="b107021743132010"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p1170217432201"><a name="p1170217432201"></a><a name="p1170217432201"></a><strong id="b3702243202015"><a name="b3702243202015"></a><a name="b3702243202015"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row1670212432206"><td class="cellrowborder" valign="top" width="21.36%"><p id="p77021543152017"><a name="p77021543152017"></a><a name="p77021543152017"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p770214310209"><a name="p770214310209"></a><a name="p770214310209"></a>操作成功</p>
</td>
</tr>
<tr id="row10702194313201"><td class="cellrowborder" valign="top" width="21.36%"><p id="p165182216306"><a name="p165182216306"></a><a name="p165182216306"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p651815219302"><a name="p651815219302"></a><a name="p651815219302"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -681,38 +358,17 @@ if (ret != 0) { ...@@ -681,38 +358,17 @@ if (ret != 0) {
复位RTC,复位RTC后各配置寄存器恢复默认值,可以通过以下函数完成: 复位RTC,复位RTC后各配置寄存器恢复默认值,可以通过以下函数完成:
int32\_t RtcReset\(DevHandle handle\); int32_t RtcReset(DevHandle handle);
**表 12** RtcReset参数和返回值描述 **表12** RtcReset参数和返回值描述
<a name="table398973152517"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row179899311254"><td class="cellrowborder" valign="top" width="21.36%"><p id="p199899314257"><a name="p199899314257"></a><a name="p199899314257"></a><strong id="b3989163192516"><a name="b3989163192516"></a><a name="b3989163192516"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.64%"><p id="p179897315257"><a name="p179897315257"></a><a name="p179897315257"></a><strong id="b16989193110252"><a name="b16989193110252"></a><a name="b16989193110252"></a>参数描述</strong></p> | **返回值** | **返回值描述** |
</td> | 0 | 操作成功 |
</tr> | 负数 | 操作失败 |
<tr id="row14989113118257"><td class="cellrowborder" valign="top" width="21.36%"><p id="p129018136436"><a name="p129018136436"></a><a name="p129018136436"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p290111304310"><a name="p290111304310"></a><a name="p290111304310"></a>RTC设备句柄</p>
</td>
</tr>
<tr id="row7989123111254"><td class="cellrowborder" valign="top" width="21.36%"><p id="p129894313251"><a name="p129894313251"></a><a name="p129894313251"></a><strong id="b7989931162516"><a name="b7989931162516"></a><a name="b7989931162516"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p799013112256"><a name="p799013112256"></a><a name="p799013112256"></a><strong id="b499053112519"><a name="b499053112519"></a><a name="b499053112519"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row9990193142513"><td class="cellrowborder" valign="top" width="21.36%"><p id="p1999043111257"><a name="p1999043111257"></a><a name="p1999043111257"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p1799093182516"><a name="p1799093182516"></a><a name="p1799093182516"></a>操作成功</p>
</td>
</tr>
<tr id="row16990133152516"><td class="cellrowborder" valign="top" width="21.36%"><p id="p17536173573015"><a name="p17536173573015"></a><a name="p17536173573015"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.64%"><p id="p1153623503014"><a name="p1153623503014"></a><a name="p1153623503014"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -728,48 +384,19 @@ if (ret != 0) { ...@@ -728,48 +384,19 @@ if (ret != 0) {
按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: 按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成:
int32\_t RtcReadReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t \*value\); int32_t RtcReadReg(DevHandle handle, uint8_t usrDefIndex, uint8_t \*value);
**表 13** RtcReadReg参数和返回值描述 **表13** RtcReadReg参数和返回值描述
<a name="table1624674153319"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row92469423320"><td class="cellrowborder" valign="top" width="21.62%"><p id="p102461548331"><a name="p102461548331"></a><a name="p102461548331"></a><strong id="b224610493313"><a name="b224610493313"></a><a name="b224610493313"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p15246847331"><a name="p15246847331"></a><a name="p15246847331"></a><strong id="b724612453315"><a name="b724612453315"></a><a name="b724612453315"></a>参数描述</strong></p> | usrDefIndex | 用户定义的寄存器对应索引 |
</td> | value | 寄存器值 |
</tr> | **返回值** | **返回值描述** |
<tr id="row171318200434"><td class="cellrowborder" valign="top" width="21.62%"><p id="p9895321184320"><a name="p9895321184320"></a><a name="p9895321184320"></a>handle</p> | 0 | 操作成功 |
</td> | 负数 | 操作失败 |
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p68951214436"><a name="p68951214436"></a><a name="p68951214436"></a>RTC设备句柄</p>
</td>
</tr>
<tr id="row324614143314"><td class="cellrowborder" valign="top" width="21.62%"><p id="p82466433320"><a name="p82466433320"></a><a name="p82466433320"></a>usrDefIndex</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p181671825470"><a name="p181671825470"></a><a name="p181671825470"></a>用户定义的寄存器对应索引</p>
</td>
</tr>
<tr id="row524716420334"><td class="cellrowborder" valign="top" width="21.62%"><p id="p8247844333"><a name="p8247844333"></a><a name="p8247844333"></a>value</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p524711413319"><a name="p524711413319"></a><a name="p524711413319"></a>寄存器值</p>
</td>
</tr>
<tr id="row112471143334"><td class="cellrowborder" valign="top" width="21.62%"><p id="p1124716483312"><a name="p1124716483312"></a><a name="p1124716483312"></a><strong id="b192476416337"><a name="b192476416337"></a><a name="b192476416337"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p1524716443313"><a name="p1524716443313"></a><a name="p1524716443313"></a><strong id="b72472473313"><a name="b72472473313"></a><a name="b72472473313"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row9247194183314"><td class="cellrowborder" valign="top" width="21.62%"><p id="p62476410334"><a name="p62476410334"></a><a name="p62476410334"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p152471433317"><a name="p152471433317"></a><a name="p152471433317"></a>操作成功</p>
</td>
</tr>
<tr id="row1424719410333"><td class="cellrowborder" valign="top" width="21.62%"><p id="p112477417335"><a name="p112477417335"></a><a name="p112477417335"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p7247547338"><a name="p7247547338"></a><a name="p7247547338"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -787,48 +414,19 @@ if (ret != 0) { ...@@ -787,48 +414,19 @@ if (ret != 0) {
按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: 按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成:
int32\_t RtcWriteReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t value\); int32_t RtcWriteReg(DevHandle handle, uint8_t usrDefIndex, uint8_t value);
**表 14** RtcWriteReg参数和返回值描述 **表14** RtcWriteReg参数和返回值描述
<a name="table1072216482360"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row187221648133611"><td class="cellrowborder" valign="top" width="21.62%"><p id="p2722184823617"><a name="p2722184823617"></a><a name="p2722184823617"></a><strong id="b18723134883614"><a name="b18723134883614"></a><a name="b18723134883614"></a>参数</strong></p> | -------- | -------- |
</td> | handle | RTC设备句柄 |
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p1372374810367"><a name="p1372374810367"></a><a name="p1372374810367"></a><strong id="b147230481369"><a name="b147230481369"></a><a name="b147230481369"></a>参数描述</strong></p> | usrDefIndex | 用户定义的寄存器对应索引 |
</td> | value | 寄存器值 |
</tr> | **返回值** | **返回值描述** |
<tr id="row1675092612435"><td class="cellrowborder" valign="top" width="21.62%"><p id="p7783927144312"><a name="p7783927144312"></a><a name="p7783927144312"></a>handle</p> | 0 | 操作成功 |
</td> | 负数 | 操作失败 |
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p197831427134310"><a name="p197831427134310"></a><a name="p197831427134310"></a>RTC设备句柄</p>
</td>
</tr>
<tr id="row1723174815367"><td class="cellrowborder" valign="top" width="21.62%"><p id="p1972364814366"><a name="p1972364814366"></a><a name="p1972364814366"></a>usrDefIndex</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p18723184819365"><a name="p18723184819365"></a><a name="p18723184819365"></a>用户定义的寄存器对应索引</p>
</td>
</tr>
<tr id="row2723548163611"><td class="cellrowborder" valign="top" width="21.62%"><p id="p1772364893610"><a name="p1772364893610"></a><a name="p1772364893610"></a>value</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p1772324803619"><a name="p1772324803619"></a><a name="p1772324803619"></a>寄存器值</p>
</td>
</tr>
<tr id="row1072314482361"><td class="cellrowborder" valign="top" width="21.62%"><p id="p6723194853618"><a name="p6723194853618"></a><a name="p6723194853618"></a><strong id="b14723194863611"><a name="b14723194863611"></a><a name="b14723194863611"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p1872314893614"><a name="p1872314893614"></a><a name="p1872314893614"></a><strong id="b8723154812365"><a name="b8723154812365"></a><a name="b8723154812365"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row20723148173617"><td class="cellrowborder" valign="top" width="21.62%"><p id="p12723348133615"><a name="p12723348133615"></a><a name="p12723348133615"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p472324873620"><a name="p472324873620"></a><a name="p472324873620"></a>操作成功</p>
</td>
</tr>
<tr id="row127231848123615"><td class="cellrowborder" valign="top" width="21.62%"><p id="p197231148173613"><a name="p197231148173613"></a><a name="p197231148173613"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="78.38000000000001%"><p id="p16723134823618"><a name="p16723134823618"></a><a name="p16723134823618"></a>操作失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -842,17 +440,22 @@ if (ret != 0) { ...@@ -842,17 +440,22 @@ if (ret != 0) {
} }
``` ```
## 使用实例<a name="section1186111020456"></a>
## 使用实例
本实例提供RTC接口的完整使用流程: 本实例提供RTC接口的完整使用流程:
1. 系统启动,驱动管理模块会识别系统当前的RTC器件; 1. 系统启动,驱动管理模块会识别系统当前的RTC器件;
2. 驱动管理模块完成RTC设备的初始化和设备创建; 2. 驱动管理模块完成RTC设备的初始化和设备创建;
3. 用户通过不同API,对该RTC设备进行对应的操作; 3. 用户通过不同API,对该RTC设备进行对应的操作;
4. 关闭RTC设备,释放设备资源。 4. 关闭RTC设备,释放设备资源。
示例如下: 示例如下:
``` ```
#include "rtc_if.h" #include "rtc_if.h"
int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex)
...@@ -938,4 +541,3 @@ void RtcTestSample(void) ...@@ -938,4 +541,3 @@ void RtcTestSample(void)
RtcClose(handle); RtcClose(handle);
} }
``` ```
# RTC<a name="ZH-CN_TOPIC_0000001176922448"></a> # RTC
- [概述](#section509989381142407)
- [接口说明](#section752964871810)
- [开发步骤](#section1784450860142407)
- [开发实例](#section1594883301142407)
## 概述<a name="section509989381142407"></a> ## 概述
RTC\(real-time clock\)为操作系统中的实时时钟设备,在HDF框架中,RTC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 RTC(real-time clock)为操作系统中的实时时钟设备,在HDF框架中,RTC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
**图 1** RTC独立服务模式结构图<a name="fig6742142611299"></a> **图1** RTC独立服务模式结构图
![](figures/独立服务模式结构图.png "RTC独立服务模式结构图")
## 接口说明<a name="section752964871810"></a> ![zh-cn_image_0000001177082386](figures/zh-cn_image_0000001177082386.png)
## 接口说明
RtcMethod定义: RtcMethod定义:
``` ```
struct RtcMethod { struct RtcMethod {
int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time); int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time);
...@@ -32,176 +31,50 @@ struct RtcMethod { ...@@ -32,176 +31,50 @@ struct RtcMethod {
}; };
``` ```
**表 1** RtcMethod结构体成员的回调函数功能说明 **表1** RtcMethod结构体成员的回调函数功能说明
<a name="table12929217311"></a> | 函数 | 入参 | 出参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row293621203111"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p15932212314"><a name="p15932212314"></a><a name="p15932212314"></a>函数</p> | -------- | -------- | -------- | -------- | -------- |
</th> | ReadTime | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;; | time:&nbsp;结构体指针,传出的时间值; | HDF_STATUS相关状态 | 读RTC时间信息 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p1193421113111"><a name="p1193421113111"></a><a name="p1193421113111"></a>入参</p> | WriteTime | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;;time:&nbsp;结构体指针,时间传入值; | 无 | HDF_STATUS相关状态 | 写RTC时间信息(包括毫秒~年) |
</th> | ReadAlarm | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;;alarmIndex:&nbsp;枚举值,闹钟报警索引&nbsp;; | time:&nbsp;结构体指针,传出的时间值; | HDF_STATUS相关状态 | 读RTC报警时间信息 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p179312214317"><a name="p179312214317"></a><a name="p179312214317"></a>出参</p> | WriteAlarm | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;;alarmIndex:&nbsp;枚举值,闹钟报警索引&nbsp;;time:&nbsp;结构体指针,时间传入值; | 无 | HDF_STATUS相关状态 | 写RTC报警时间信息 |
</th> | RegisterAlarmCallback | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;;alarmIndex:&nbsp;枚举值,闹钟报警索引&nbsp;;cb:函数指针,回调函数; | 无 | HDF_STATUS相关状态 | 注册报警超时回调函数 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p993521163113"><a name="p993521163113"></a><a name="p993521163113"></a>返回值</p> | AlarmInterruptEnable | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;;alarmIndex:&nbsp;枚举值,闹钟报警索引&nbsp;;enable:&nbsp;布尔值,控制报警; | 无 | HDF_STATUS相关状态 | 使能/去使能RTC报警中断 |
</th> | GetFreq | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;; | freq:&nbsp;uint32_t指针,传出的频率值; | HDF_STATUS相关状态 | 读RTC外接晶振频率 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p5931821123115"><a name="p5931821123115"></a><a name="p5931821123115"></a>功能</p> | SetFreq | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;;freq:&nbsp;uint32_t,频率传入值; | 无 | HDF_STATUS相关状态 | 配置RTC外接晶振频率 |
</th> | Reset | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;; | 无 | HDF_STATUS相关状态 | RTC复位 |
</tr> | ReadReg | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;;usrDefIndex:&nbsp;结构体,用户自定义寄存器索引; | value:&nbsp;uint8_t指针,传出的寄存器值; | HDF_STATUS相关状态 | 按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值 |
</thead> | WriteReg | host:&nbsp;结构体指针,核心层RTC控制器&nbsp;;usrDefIndex:&nbsp;结构体,用户自定义寄存器索引;value:&nbsp;uint8_t,寄存器传入值; | 无 | HDF_STATUS相关状态 | 按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值 |
<tbody><tr id="row1093521113114"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p14941421163112"><a name="p14941421163112"></a><a name="p14941421163112"></a>ReadTime</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p094112118314"><a name="p094112118314"></a><a name="p094112118314"></a>host: 结构体指针,核心层RTC控制器 ;</p> ## 开发步骤
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p19945219318"><a name="p19945219318"></a><a name="p19945219318"></a>time: 结构体指针,传出的时间值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p20941021143120"><a name="p20941021143120"></a><a name="p20941021143120"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p094132115317"><a name="p094132115317"></a><a name="p094132115317"></a>读RTC时间信息</p>
</td>
</tr>
<tr id="row199472183111"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p69418214318"><a name="p69418214318"></a><a name="p69418214318"></a>WriteTime</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p89418214311"><a name="p89418214311"></a><a name="p89418214311"></a>host: 结构体指针,核心层RTC控制器 ;time: 结构体指针,时间传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p3944214314"><a name="p3944214314"></a><a name="p3944214314"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1194321113112"><a name="p1194321113112"></a><a name="p1194321113112"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p5941521123118"><a name="p5941521123118"></a><a name="p5941521123118"></a>写RTC时间信息(包括毫秒~年)</p>
</td>
</tr>
<tr id="row4941521113111"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p19462119319"><a name="p19462119319"></a><a name="p19462119319"></a>ReadAlarm</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p9951721113113"><a name="p9951721113113"></a><a name="p9951721113113"></a>host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1995921113112"><a name="p1995921113112"></a><a name="p1995921113112"></a>time: 结构体指针,传出的时间值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p10951721133115"><a name="p10951721133115"></a><a name="p10951721133115"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p14951121193113"><a name="p14951121193113"></a><a name="p14951121193113"></a>读RTC报警时间信息</p>
</td>
</tr>
<tr id="row6957211313"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p129517219311"><a name="p129517219311"></a><a name="p129517219311"></a>WriteAlarm</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p595152114315"><a name="p595152114315"></a><a name="p595152114315"></a>host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;time: 结构体指针,时间传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p16951321203115"><a name="p16951321203115"></a><a name="p16951321203115"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p195321113116"><a name="p195321113116"></a><a name="p195321113116"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1095122163116"><a name="p1095122163116"></a><a name="p1095122163116"></a>写RTC报警时间信息</p>
</td>
</tr>
<tr id="row1495021173112"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p795421193118"><a name="p795421193118"></a><a name="p795421193118"></a>RegisterAlarmCallback</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1295182163112"><a name="p1295182163112"></a><a name="p1295182163112"></a>host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;cb:函数指针,回调函数;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p79582123118"><a name="p79582123118"></a><a name="p79582123118"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1996122173116"><a name="p1996122173116"></a><a name="p1996122173116"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p39602133113"><a name="p39602133113"></a><a name="p39602133113"></a>注册报警超时回调函数</p>
</td>
</tr>
<tr id="row6961321113110"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p129682193119"><a name="p129682193119"></a><a name="p129682193119"></a>AlarmInterruptEnable</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p59682173112"><a name="p59682173112"></a><a name="p59682173112"></a>host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;enable: 布尔值,控制报警;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p5962021123110"><a name="p5962021123110"></a><a name="p5962021123110"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p16961621143119"><a name="p16961621143119"></a><a name="p16961621143119"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p996182112316"><a name="p996182112316"></a><a name="p996182112316"></a>使能/去使能RTC报警中断</p>
</td>
</tr>
<tr id="row199622114317"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p09615216315"><a name="p09615216315"></a><a name="p09615216315"></a>GetFreq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p16961021103119"><a name="p16961021103119"></a><a name="p16961021103119"></a>host: 结构体指针,核心层RTC控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p09620218318"><a name="p09620218318"></a><a name="p09620218318"></a>freq: uint32_t指针,传出的频率值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p15961121163111"><a name="p15961121163111"></a><a name="p15961121163111"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p3968214311"><a name="p3968214311"></a><a name="p3968214311"></a>读RTC外接晶振频率</p>
</td>
</tr>
<tr id="row29692120319"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1296421103115"><a name="p1296421103115"></a><a name="p1296421103115"></a>SetFreq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p79792114315"><a name="p79792114315"></a><a name="p79792114315"></a>host: 结构体指针,核心层RTC控制器 ;freq: uint32_t,频率传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p4971021103118"><a name="p4971021103118"></a><a name="p4971021103118"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p109772117315"><a name="p109772117315"></a><a name="p109772117315"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p11971621193115"><a name="p11971621193115"></a><a name="p11971621193115"></a>配置RTC外接晶振频率</p>
</td>
</tr>
<tr id="row1697112123114"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p99712117318"><a name="p99712117318"></a><a name="p99712117318"></a>Reset</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p169712123111"><a name="p169712123111"></a><a name="p169712123111"></a>host: 结构体指针,核心层RTC控制器 ;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p3974213312"><a name="p3974213312"></a><a name="p3974213312"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p109718210315"><a name="p109718210315"></a><a name="p109718210315"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p197112116316"><a name="p197112116316"></a><a name="p197112116316"></a>RTC复位</p>
</td>
</tr>
<tr id="row3971821103115"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p2971221173111"><a name="p2971221173111"></a><a name="p2971221173111"></a>ReadReg</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p18975210312"><a name="p18975210312"></a><a name="p18975210312"></a>host: 结构体指针,核心层RTC控制器 ;usrDefIndex: 结构体,用户自定义寄存器索引;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p14975211314"><a name="p14975211314"></a><a name="p14975211314"></a>value: uint8_t指针,传出的寄存器值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p15981221193114"><a name="p15981221193114"></a><a name="p15981221193114"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1098821143115"><a name="p1098821143115"></a><a name="p1098821143115"></a>按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值</p>
</td>
</tr>
<tr id="row1298102119313"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p598121153114"><a name="p598121153114"></a><a name="p598121153114"></a>WriteReg</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1498172173115"><a name="p1498172173115"></a><a name="p1498172173115"></a>host: 结构体指针,核心层RTC控制器 ;usrDefIndex: 结构体,用户自定义寄存器索引;value: uint8_t,寄存器传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1998162193110"><a name="p1998162193110"></a><a name="p1998162193110"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p198162173118"><a name="p198162173118"></a><a name="p198162173118"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p13981421203110"><a name="p13981421203110"></a><a name="p13981421203110"></a>按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section1784450860142407"></a>
RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加rtc\_config.hcs器件属性文件。 - 【可选】添加rtc_config.hcs器件属性文件。
3. **实例化RTC控制器对象:** 3. **实例化RTC控制器对象:**
- 初始化RtcHost成员。 - 初始化RtcHost成员。
- 实例化RtcHost成员RtcMethod。 - 实例化RtcHost成员RtcMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化RtcHost成员RtcMethod,其定义和成员说明见[接口说明](#接口说明)。
>实例化RtcHost成员RtcMethod,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如RTC控制状态,中断响应情况等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如RTC控制状态,中断响应情况等。
## 开发实例<a name="section1594883301142407"></a> ## 开发实例
下方将以rtc\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以rtc_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
RTC驱动入口参考: RTC驱动入口参考:
...@@ -218,11 +91,10 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -218,11 +91,10 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
HDF_INIT(g_rtcDriverEntry); HDF_INIT(g_rtcDriverEntry);
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 rtc\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层RtcHost成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 rtc_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层RtcHost成员的默认值或限制范围有密切关系。
本例只有一个RTC控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在rtc_config文件中增加对应的器件属性。
本例只有一个RTC控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在rtc\_config文件中增加对应的器件属性 - device_info.hcs 配置参考
- device\_info.hcs 配置参考。
``` ```
root { root {
...@@ -243,7 +115,8 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -243,7 +115,8 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
} }
``` ```
- rtc\_config.hcs 配置参考。 - rtc_config.hcs 配置参考。
``` ```
root { root {
...@@ -270,7 +143,8 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -270,7 +143,8 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
3. 完成驱动入口注册之后,最后一步就是以核心层RtcHost对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化RtcHost成员RtcMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层RtcHost对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化RtcHost成员RtcMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考。 - 自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且rtc\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员。 从驱动的角度看,自定义结构体是参数和数据的载体,而且rtc_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员。
``` ```
struct RtcConfigInfo { struct RtcConfigInfo {
...@@ -295,9 +169,9 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -295,9 +169,9 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
void *data; void *data;
}; };
``` ```
- RtcHost成员回调函数结构体RtcMethod的实例化,其他成员在Init函数中初始化。 - RtcHost成员回调函数结构体RtcMethod的实例化,其他成员在Init函数中初始化。
``` ```
// rtc_hi35xx.c 中的示例:钩子函数的填充 // rtc_hi35xx.c 中的示例:钩子函数的填充
static struct RtcMethod g_method = { static struct RtcMethod g_method = {
...@@ -323,54 +197,24 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -323,54 +197,24 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
返回值: 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
**表 2** Bind 函数入参及返回值对照表 **表2** Bind 函数入参及返回值对照表
<a name="table14285177465"></a> | 状态(值) | 问题描述 |
<table><thead align="left"><tr id="row6280177461"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p528181764613"><a name="p528181764613"></a><a name="p528181764613"></a>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p192891754615"><a name="p192891754615"></a><a name="p192891754615"></a>问题描述</p> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</th> | HDF_ERR_INVALID_PARAM | 参数非法 |
</tr> | HDF_ERR_IO | I/O&nbsp;错误 |
</thead> | HDF_SUCCESS | 初始化成功 |
<tbody><tr id="row1328191713465"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p02812173467"><a name="p02812173467"></a><a name="p02812173467"></a>HDF_ERR_INVALID_OBJECT</p> | HDF_FAILURE | 初始化失败 |
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p142861714610"><a name="p142861714610"></a><a name="p142861714610"></a>控制器对象非法</p>
</td>
</tr>
<tr id="row19288170464"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16282017184619"><a name="p16282017184619"></a><a name="p16282017184619"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p02841754611"><a name="p02841754611"></a><a name="p02841754611"></a>内存分配失败</p>
</td>
</tr>
<tr id="row229131734619"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p429171784617"><a name="p429171784617"></a><a name="p429171784617"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1229151764617"><a name="p1229151764617"></a><a name="p1229151764617"></a>参数非法</p>
</td>
</tr>
<tr id="row6291017154612"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p15294179461"><a name="p15294179461"></a><a name="p15294179461"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p329517154617"><a name="p329517154617"></a><a name="p329517154617"></a>I/O 错误</p>
</td>
</tr>
<tr id="row9298171469"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p13297172461"><a name="p13297172461"></a><a name="p13297172461"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p11299171460"><a name="p11299171460"></a><a name="p11299171460"></a>初始化成功</p>
</td>
</tr>
<tr id="row122911175467"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p32931744612"><a name="p32931744612"></a><a name="p32931744612"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p102911724610"><a name="p102911724610"></a><a name="p102911724610"></a>初始化失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
关联HdfDeviceObject对象和RtcHost。 关联HdfDeviceObject对象和RtcHost。
``` ```
static int32_t HiRtcBind(struct HdfDeviceObject *device) static int32_t HiRtcBind(struct HdfDeviceObject *device)
{ {
...@@ -386,18 +230,19 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -386,18 +230,19 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
- Init函数参考 - Init函数参考
入参**:** 入参:
HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。
返回值**:** 返回值:
HDF\_STATUS相关状态。 HDF_STATUS相关状态。
函数说明: 函数说明:
初始化自定义结构体对象,初始化RtcHost成员。 初始化自定义结构体对象,初始化RtcHost成员。
``` ```
static int32_t HiRtcInit(struct HdfDeviceObject *device) static int32_t HiRtcInit(struct HdfDeviceObject *device)
{ {
...@@ -425,14 +270,13 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -425,14 +270,13 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
- Release 函数参考 - Release 函数参考
入参**:** 入参:
HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。
返回值**:** 返回值:
无。 无。
...@@ -440,6 +284,7 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -440,6 +284,7 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作前提是在Init或Bind函数中具备对应赋值的操作。 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作前提是在Init或Bind函数中具备对应赋值的操作。
``` ```
static void HiRtcRelease(struct HdfDeviceObject *device) static void HiRtcRelease(struct HdfDeviceObject *device)
{ {
...@@ -456,6 +301,3 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -456,6 +301,3 @@ RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动
RtcHostDestroy(host); //释放RtcHost RtcHostDestroy(host); //释放RtcHost
} }
``` ```
# SDIO<a name="ZH-CN_TOPIC_0000001160653028"></a> # SDIO
- [概述](#section1155271783811)
- [接口说明](#section12601496259) ## 概述
- [使用指导](#section1878939192515)
- [使用流程](#section1490685512255)
- [打开SDIO控制器](#section10782428132616)
- [独占HOST](#section11263172312715)
- [使能SDIO设备](#section17861486271)
- [注册SDIO中断](#section521213262286)
- [进行SDIO通信](#section85661522153420)
- [释放SDIO中断](#section1683449352)
- [去使能SDIO设备](#section15379324143611)
- [释放HOST](#section536018263713)
- [关闭SDIO控制器](#section4752739183716)
- [使用实例](#section376910122382)
## 概述<a name="section1155271783811"></a>
- SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD内存卡,并且可以连接支持SDIO接口的设备。 - SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD内存卡,并且可以连接支持SDIO接口的设备。
- SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。 - SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。
- SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如下图所示:
- SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如下图所示:
- CLK信号:HOST给DEVICE的时钟信号。 - CLK信号:HOST给DEVICE的时钟信号。
- VDD信号:电源信号。 - VDD信号:电源信号。
- VSS信号:Ground信号。 - VSS信号:Ground信号。
- D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。 - D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。
- CMD信号:用于HOST发送命令和DEVICE回复响应。 - CMD信号:用于HOST发送命令和DEVICE回复响应。
**图 1** SDIO的HOST-DEVICE连接示意图<a name="fig1895112631810"></a> **图1** SDIO的HOST-DEVICE连接示意图
![](figures/SDIO的HOST-DEVICE连接示意图.png "SDIO的HOST-DEVICE连接示意图")
![zh-cn_image_0000001206092987](figures/zh-cn_image_0000001206092987.png)
- SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。 - SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。
## 接口说明<a name="section12601496259"></a>
## 接口说明
**表 1** SDIO驱动API接口功能介绍
**表1** SDIO驱动API接口功能介绍
<a name="table1731550155318"></a>
<table><thead align="left"><tr id="row1625342317507"><th class="cellrowborder" valign="top" width="21.07%" id="mcps1.2.4.1.1"><p id="p1779183435016"><a name="p1779183435016"></a><a name="p1779183435016"></a>功能分类</p> | 功能分类 | 接口描述 |
</th> | -------- | -------- |
<th class="cellrowborder" valign="top" width="34.04%" id="mcps1.2.4.1.2"><p id="p1879163417502"><a name="p1879163417502"></a><a name="p1879163417502"></a>接口名</p> | SDIO设备打开/关闭接口 | -&nbsp;SdioOpen:打开指定总线号的SDIO控制器<br/>-&nbsp;SdioClose:关闭SDIO控制器 |
</th> | SDIO读写接口 | -&nbsp;SdioReadBytes:从指定地址开始,增量读取指定长度的数据<br/>-&nbsp;SdioWriteBytes:从指定地址开始,增量写入指定长度的数据<br/>-&nbsp;SdioReadBytesFromFixedAddr:从固定地址读取指定长度的数据<br/>-&nbsp;SdioWriteBytesToFixedAddr:向固定地址写入指定长度的数据<br/>-&nbsp;SdioReadBytesFromFunc0:从SDIO&nbsp;function&nbsp;0的指定地址空间读取指定长度的数据<br/>-&nbsp;SdioWriteBytesToFunc0:向SDIO&nbsp;function&nbsp;0的指定地址空间写入指定长度的数据 |
<th class="cellrowborder" valign="top" width="44.89%" id="mcps1.2.4.1.3"><p id="p1379113410506"><a name="p1379113410506"></a><a name="p1379113410506"></a>描述</p> | SDIO设置块大小接口 | SdioSetBlockSize:设置块的大小 |
</th> | SDIO获取/设置公共信息接口 | -&nbsp;SdioGetCommonInfo:获取公共信息<br/>-&nbsp;SdioSetCommonInfo:设置公共信息 |
</tr> | SDIO刷新数据接口 | SdioFlushData:刷新数据 |
</thead> | SDIO独占/释放HOST接口 | -&nbsp;SdioClaimHost:独占Host<br/>-&nbsp;SdioReleaseHost:释放Host |
<tbody><tr id="row1351945135614"><td class="cellrowborder" rowspan="2" valign="top" width="21.07%" headers="mcps1.2.4.1.1 "><p id="p146755118566"><a name="p146755118566"></a><a name="p146755118566"></a>SDIO设备打开/关闭接口</p> | SDIO使能/去使能功能设备接口 | -&nbsp;SdioEnableFunc:使能SDIO功能设备<br/>-&nbsp;SdioDisableFunc:去使能SDIO功能设备 |
</td> | SDIO申请/释放中断接口 | -&nbsp;SdioClaimIrq:申请中断<br/>-&nbsp;SdioReleaseIrq:释放中断 |
<td class="cellrowborder" valign="top" width="34.04%" headers="mcps1.2.4.1.2 "><p id="p1151945185614"><a name="p1151945185614"></a><a name="p1151945185614"></a>SdioOpen</p>
</td> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
<td class="cellrowborder" valign="top" width="44.89%" headers="mcps1.2.4.1.3 "><p id="p85110451565"><a name="p85110451565"></a><a name="p85110451565"></a>打开指定总线号的SDIO控制器</p> > 本文涉及的所有接口,目前只支持在内核态使用,不支持在用户态使用。
</td>
</tr>
<tr id="row1062610995616"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p136261793568"><a name="p136261793568"></a><a name="p136261793568"></a>SdioClose</p> ## 使用指导
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p062614919566"><a name="p062614919566"></a><a name="p062614919566"></a>关闭SDIO控制器</p>
</td> ### 使用流程
</tr>
<tr id="row337105133315"><td class="cellrowborder" rowspan="6" valign="top" width="21.07%" headers="mcps1.2.4.1.1 "><p id="p07631557153319"><a name="p07631557153319"></a><a name="p07631557153319"></a>SDIO读写接口</p> 使用SDIO的一般流程如下图所示。
</td>
<td class="cellrowborder" valign="top" width="34.04%" headers="mcps1.2.4.1.2 "><p id="p34551320121416"><a name="p34551320121416"></a><a name="p34551320121416"></a>SdioReadBytes</p> **图2** SDIO使用流程图
</td>
<td class="cellrowborder" valign="top" width="44.89%" headers="mcps1.2.4.1.3 "><p id="p748062291415"><a name="p748062291415"></a><a name="p748062291415"></a>从指定地址开始,增量读取指定长度的数据</p> ![zh-cn_image_0000001206171539](figures/zh-cn_image_0000001206171539.png)
</td>
</tr>
<tr id="row9317134301618"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p10345104001412"><a name="p10345104001412"></a><a name="p10345104001412"></a>SdioWriteBytes</p> ### 打开SDIO控制器
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p113452040141418"><a name="p113452040141418"></a><a name="p113452040141418"></a>从指定地址开始,增量写入指定长度的数据</p>
</td>
</tr>
<tr id="row131301734171616"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p713025410166"><a name="p713025410166"></a><a name="p713025410166"></a>SdioReadBytesFromFixedAddr</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p14130165418168"><a name="p14130165418168"></a><a name="p14130165418168"></a>从固定地址读取指定长度的数据</p>
</td>
</tr>
<tr id="row1434434011147"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1913013546161"><a name="p1913013546161"></a><a name="p1913013546161"></a>SdioWriteBytesToFixedAddr</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p111301954131614"><a name="p111301954131614"></a><a name="p111301954131614"></a>向固定地址写入指定长度的数据</p>
</td>
</tr>
<tr id="row364393591410"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1851815711620"><a name="p1851815711620"></a><a name="p1851815711620"></a>SdioReadBytesFromFunc0</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p751875761611"><a name="p751875761611"></a><a name="p751875761611"></a>从SDIO function 0的指定地址空间读取指定长度的数据</p>
</td>
</tr>
<tr id="row17455333175"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1645519318173"><a name="p1645519318173"></a><a name="p1645519318173"></a>SdioWriteBytesToFunc0</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p114552320176"><a name="p114552320176"></a><a name="p114552320176"></a>向SDIO function 0的指定地址空间写入指定长度的数据</p>
</td>
</tr>
<tr id="row34145016535"><td class="cellrowborder" valign="top" width="21.07%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>SDIO设置块大小接口</p>
</td>
<td class="cellrowborder" valign="top" width="34.04%" headers="mcps1.2.4.1.2 "><p id="p74531720181413"><a name="p74531720181413"></a><a name="p74531720181413"></a>SdioSetBlockSize</p>
</td>
<td class="cellrowborder" valign="top" width="44.89%" headers="mcps1.2.4.1.3 "><p id="p247972241411"><a name="p247972241411"></a><a name="p247972241411"></a>设置块的大小</p>
</td>
</tr>
<tr id="row778816813238"><td class="cellrowborder" rowspan="2" valign="top" width="21.07%" headers="mcps1.2.4.1.1 "><p id="p1578958142317"><a name="p1578958142317"></a><a name="p1578958142317"></a>SDIO获取/设置公共信息接口</p>
</td>
<td class="cellrowborder" valign="top" width="34.04%" headers="mcps1.2.4.1.2 "><p id="p378918842311"><a name="p378918842311"></a><a name="p378918842311"></a>SdioGetCommonInfo</p>
</td>
<td class="cellrowborder" valign="top" width="44.89%" headers="mcps1.2.4.1.3 "><p id="p1078919892313"><a name="p1078919892313"></a><a name="p1078919892313"></a>获取公共信息</p>
</td>
</tr>
<tr id="row5667102342417"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p2668623182411"><a name="p2668623182411"></a><a name="p2668623182411"></a>SdioSetCommonInfo</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p14668192362419"><a name="p14668192362419"></a><a name="p14668192362419"></a>设置公共信息</p>
</td>
</tr>
<tr id="row1165101111256"><td class="cellrowborder" valign="top" width="21.07%" headers="mcps1.2.4.1.1 "><p id="p8166161192511"><a name="p8166161192511"></a><a name="p8166161192511"></a>SDIO刷新数据接口</p>
</td>
<td class="cellrowborder" valign="top" width="34.04%" headers="mcps1.2.4.1.2 "><p id="p121662112256"><a name="p121662112256"></a><a name="p121662112256"></a>SdioFlushData</p>
</td>
<td class="cellrowborder" valign="top" width="44.89%" headers="mcps1.2.4.1.3 "><p id="p171661711112519"><a name="p171661711112519"></a><a name="p171661711112519"></a>刷新数据</p>
</td>
</tr>
<tr id="row17388101522515"><td class="cellrowborder" rowspan="2" valign="top" width="21.07%" headers="mcps1.2.4.1.1 "><p id="p53101413268"><a name="p53101413268"></a><a name="p53101413268"></a>SDIO独占/释放HOST接口</p>
</td>
<td class="cellrowborder" valign="top" width="34.04%" headers="mcps1.2.4.1.2 "><p id="p1638881562520"><a name="p1638881562520"></a><a name="p1638881562520"></a>SdioClaimHost</p>
</td>
<td class="cellrowborder" valign="top" width="44.89%" headers="mcps1.2.4.1.3 "><p id="p143881715152517"><a name="p143881715152517"></a><a name="p143881715152517"></a>独占Host</p>
</td>
</tr>
<tr id="row5352175517251"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p93537557259"><a name="p93537557259"></a><a name="p93537557259"></a>SdioReleaseHost</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1235355511254"><a name="p1235355511254"></a><a name="p1235355511254"></a>释放Host</p>
</td>
</tr>
<tr id="row8759125415269"><td class="cellrowborder" rowspan="2" valign="top" width="21.07%" headers="mcps1.2.4.1.1 "><p id="p272143815359"><a name="p272143815359"></a><a name="p272143815359"></a>SDIO使能/去使能功能设备接口</p>
</td>
<td class="cellrowborder" valign="top" width="34.04%" headers="mcps1.2.4.1.2 "><p id="p6760195452615"><a name="p6760195452615"></a><a name="p6760195452615"></a>SdioEnableFunc</p>
</td>
<td class="cellrowborder" valign="top" width="44.89%" headers="mcps1.2.4.1.3 "><p id="p9760135417263"><a name="p9760135417263"></a><a name="p9760135417263"></a>使能SDIO功能设备</p>
</td>
</tr>
<tr id="row1166105762620"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p5662175782616"><a name="p5662175782616"></a><a name="p5662175782616"></a>SdioDisableFunc</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p3662135722618"><a name="p3662135722618"></a><a name="p3662135722618"></a>去使能SDIO功能设备</p>
</td>
</tr>
<tr id="row12332331113517"><td class="cellrowborder" rowspan="2" valign="top" width="21.07%" headers="mcps1.2.4.1.1 "><p id="p188181849203614"><a name="p188181849203614"></a><a name="p188181849203614"></a>SDIO申请/释放中断接口</p>
</td>
<td class="cellrowborder" valign="top" width="34.04%" headers="mcps1.2.4.1.2 "><p id="p933383133517"><a name="p933383133517"></a><a name="p933383133517"></a>SdioClaimIrq</p>
</td>
<td class="cellrowborder" valign="top" width="44.89%" headers="mcps1.2.4.1.3 "><p id="p20333431203510"><a name="p20333431203510"></a><a name="p20333431203510"></a>申请中断</p>
</td>
</tr>
<tr id="row173103413357"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p2073123413515"><a name="p2073123413515"></a><a name="p2073123413515"></a>SdioReleaseIrq</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1773634153518"><a name="p1773634153518"></a><a name="p1773634153518"></a>释放中断</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,目前只支持在内核态使用,不支持在用户态使用。
## 使用指导<a name="section1878939192515"></a>
### 使用流程<a name="section1490685512255"></a>
使用SDIO的一般流程如[图2](#fig1969028202613)所示。
**图 2** SDIO使用流程图<a name="fig1969028202613"></a>
![](figures/SDIO使用流程图.png "SDIO使用流程图")
### 打开SDIO控制器<a name="section10782428132616"></a>
在使用SDIO进行通信前,首先要调用SdioOpen获取SDIO控制器的设备句柄,该函数会返回指定总线号的SDIO控制器的设备句柄。 在使用SDIO进行通信前,首先要调用SdioOpen获取SDIO控制器的设备句柄,该函数会返回指定总线号的SDIO控制器的设备句柄。
DevHandle SdioOpen\(int16\_t mmcBusNum, struct SdioFunctionConfig \*config\);
```
**表 2** SdioOpen函数的参数和返回值描述 DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig *config);
```
<a name="table1036944152712"></a>
<table><thead align="left"><tr id="row4370114192717"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p737074112720"><a name="p737074112720"></a><a name="p737074112720"></a>参数</p> **表2** SdioOpen函数的参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p15370154102716"><a name="p15370154102716"></a><a name="p15370154102716"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | mmcBusNum | 总线号 |
</thead> | config | SDIO功能配置信息 |
<tbody><tr id="row3370184112716"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p337094142715"><a name="p337094142715"></a><a name="p337094142715"></a>mmcBusNum</p> | **返回值** | **返回值描述** |
</td> | NULL | 获取SDIO控制器的设备句柄失败 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p8370154162718"><a name="p8370154162718"></a><a name="p8370154162718"></a>总线号</p> | 设备句柄 | SDIO控制器的设备句柄 |
</td>
</tr> 打开SDIO控制器的示例如下:
<tr id="row10370746272"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p23706402717"><a name="p23706402717"></a><a name="p23706402717"></a>config</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p153701492715"><a name="p153701492715"></a><a name="p153701492715"></a>SDIO功能配置信息</p>
</td>
</tr>
<tr id="row173703417274"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p183701349276"><a name="p183701349276"></a><a name="p183701349276"></a><strong id="b537017416272"><a name="b537017416272"></a><a name="b537017416272"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p203701647275"><a name="p203701647275"></a><a name="p203701647275"></a><strong id="b1370134122712"><a name="b1370134122712"></a><a name="b1370134122712"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row837016462716"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p937184172716"><a name="p937184172716"></a><a name="p937184172716"></a>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1837184182720"><a name="p1837184182720"></a><a name="p1837184182720"></a>获取SDIO控制器的设备句柄失败</p>
</td>
</tr>
<tr id="row737116492712"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p537174122715"><a name="p537174122715"></a><a name="p537174122715"></a>设备句柄</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p113715411274"><a name="p113715411274"></a><a name="p113715411274"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
</tbody>
</table>
打开SDIO控制器的示例如下:
``` ```
DevHandle handle = NULL; DevHandle handle = NULL;
...@@ -225,75 +86,51 @@ if (handle == NULL) { ...@@ -225,75 +86,51 @@ if (handle == NULL) {
} }
``` ```
### 独占HOST<a name="section11263172312715"></a>
### 独占HOST
获取到SDIO控制器的设备句柄之后,需要先独占HOST才能进行SDIO后续的一系列操作,独占HOST函数如下所示: 获取到SDIO控制器的设备句柄之后,需要先独占HOST才能进行SDIO后续的一系列操作,独占HOST函数如下所示:
void SdioClaimHost\(DevHandle handle\);
```
**表 3** SdioClaimHost函数的参数描述 void SdioClaimHost(DevHandle handle);
```
<a name="table192822447271"></a>
<table><thead align="left"><tr id="row192829443279"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1128284452713"><a name="p1128284452713"></a><a name="p1128284452713"></a>参数</p> **表3** SdioClaimHost函数的参数描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p1528264418272"><a name="p1528264418272"></a><a name="p1528264418272"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | SDIO控制器的设备句柄 |
</thead>
<tbody><tr id="row328264472711"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p15282124420274"><a name="p15282124420274"></a><a name="p15282124420274"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p0282164432719"><a name="p0282164432719"></a><a name="p0282164432719"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
</tbody>
</table>
独占HOST示例如下: 独占HOST示例如下:
``` ```
SdioClaimHost(handle); /* 独占HOST */ SdioClaimHost(handle); /* 独占HOST */
``` ```
### 使能SDIO设备<a name="section17861486271"></a>
### 使能SDIO设备
在访问寄存器之前,需要先使能SDIO设备,使能SDIO设备的函数如下所示: 在访问寄存器之前,需要先使能SDIO设备,使能SDIO设备的函数如下所示:
int32\_t SdioEnableFunc\(DevHandle handle\);
```
**表 4** SdioEnableFunc函数的参数和返回值描述 int32_t SdioEnableFunc(DevHandle handle);
```
<a name="table144881047485"></a>
<table><thead align="left"><tr id="row8487204184815"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1648611415486"><a name="p1648611415486"></a><a name="p1648611415486"></a>参数</p> **表4** SdioEnableFunc函数的参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p19487134124820"><a name="p19487134124820"></a><a name="p19487134124820"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | SDIO控制器的设备句柄 |
</thead> | **返回值** | **返回值描述** |
<tbody><tr id="row16487044480"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p74878414810"><a name="p74878414810"></a><a name="p74878414810"></a>handle</p> | 0 | SDIO使能成功 |
</td> | 负数 | SDIO使能失败 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17487184194819"><a name="p17487184194819"></a><a name="p17487184194819"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
<tr id="row13487748487"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p24873424811"><a name="p24873424811"></a><a name="p24873424811"></a><strong id="b348754124819"><a name="b348754124819"></a><a name="b348754124819"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p4487174134813"><a name="p4487174134813"></a><a name="p4487174134813"></a><strong id="b134877434810"><a name="b134877434810"></a><a name="b134877434810"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row1748814494812"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p84878410488"><a name="p84878410488"></a><a name="p84878410488"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p948715410483"><a name="p948715410483"></a><a name="p948715410483"></a>SDIO使能成功</p>
</td>
</tr>
<tr id="row54881416482"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p24881645489"><a name="p24881645489"></a><a name="p24881645489"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p10488247487"><a name="p10488247487"></a><a name="p10488247487"></a>SDIO使能失败</p>
</td>
</tr>
</tbody>
</table>
使能SDIO设备的示例如下: 使能SDIO设备的示例如下:
``` ```
int32_t ret; int32_t ret;
/* 使能SDIO设备 */ /* 使能SDIO设备 */
...@@ -303,50 +140,27 @@ if (ret != 0) { ...@@ -303,50 +140,27 @@ if (ret != 0) {
} }
``` ```
### 注册SDIO中断<a name="section521213262286"></a>
### 注册SDIO中断
在通信之前,还需要注册SDIO中断,注册SDIO中断函数如下图所示: 在通信之前,还需要注册SDIO中断,注册SDIO中断函数如下图所示:
int32\_t SdioClaimIrq\(DevHandle handle, SdioIrqHandler \*handler\);
```
**表 5** SdioClaimIrq函数的参数和返回值描述 int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler *handler);
```
<a name="table1149014114815"></a>
<table><thead align="left"><tr id="row114891042488"><th class="cellrowborder" valign="top" width="49.980000000000004%" id="mcps1.2.3.1.1"><p id="p1348864164811"><a name="p1348864164811"></a><a name="p1348864164811"></a>参数</p> **表5** SdioClaimIrq函数的参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50.019999999999996%" id="mcps1.2.3.1.2"><p id="p14885410486"><a name="p14885410486"></a><a name="p14885410486"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | SDIO控制器的设备句柄 |
</thead> | handler | 中断服务函数指针 |
<tbody><tr id="row048911404820"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p248974174814"><a name="p248974174814"></a><a name="p248974174814"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | 注册中断成功 |
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1848915494813"><a name="p1848915494813"></a><a name="p1848915494813"></a>SDIO控制器的设备句柄</p> | 负数 | 注册中断失败 |
</td>
</tr> 注册SDIO中的示例如下:
<tr id="row204894454813"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p17489944488"><a name="p17489944488"></a><a name="p17489944488"></a>handler</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1548984174813"><a name="p1548984174813"></a><a name="p1548984174813"></a>中断服务函数指针</p>
</td>
</tr>
<tr id="row44898413488"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p1548934124815"><a name="p1548934124815"></a><a name="p1548934124815"></a><strong id="b1448911410486"><a name="b1448911410486"></a><a name="b1448911410486"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p54891444485"><a name="p54891444485"></a><a name="p54891444485"></a><strong id="b13489104164810"><a name="b13489104164810"></a><a name="b13489104164810"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row748994144811"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p448918415484"><a name="p448918415484"></a><a name="p448918415484"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p174892412489"><a name="p174892412489"></a><a name="p174892412489"></a>注册中断成功</p>
</td>
</tr>
<tr id="row448914420489"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p248912464817"><a name="p248912464817"></a><a name="p248912464817"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p34891645485"><a name="p34891645485"></a><a name="p34891645485"></a>注册中断失败</p>
</td>
</tr>
</tbody>
</table>
注册SDIO中的示例如下:
``` ```
/* 中断服务函数需要根据各自平台的情况去实现 */ /* 中断服务函数需要根据各自平台的情况去实现 */
...@@ -367,200 +181,103 @@ if (ret != 0) { ...@@ -367,200 +181,103 @@ if (ret != 0) {
} }
``` ```
### 进行SDIO通信<a name="section85661522153420"></a>
### 进行SDIO通信
- 向SDIO设备增量写入指定长度的数据 - 向SDIO设备增量写入指定长度的数据
对应的接口函数如下所示: 对应的接口函数如下所示:
int32\_t SdioWriteBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**表 6** SdioWriteBytes函数的参数和返回值描述
<a name="table6887174174111"></a>
<table><thead align="left"><tr id="row10887144111419"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p181381751164113"><a name="p181381751164113"></a><a name="p181381751164113"></a>参数</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p19138115184116"><a name="p19138115184116"></a><a name="p19138115184116"></a>参数描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row4887341174114"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1534612017427"><a name="p1534612017427"></a><a name="p1534612017427"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p8179347434"><a name="p8179347434"></a><a name="p8179347434"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
<tr id="row18881041144120"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p10888154118412"><a name="p10888154118412"></a><a name="p10888154118412"></a>data</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1288854115413"><a name="p1288854115413"></a><a name="p1288854115413"></a>待写入数据的指针</p>
</td>
</tr>
<tr id="row191054911432"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p91054994311"><a name="p91054994311"></a><a name="p91054994311"></a>addr</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p111024915432"><a name="p111024915432"></a><a name="p111024915432"></a>待写入数据的起始地址</p>
</td>
</tr>
<tr id="row14888144124119"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1588814413412"><a name="p1588814413412"></a><a name="p1588814413412"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1288813411413"><a name="p1288813411413"></a><a name="p1288813411413"></a>待写入数据的长度</p>
</td>
</tr>
<tr id="row18247654163519"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p486155173610"><a name="p486155173610"></a><a name="p486155173610"></a><strong id="b169231220183618"><a name="b169231220183618"></a><a name="b169231220183618"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1686155113620"><a name="p1686155113620"></a><a name="p1686155113620"></a><strong id="b9924152013365"><a name="b9924152013365"></a><a name="b9924152013365"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row10574165663512"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p912141012364"><a name="p912141012364"></a><a name="p912141012364"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p51219107363"><a name="p51219107363"></a><a name="p51219107363"></a>SDIO写数据成功</p>
</td>
</tr>
<tr id="row1490635883519"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p10121510133617"><a name="p10121510133617"></a><a name="p10121510133617"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p131212106365"><a name="p131212106365"></a><a name="p131212106365"></a>SDIO写数据失败</p>
</td>
</tr>
</tbody>
</table>
向SDIO设备增量写入指定长度的数据的示例如下:
```
int32_t ret; ```
uint8_t wbuff[] = {1,2,3,4,5}; int32_t SdioWriteBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size);
uint32_t addr = 0x100 + 0x09; ```
/* 向SDIO设备起始地址0x109,增量写入5个字节的数据 */
ret = SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0])); **表6** SdioWriteBytes函数的参数和返回值描述
if (ret != 0) {
| 参数 | 参数描述 |
| -------- | -------- |
| handle | SDIO控制器的设备句柄 |
| data | 待写入数据的指针 |
| addr | 待写入数据的起始地址 |
| size | 待写入数据的长度 |
| **返回值** | **返回值描述** |
| 0 | SDIO写数据成功 |
| 负数 | SDIO写数据失败 |
向SDIO设备增量写入指定长度的数据的示例如下:
```
int32_t ret;
uint8_t wbuff[] = {1,2,3,4,5};
uint32_t addr = 0x100 + 0x09;
/* 向SDIO设备起始地址0x109,增量写入5个字节的数据 */
ret = SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]));
if (ret != 0) {
HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret);
} }
``` ```
- 从SDIO设备增量读取指定长度的数据 - 从SDIO设备增量读取指定长度的数据
对应的接口函数如下所示: 对应的接口函数如下所示:
int32\_t SdioReadBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**表 7** SdioReadBytes函数的参数和返回值描述
<a name="table5783755152110"></a>
<table><thead align="left"><tr id="row19783355162116"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p635754142212"><a name="p635754142212"></a><a name="p635754142212"></a>参数</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p1035774182215"><a name="p1035774182215"></a><a name="p1035774182215"></a>参数描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row137831055192118"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p14783155192114"><a name="p14783155192114"></a><a name="p14783155192114"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p9676437202218"><a name="p9676437202218"></a><a name="p9676437202218"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
<tr id="row4784155102111"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1978455510217"><a name="p1978455510217"></a><a name="p1978455510217"></a>data</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p767683714223"><a name="p767683714223"></a><a name="p767683714223"></a>接收读取数据的指针</p>
</td>
</tr>
<tr id="row63651118499"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p73669113496"><a name="p73669113496"></a><a name="p73669113496"></a>addr</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p53661144916"><a name="p53661144916"></a><a name="p53661144916"></a>待读取数据的起始地址</p>
</td>
</tr>
<tr id="row7784145510218"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1078413554219"><a name="p1078413554219"></a><a name="p1078413554219"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p14676163782210"><a name="p14676163782210"></a><a name="p14676163782210"></a>待读取数据的长度</p>
</td>
</tr>
<tr id="row964182643610"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7833639163612"><a name="p7833639163612"></a><a name="p7833639163612"></a><strong id="b122757566365"><a name="b122757566365"></a><a name="b122757566365"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p3833939113619"><a name="p3833939113619"></a><a name="p3833939113619"></a><strong id="b15276185619361"><a name="b15276185619361"></a><a name="b15276185619361"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row199479312363"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p567424413611"><a name="p567424413611"></a><a name="p567424413611"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p166741544113615"><a name="p166741544113615"></a><a name="p166741544113615"></a>SDIO读数据成功</p>
</td>
</tr>
<tr id="row5166203418361"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1167416448361"><a name="p1167416448361"></a><a name="p1167416448361"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p9674114410364"><a name="p9674114410364"></a><a name="p9674114410364"></a>SDIO读数据失败</p>
</td>
</tr>
</tbody>
</table>
从SDIO设备增量读取指定长度的数据的示例如下:
```
int32_t ret; ```
uint8_t rbuff[5] = {0}; int32_t SdioReadBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size);
uint32_t addr = 0x100 + 0x09; ```
/* 从SDIO设备起始地址0x109,增量读取5个字节的数据 */
ret = SdioReadBytes(handle, rbuff, addr, 5); **表7** SdioReadBytes函数的参数和返回值描述
if (ret != 0) {
| 参数 | 参数描述 |
| -------- | -------- |
| handle | SDIO控制器的设备句柄 |
| data | 接收读取数据的指针 |
| addr | 待读取数据的起始地址 |
| size | 待读取数据的长度 |
| **返回值** | **返回值描述** |
| 0 | SDIO读数据成功 |
| 负数 | SDIO读数据失败 |
从SDIO设备增量读取指定长度的数据的示例如下:
```
int32_t ret;
uint8_t rbuff[5] = {0};
uint32_t addr = 0x100 + 0x09;
/* 从SDIO设备起始地址0x109,增量读取5个字节的数据 */
ret = SdioReadBytes(handle, rbuff, addr, 5);
if (ret != 0) {
HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret);
} }
``` ```
- 向SDIO设备的固定地址写入指定长度的数据 - 向SDIO设备的固定地址写入指定长度的数据
对应的接口函数如下所示: 对应的接口函数如下所示:
int32\_t SdioWriteBytesToFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\);
```
**表 8** SdioWriteBytesToFixedAddr函数的参数和返回值描述 int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
```
<a name="table1982918113010"></a>
<table><thead align="left"><tr id="row1582911114010"><th class="cellrowborder" valign="top" width="48.43%" id="mcps1.2.3.1.1"><p id="p28301411903"><a name="p28301411903"></a><a name="p28301411903"></a>参数</p> **表8** SdioWriteBytesToFixedAddr函数的参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="51.57000000000001%" id="mcps1.2.3.1.2"><p id="p1883019111018"><a name="p1883019111018"></a><a name="p1883019111018"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | SDIO控制器的设备句柄 |
</thead> | data | 待写入数据的指针 |
<tbody><tr id="row10830141111014"><td class="cellrowborder" valign="top" width="48.43%" headers="mcps1.2.3.1.1 "><p id="p470818551018"><a name="p470818551018"></a><a name="p470818551018"></a>handle</p> | addr | 待写入数据的固定地址 |
</td> | size | 待写入数据的长度 |
<td class="cellrowborder" valign="top" width="51.57000000000001%" headers="mcps1.2.3.1.2 "><p id="p18578510518"><a name="p18578510518"></a><a name="p18578510518"></a>SDIO控制器的设备句柄</p> | scatterLen | 集散表的长度。如果该字段不为0,则data为集散表类型。 |
</td> | **返回值** | **返回值描述** |
</tr> | 0 | SDIO写数据成功 |
<tr id="row48303111304"><td class="cellrowborder" valign="top" width="48.43%" headers="mcps1.2.3.1.1 "><p id="p127081955502"><a name="p127081955502"></a><a name="p127081955502"></a>data</p> | 负数 | SDIO写数据失败 |
</td>
<td class="cellrowborder" valign="top" width="51.57000000000001%" headers="mcps1.2.3.1.2 "><p id="p1857841013110"><a name="p1857841013110"></a><a name="p1857841013110"></a>待写入数据的指针</p>
</td>
</tr>
<tr id="row9830111119019"><td class="cellrowborder" valign="top" width="48.43%" headers="mcps1.2.3.1.1 "><p id="p187085555011"><a name="p187085555011"></a><a name="p187085555011"></a>addr</p>
</td>
<td class="cellrowborder" valign="top" width="51.57000000000001%" headers="mcps1.2.3.1.2 "><p id="p257831016115"><a name="p257831016115"></a><a name="p257831016115"></a>待写入数据的固定地址</p>
</td>
</tr>
<tr id="row683091120012"><td class="cellrowborder" valign="top" width="48.43%" headers="mcps1.2.3.1.1 "><p id="p370819555013"><a name="p370819555013"></a><a name="p370819555013"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="51.57000000000001%" headers="mcps1.2.3.1.2 "><p id="p7578181015113"><a name="p7578181015113"></a><a name="p7578181015113"></a>待写入数据的长度</p>
</td>
</tr>
<tr id="row58301911309"><td class="cellrowborder" valign="top" width="48.43%" headers="mcps1.2.3.1.1 "><p id="p570810551107"><a name="p570810551107"></a><a name="p570810551107"></a>scatterLen</p>
</td>
<td class="cellrowborder" valign="top" width="51.57000000000001%" headers="mcps1.2.3.1.2 "><p id="p17579910915"><a name="p17579910915"></a><a name="p17579910915"></a>集散表的长度。如果该字段不为0,则data为集散表类型。</p>
</td>
</tr>
<tr id="row18215162810212"><td class="cellrowborder" valign="top" width="48.43%" headers="mcps1.2.3.1.1 "><p id="p1521319452211"><a name="p1521319452211"></a><a name="p1521319452211"></a><strong id="b621312451720"><a name="b621312451720"></a><a name="b621312451720"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.57000000000001%" headers="mcps1.2.3.1.2 "><p id="p162138457217"><a name="p162138457217"></a><a name="p162138457217"></a><strong id="b221311451226"><a name="b221311451226"></a><a name="b221311451226"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row2197123118210"><td class="cellrowborder" valign="top" width="48.43%" headers="mcps1.2.3.1.1 "><p id="p1921413451212"><a name="p1921413451212"></a><a name="p1921413451212"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="51.57000000000001%" headers="mcps1.2.3.1.2 "><p id="p32146451624"><a name="p32146451624"></a><a name="p32146451624"></a>SDIO写数据成功</p>
</td>
</tr>
<tr id="row18629103314218"><td class="cellrowborder" valign="top" width="48.43%" headers="mcps1.2.3.1.1 "><p id="p132141245622"><a name="p132141245622"></a><a name="p132141245622"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="51.57000000000001%" headers="mcps1.2.3.1.2 "><p id="p17214345328"><a name="p17214345328"></a><a name="p17214345328"></a>SDIO写数据失败</p>
</td>
</tr>
</tbody>
</table>
向SDIO设备的固定地址写入指定长度的数据的示例如下: 向SDIO设备的固定地址写入指定长度的数据的示例如下:
``` ```
int32_t ret; int32_t ret;
uint8_t wbuff[] = {1,2,3,4,5}; uint8_t wbuff[] = {1,2,3,4,5};
...@@ -573,65 +290,29 @@ if (ret != 0) { ...@@ -573,65 +290,29 @@ if (ret != 0) {
``` ```
- 从SDIO设备的固定地址读取指定长度的数据 - 从SDIO设备的固定地址读取指定长度的数据
对应的接口函数如下所示: 对应的接口函数如下所示:
int32\_t SdioReadBytesFromFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\);
```
**表 9** SdioReadBytesFromFixedAddr函数的参数和返回值描述 int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
```
<a name="table2724132220115"></a>
<table><thead align="left"><tr id="row8724142214115"><th class="cellrowborder" valign="top" width="48.699999999999996%" id="mcps1.2.3.1.1"><p id="p16752055131112"><a name="p16752055131112"></a><a name="p16752055131112"></a>参数</p> **表9** SdioReadBytesFromFixedAddr函数的参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="51.300000000000004%" id="mcps1.2.3.1.2"><p id="p914434191218"><a name="p914434191218"></a><a name="p914434191218"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | SDIO控制器的设备句柄 |
</thead> | data | 接收读取数据的指针 |
<tbody><tr id="row1372462214119"><td class="cellrowborder" valign="top" width="48.699999999999996%" headers="mcps1.2.3.1.1 "><p id="p2752175516113"><a name="p2752175516113"></a><a name="p2752175516113"></a>handle</p> | addr | 待读取数据的起始地址 |
</td> | size | 待读取数据的长度 |
<td class="cellrowborder" valign="top" width="51.300000000000004%" headers="mcps1.2.3.1.2 "><p id="p1353155020125"><a name="p1353155020125"></a><a name="p1353155020125"></a>SDIO控制器的设备句柄</p> | scatterLen | 集散表的长度。如果该字段不为0,则data为集散表类型。 |
</td> | **返回值** | **返回值描述** |
</tr> | 0 | SDIO读数据成功 |
<tr id="row197244220117"><td class="cellrowborder" valign="top" width="48.699999999999996%" headers="mcps1.2.3.1.1 "><p id="p12752165581117"><a name="p12752165581117"></a><a name="p12752165581117"></a>data</p> | 负数 | SDIO读数据失败 |
</td>
<td class="cellrowborder" valign="top" width="51.300000000000004%" headers="mcps1.2.3.1.2 "><p id="p9540508121"><a name="p9540508121"></a><a name="p9540508121"></a>接收读取数据的指针</p>
</td>
</tr>
<tr id="row172519228116"><td class="cellrowborder" valign="top" width="48.699999999999996%" headers="mcps1.2.3.1.1 "><p id="p1675315521120"><a name="p1675315521120"></a><a name="p1675315521120"></a>addr</p>
</td>
<td class="cellrowborder" valign="top" width="51.300000000000004%" headers="mcps1.2.3.1.2 "><p id="p05415501125"><a name="p05415501125"></a><a name="p05415501125"></a>待读取数据的起始地址</p>
</td>
</tr>
<tr id="row137251922131117"><td class="cellrowborder" valign="top" width="48.699999999999996%" headers="mcps1.2.3.1.1 "><p id="p47531355111111"><a name="p47531355111111"></a><a name="p47531355111111"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="51.300000000000004%" headers="mcps1.2.3.1.2 "><p id="p1954165031214"><a name="p1954165031214"></a><a name="p1954165031214"></a>待读取数据的长度</p>
</td>
</tr>
<tr id="row972552281111"><td class="cellrowborder" valign="top" width="48.699999999999996%" headers="mcps1.2.3.1.1 "><p id="p2753755161114"><a name="p2753755161114"></a><a name="p2753755161114"></a>scatterLen</p>
</td>
<td class="cellrowborder" valign="top" width="51.300000000000004%" headers="mcps1.2.3.1.2 "><p id="p3541350111218"><a name="p3541350111218"></a><a name="p3541350111218"></a>集散表的长度。如果该字段不为0,则data为集散表类型。</p>
</td>
</tr>
<tr id="row15725162210117"><td class="cellrowborder" valign="top" width="48.699999999999996%" headers="mcps1.2.3.1.1 "><p id="p681073451314"><a name="p681073451314"></a><a name="p681073451314"></a><strong id="b118106344137"><a name="b118106344137"></a><a name="b118106344137"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="51.300000000000004%" headers="mcps1.2.3.1.2 "><p id="p17810134121316"><a name="p17810134121316"></a><a name="p17810134121316"></a><strong id="b281014341134"><a name="b281014341134"></a><a name="b281014341134"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row1772511227119"><td class="cellrowborder" valign="top" width="48.699999999999996%" headers="mcps1.2.3.1.1 "><p id="p78105346133"><a name="p78105346133"></a><a name="p78105346133"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="51.300000000000004%" headers="mcps1.2.3.1.2 "><p id="p18810173411312"><a name="p18810173411312"></a><a name="p18810173411312"></a>SDIO读数据成功</p>
</td>
</tr>
<tr id="row191829161138"><td class="cellrowborder" valign="top" width="48.699999999999996%" headers="mcps1.2.3.1.1 "><p id="p1581012340131"><a name="p1581012340131"></a><a name="p1581012340131"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="51.300000000000004%" headers="mcps1.2.3.1.2 "><p id="p28101834161317"><a name="p28101834161317"></a><a name="p28101834161317"></a>SDIO读数据失败</p>
</td>
</tr>
</tbody>
</table>
从SDIO设备的固定地址读取指定长度的数据的示例如下: 从SDIO设备的固定地址读取指定长度的数据的示例如下:
``` ```
int32_t ret; int32_t ret;
uint8_t rbuff[5] = {0}; uint8_t rbuff[5] = {0};
...@@ -643,177 +324,93 @@ if (ret != 0) { ...@@ -643,177 +324,93 @@ if (ret != 0) {
} }
``` ```
- 向SDIO function 0的指定地址空间写入指定长度的数据 - 向SDIO function 0的指定地址空间写入指定长度的数据
当前只支持写入一个字节的数据,对应的接口函数如下所示: 当前只支持写入一个字节的数据,对应的接口函数如下所示:
int32\_t SdioWriteBytesToFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**表 10** SdioWriteBytesToFunc0函数的参数和返回值描述
<a name="table5339151811112"></a>
<table><thead align="left"><tr id="row2033991881120"><th class="cellrowborder" valign="top" width="49.94%" id="mcps1.2.3.1.1"><p id="p1116916499117"><a name="p1116916499117"></a><a name="p1116916499117"></a>参数</p>
</th>
<th class="cellrowborder" valign="top" width="50.06%" id="mcps1.2.3.1.2"><p id="p13169174971115"><a name="p13169174971115"></a><a name="p13169174971115"></a>参数描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row9339171871118"><td class="cellrowborder" valign="top" width="49.94%" headers="mcps1.2.3.1.1 "><p id="p16169194914117"><a name="p16169194914117"></a><a name="p16169194914117"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50.06%" headers="mcps1.2.3.1.2 "><p id="p10169114921110"><a name="p10169114921110"></a><a name="p10169114921110"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
<tr id="row93401118171116"><td class="cellrowborder" valign="top" width="49.94%" headers="mcps1.2.3.1.1 "><p id="p216919491118"><a name="p216919491118"></a><a name="p216919491118"></a>data</p>
</td>
<td class="cellrowborder" valign="top" width="50.06%" headers="mcps1.2.3.1.2 "><p id="p5169449121117"><a name="p5169449121117"></a><a name="p5169449121117"></a>待写入数据的指针</p>
</td>
</tr>
<tr id="row534019182114"><td class="cellrowborder" valign="top" width="49.94%" headers="mcps1.2.3.1.1 "><p id="p2016934941114"><a name="p2016934941114"></a><a name="p2016934941114"></a>addr</p>
</td>
<td class="cellrowborder" valign="top" width="50.06%" headers="mcps1.2.3.1.2 "><p id="p8169649101112"><a name="p8169649101112"></a><a name="p8169649101112"></a>待写入数据的起始地址</p>
</td>
</tr>
<tr id="row334011871113"><td class="cellrowborder" valign="top" width="49.94%" headers="mcps1.2.3.1.1 "><p id="p6169194913117"><a name="p6169194913117"></a><a name="p6169194913117"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="50.06%" headers="mcps1.2.3.1.2 "><p id="p71691449141119"><a name="p71691449141119"></a><a name="p71691449141119"></a>待写入数据的长度</p>
</td>
</tr>
<tr id="row123407185111"><td class="cellrowborder" valign="top" width="49.94%" headers="mcps1.2.3.1.1 "><p id="p294173071617"><a name="p294173071617"></a><a name="p294173071617"></a><strong id="b1294103061611"><a name="b1294103061611"></a><a name="b1294103061611"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50.06%" headers="mcps1.2.3.1.2 "><p id="p39421830111616"><a name="p39421830111616"></a><a name="p39421830111616"></a><strong id="b179429301164"><a name="b179429301164"></a><a name="b179429301164"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row8950101811164"><td class="cellrowborder" valign="top" width="49.94%" headers="mcps1.2.3.1.1 "><p id="p9942730181613"><a name="p9942730181613"></a><a name="p9942730181613"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50.06%" headers="mcps1.2.3.1.2 "><p id="p89421130141617"><a name="p89421130141617"></a><a name="p89421130141617"></a>SDIO写数据成功</p>
</td>
</tr>
<tr id="row42485216168"><td class="cellrowborder" valign="top" width="49.94%" headers="mcps1.2.3.1.1 "><p id="p1194223012167"><a name="p1194223012167"></a><a name="p1194223012167"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50.06%" headers="mcps1.2.3.1.2 "><p id="p19942630121617"><a name="p19942630121617"></a><a name="p19942630121617"></a>SDIO写数据失败</p>
</td>
</tr>
</tbody>
</table>
向SDIO function 0的指定地址空间写入指定长度的数据的示例如下:
```
int32_t ret; ```
uint8_t wbuff = 1; int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size);
/* 向SDIO function 0地址0x2中写入1字节的数据 */ ```
ret = SdioWriteBytesToFunc0(handle, &wbuff, 0x2, 1);
if (ret != 0) { **表10** SdioWriteBytesToFunc0函数的参数和返回值描述
| 参数 | 参数描述 |
| -------- | -------- |
| handle | SDIO控制器的设备句柄 |
| data | 待写入数据的指针 |
| addr | 待写入数据的起始地址 |
| size | 待写入数据的长度 |
| **返回值** | **返回值描述** |
| 0 | SDIO写数据成功 |
| 负数 | SDIO写数据失败 |
向SDIO function 0的指定地址空间写入指定长度的数据的示例如下:
```
int32_t ret;
uint8_t wbuff = 1;
/* 向SDIO function 0地址0x2中写入1字节的数据 */
ret = SdioWriteBytesToFunc0(handle, &wbuff, 0x2, 1);
if (ret != 0) {
HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret);
} }
``` ```
- 从SDIO function 0的指定地址空间读取指定长度的数据 - 从SDIO function 0的指定地址空间读取指定长度的数据
当前只支持读取一个字节的数据,对应的接口函数如下所示: 当前只支持读取一个字节的数据,对应的接口函数如下所示:
int32\_t SdioReadBytesFromFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\);
**表 11** SdioReadBytesFromFunc0函数的参数和返回值描述
<a name="table1071931161814"></a>
<table><thead align="left"><tr id="row771918171819"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p71291418171813"><a name="p71291418171813"></a><a name="p71291418171813"></a>参数</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p51291818101818"><a name="p51291818101818"></a><a name="p51291818101818"></a>参数描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row9720113186"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p121294185189"><a name="p121294185189"></a><a name="p121294185189"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p20129141815184"><a name="p20129141815184"></a><a name="p20129141815184"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
<tr id="row672017114185"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p171291186185"><a name="p171291186185"></a><a name="p171291186185"></a>data</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p8129118171820"><a name="p8129118171820"></a><a name="p8129118171820"></a>接收读取数据的指针</p>
</td>
</tr>
<tr id="row5720910188"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8129121816184"><a name="p8129121816184"></a><a name="p8129121816184"></a>addr</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p21296189182"><a name="p21296189182"></a><a name="p21296189182"></a>待读取数据的起始地址</p>
</td>
</tr>
<tr id="row172020115189"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p18129418191816"><a name="p18129418191816"></a><a name="p18129418191816"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p612921851820"><a name="p612921851820"></a><a name="p612921851820"></a>待读取数据的长度</p>
</td>
</tr>
<tr id="row167202113189"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1813001881810"><a name="p1813001881810"></a><a name="p1813001881810"></a><strong id="b1130151841813"><a name="b1130151841813"></a><a name="b1130151841813"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1313081817184"><a name="p1313081817184"></a><a name="p1313081817184"></a><strong id="b19130141818183"><a name="b19130141818183"></a><a name="b19130141818183"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row17720151101818"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p131307185182"><a name="p131307185182"></a><a name="p131307185182"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p113019187182"><a name="p113019187182"></a><a name="p113019187182"></a>SDIO读数据成功</p>
</td>
</tr>
<tr id="row1972019118189"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p18130151815185"><a name="p18130151815185"></a><a name="p18130151815185"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1013001861815"><a name="p1013001861815"></a><a name="p1013001861815"></a>SDIO读数据失败</p>
</td>
</tr>
</tbody>
</table>
从SDIO function 0的指定地址空间读取指定长度的数据的示例如下:
```
int32_t ret; ```
uint8_t rbuff; int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size);
/* 从SDIO function 0设备地址0x2中读取1字节的数据 */ ```
ret = SdioReadBytesFromFunc0(handle, &rbuff, 0x2, 1);
if (ret != 0) { **表11** SdioReadBytesFromFunc0函数的参数和返回值描述
| 参数 | 参数描述 |
| -------- | -------- |
| handle | SDIO控制器的设备句柄 |
| data | 接收读取数据的指针 |
| addr | 待读取数据的起始地址 |
| size | 待读取数据的长度 |
| **返回值** | **返回值描述** |
| 0 | SDIO读数据成功 |
| 负数 | SDIO读数据失败 |
从SDIO function 0的指定地址空间读取指定长度的数据的示例如下:
```
int32_t ret;
uint8_t rbuff;
/* 从SDIO function 0设备地址0x2中读取1字节的数据 */
ret = SdioReadBytesFromFunc0(handle, &rbuff, 0x2, 1);
if (ret != 0) {
HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret);
} }
``` ```
### 释放SDIO中断<a name="section1683449352"></a> ### 释放SDIO中断
通信完成之后,需要释放SDIO中断,函数如下所示: 通信完成之后,需要释放SDIO中断,函数如下所示:
int32\_t SdioReleaseIrq\(DevHandle handle\); int32_t SdioReleaseIrq(DevHandle handle);
**表 12** SdioReleaseIrq函数的参数和返回值描述 **表12** SdioReleaseIrq函数的参数和返回值描述
<a name="table165006412481"></a> | 参数 | 参数描述 |
<table><thead align="left"><tr id="row15499849482"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1549964114814"><a name="p1549964114814"></a><a name="p1549964114814"></a>参数</p> | -------- | -------- |
</th> | handle | SDIO控制器的设备句柄 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p749915484816"><a name="p749915484816"></a><a name="p749915484816"></a>参数描述</p> | **返回值** | **返回值描述** |
</th> | 0 | 释放SDIO中断成功 |
</tr> | 负数 | 释放SDIO中断失败 |
</thead>
<tbody><tr id="row1499194104813"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p9499743481"><a name="p9499743481"></a><a name="p9499743481"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p184999434815"><a name="p184999434815"></a><a name="p184999434815"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
<tr id="row3499442485"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p649918414812"><a name="p649918414812"></a><a name="p649918414812"></a><strong id="b154993419486"><a name="b154993419486"></a><a name="b154993419486"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p164991242486"><a name="p164991242486"></a><a name="p164991242486"></a><strong id="b174998413486"><a name="b174998413486"></a><a name="b174998413486"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row1349919494810"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p24994484820"><a name="p24994484820"></a><a name="p24994484820"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1649920414482"><a name="p1649920414482"></a><a name="p1649920414482"></a>释放SDIO中断成功</p>
</td>
</tr>
<tr id="row17500204154810"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p194990415489"><a name="p194990415489"></a><a name="p194990415489"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p74997419484"><a name="p74997419484"></a><a name="p74997419484"></a>释放SDIO中断失败</p>
</td>
</tr>
</tbody>
</table>
释放SDIO中断的示例如下: 释放SDIO中断的示例如下:
``` ```
int32_t ret; int32_t ret;
/* 释放SDIO中断 */ /* 释放SDIO中断 */
...@@ -823,46 +420,25 @@ if (ret != 0) { ...@@ -823,46 +420,25 @@ if (ret != 0) {
} }
``` ```
### 去使能SDIO设备<a name="section15379324143611"></a>
### 去使能SDIO设备
通信完成之后,还需要去使能SDIO设备,函数如下所示: 通信完成之后,还需要去使能SDIO设备,函数如下所示:
int32\_t SdioDisableFunc\(DevHandle handle\); int32_t SdioDisableFunc(DevHandle handle);
**表 13** SdioDisableFunc函数的参数和返回值描述 **表13** SdioDisableFunc函数的参数和返回值描述
<a name="table25012415481"></a> | 参数 | 参数描述 |
<table><thead align="left"><tr id="row1050010474810"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p05002419488"><a name="p05002419488"></a><a name="p05002419488"></a>参数</p> | -------- | -------- |
</th> | handle | SDIO控制器的设备句柄 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p17500114174811"><a name="p17500114174811"></a><a name="p17500114174811"></a>参数描述</p> | **返回值** | **返回值描述** |
</th> | 0 | 去使能SDIO设备成功 |
</tr> | 负数 | 去使能SDIO设备失败 |
</thead>
<tbody><tr id="row65001946482"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1150054104814"><a name="p1150054104814"></a><a name="p1150054104814"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1850014184812"><a name="p1850014184812"></a><a name="p1850014184812"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
<tr id="row175013494817"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p350013434816"><a name="p350013434816"></a><a name="p350013434816"></a><strong id="b15001442488"><a name="b15001442488"></a><a name="b15001442488"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1750184104813"><a name="p1750184104813"></a><a name="p1750184104813"></a><strong id="b125007414481"><a name="b125007414481"></a><a name="b125007414481"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row1850113413481"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p11501164114818"><a name="p11501164114818"></a><a name="p11501164114818"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1550116416489"><a name="p1550116416489"></a><a name="p1550116416489"></a>去使能SDIO设备成功</p>
</td>
</tr>
<tr id="row45015444817"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7501184154816"><a name="p7501184154816"></a><a name="p7501184154816"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p35011040484"><a name="p35011040484"></a><a name="p35011040484"></a>去使能SDIO设备失败</p>
</td>
</tr>
</tbody>
</table>
去使能SDIO设备的示例如下: 去使能SDIO设备的示例如下:
``` ```
int32_t ret; int32_t ret;
/* 去使能SDIO设备 */ /* 去使能SDIO设备 */
...@@ -872,69 +448,58 @@ if (ret != 0) { ...@@ -872,69 +448,58 @@ if (ret != 0) {
} }
``` ```
### 释放HOST<a name="section536018263713"></a>
### 释放HOST
通信完成之后,还需要释放去HOST,函数如下所示: 通信完成之后,还需要释放去HOST,函数如下所示:
void SdioReleaseHost\(DevHandle handle\);
```
**表 14** SdioReleaseHost函数的参数描述 void SdioReleaseHost(DevHandle handle);
```
<a name="table1350214164813"></a>
<table><thead align="left"><tr id="row6502134194814"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p18501945486"><a name="p18501945486"></a><a name="p18501945486"></a>参数</p> **表14** SdioReleaseHost函数的参数描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p45028414817"><a name="p45028414817"></a><a name="p45028414817"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | SDIO控制器的设备句柄 |
</thead>
<tbody><tr id="row135027411483"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16502174204816"><a name="p16502174204816"></a><a name="p16502174204816"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p6502164184816"><a name="p6502164184816"></a><a name="p6502164184816"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
</tbody>
</table>
释放HOST的示例如下: 释放HOST的示例如下:
``` ```
SdioReleaseHost(handle); /* 释放HOST */ SdioReleaseHost(handle); /* 释放HOST */
``` ```
### 关闭SDIO控制器<a name="section4752739183716"></a>
### 关闭SDIO控制器
SDIO通信完成之后,最后需要关闭SDIO控制器,函数如下所示: SDIO通信完成之后,最后需要关闭SDIO控制器,函数如下所示:
void SdioClose\(DevHandle handle\);
```
void SdioClose(DevHandle handle);
```
该函数会释放掉申请的资源。 该函数会释放掉申请的资源。
**表 15** SdioClose函数的参数描述 **表15** SdioClose函数的参数描述
<a name="table950324124815"></a> | 参数 | 参数描述 |
<table><thead align="left"><tr id="row1050213424819"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p18502134194818"><a name="p18502134194818"></a><a name="p18502134194818"></a>参数</p> | -------- | -------- |
</th> | handle | SDIO控制器的设备句柄 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p2502154104813"><a name="p2502154104813"></a><a name="p2502154104813"></a>参数描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row25035434810"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p175028434819"><a name="p175028434819"></a><a name="p175028434819"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p2050274194819"><a name="p2050274194819"></a><a name="p2050274194819"></a>SDIO控制器的设备句柄</p>
</td>
</tr>
</tbody>
</table>
关闭SDIO控制器的示例如下: 关闭SDIO控制器的示例如下:
``` ```
SdioClose(handle); /* 关闭SDIO控制器 */ SdioClose(handle); /* 关闭SDIO控制器 */
``` ```
## 使用实例<a name="section376910122382"></a>
SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。 ## 使用实例
SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。
``` ```
#include "hdf_log.h" #include "hdf_log.h"
...@@ -1060,4 +625,3 @@ ENABLE_ERR: ...@@ -1060,4 +625,3 @@ ENABLE_ERR:
SdioClose(handle); SdioClose(handle);
} }
``` ```
# SDIO<a name="ZH-CN_TOPIC_0000001176922484"></a> # SDIO
- [概述](#section1347805272150053)
- [接口说明](#section752964871810)
- [开发步骤](#section581179475150053)
- [开发实例](#section2112250242150053)
## 概述<a name="section1347805272150053"></a> ## 概述
SDIO由SD卡发展而来,被统称为MMC(MultiMediaCard),相关技术差别不大,在HDF框架中,SDIO的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 SDIO由SD卡发展而来,被统称为mmc(MultiMediaCard),相关技术差别不大,在HDF框架中,SDIO的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
**图 1** SDIO独立服务模式结构图<a name="fig124181331222"></a> **图1** SDIO独立服务模式结构图
![](figures/独立服务模式结构图.png "SDIO独立服务模式结构图") ![zh-cn_image_0000001177082420](figures/zh-cn_image_0000001177082420.png)
## 接口说明<a name="section752964871810"></a>
## 接口说明
SdioDeviceOps定义: SdioDeviceOps定义:
``` ```
// 函数模板 // 函数模板
struct SdioDeviceOps { struct SdioDeviceOps {
...@@ -39,245 +37,59 @@ struct SdioDeviceOps { ...@@ -39,245 +37,59 @@ struct SdioDeviceOps {
}; };
``` ```
**表 1** SdioDeviceOps结构体成员的回调函数功能说明 **表1** SdioDeviceOps结构体成员的回调函数功能说明
<a name="table878215448417"></a> | 函数 | 入参 | 出参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row17784344241"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p67842444414"><a name="p67842444414"></a><a name="p67842444414"></a>函数</p> | -------- | -------- | -------- | -------- | -------- |
</th> | incrAddrReadBytes | dev:&nbsp;结构体指针,SDIO设备控制器;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小 | data:&nbsp;uint8_t指针,传出值; | HDF_STATUS相关状态 | 从指定的SDIO地址增量读取给定长度的数据 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p1978411444416"><a name="p1978411444416"></a><a name="p1978411444416"></a>入参</p> | incrAddrWriteBytes | dev:&nbsp;结构体指针,SDIO设备控制器;data:&nbsp;uint8_t指针,传入值;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小 | 无 | HDF_STATUS相关状态 | 将给定长度的数据增量写入指定的SDIO地址 |
</th> | fixedAddrReadBytes | dev:&nbsp;结构体指针,SDIO设备控制器;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小;scatterLen:&nbsp;uint32_t,数据长度; | data:&nbsp;uint8_t指针,传出值; | HDF_STATUS相关状态 | 从固定SDIO地址读取给定长度的数据。 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p87841441243"><a name="p87841441243"></a><a name="p87841441243"></a>出参</p> | fixedAddrWriteBytes | dev:&nbsp;结构体指针,SDIO设备控制器;data:&nbsp;uint8_t指针,传入值;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小;scatterLen:&nbsp;uint32_t,数据长度; | 无 | HDF_STATUS相关状态 | 将给定长度的数据写入固定SDIO地址 |
</th> | func0ReadBytes | dev:&nbsp;结构体指针,SDIO设备控制器;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小; | data:&nbsp;uint8_t指针,传出值; | HDF_STATUS相关状态 | 从SDIO函数0的地址空间读取给定长度的数据。 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p12784174417415"><a name="p12784174417415"></a><a name="p12784174417415"></a>返回值</p> | func0WriteBytes | dev:&nbsp;结构体指针,SDIO设备控制器;data:&nbsp;uint8_t指针,传入值;addr:&nbsp;uint32_t,地址值;size:&nbsp;uint32_t,大小; | 无 | HDF_STATUS相关状态 | 将给定长度的数据写入SDIO函数0的地址空间。 |
</th> | setBlockSize | dev:&nbsp;结构体指针,SDIO设备控制器;blockSize:&nbsp;uint32_t,Block大小 | 无 | HDF_STATUS相关状态 | 设置block大小 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p16784104418413"><a name="p16784104418413"></a><a name="p16784104418413"></a>功能</p> | getCommonInfo | dev:&nbsp;联合体指针,SDIO设备控制器;infoType:&nbsp;uint32_t,info类型; | info:&nbsp;结构体指针,传出SdioFuncInfo信息; | HDF_STATUS相关状态 | 获取CommonInfo,说明见下 |
</th> | setCommonInfo | dev:&nbsp;结构体指针,SDIO设备控制器;info:&nbsp;联合体指针,SdioFuncInfo信息传入;infoType:&nbsp;uint32_t,info类型; | 无 | HDF_STATUS相关状态 | 设置CommonInfo,说明见下 |
</tr> | flushData | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 当SDIO需要重新初始化或发生意外错误时调用的函数 |
</thead> | enableFunc | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 使能SDIO设备 |
<tbody><tr id="row8784144449"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1378415443418"><a name="p1378415443418"></a><a name="p1378415443418"></a>incrAddrReadBytes</p> | disableFunc | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 去使能SDIO设备 |
</td> | claimIrq | dev:&nbsp;结构体指针,SDIO设备控制器;irqHandler:&nbsp;void函数指针; | 无 | HDF_STATUS相关状态 | 注册SDIO中断 |
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p177857442043"><a name="p177857442043"></a><a name="p177857442043"></a>dev: 结构体指针,SDIO设备控制器;addr: uint32_t,地址值;size: uint32_t,大小</p> | releaseIrq | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 释放SDIO中断 |
</td> | findFunc | dev:&nbsp;结构体指针,SDIO设备控制器;configData:&nbsp;结构体指针,&nbsp;SDIO函数关键信息 | 无 | HDF_STATUS相关状态 | 寻找匹配的funcNum |
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p207851447410"><a name="p207851447410"></a><a name="p207851447410"></a>data: uint8_t指针,传出值;</p> | claimHost | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 独占HOST |
</td> | releaseHost | dev:&nbsp;结构体指针,SDIO设备控制器; | 无 | HDF_STATUS相关状态 | 释放HOST |
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p167851644547"><a name="p167851644547"></a><a name="p167851644547"></a>HDF_STATUS相关状态</p>
</td> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p37855441645"><a name="p37855441645"></a><a name="p37855441645"></a>从指定的SDIO地址增量读取给定长度的数据</p> > CommonInfo包括maxBlockNum(单个request中最大block数), maxBlockSize(单个block最大字节数), maxRequestSize(单个Request最大字节数), enTimeout(最大超时时间,毫秒), funcNum(功能编号1~7), irqCap(IRQ capabilities), (void \*)data.
</td>
</tr>
<tr id="row197851446413"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p5785174419412"><a name="p5785174419412"></a><a name="p5785174419412"></a>incrAddrWriteBytes</p> ## 开发步骤
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p078554411417"><a name="p078554411417"></a><a name="p078554411417"></a>dev: 结构体指针,SDIO设备控制器;data: uint8_t指针,传入值;addr: uint32_t,地址值;size: uint32_t,大小</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p678519441748"><a name="p678519441748"></a><a name="p678519441748"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p778594419416"><a name="p778594419416"></a><a name="p778594419416"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p67851444445"><a name="p67851444445"></a><a name="p67851444445"></a>将给定长度的数据增量写入指定的SDIO地址</p>
</td>
</tr>
<tr id="row11785154419412"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p978514412418"><a name="p978514412418"></a><a name="p978514412418"></a>fixedAddrReadBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p15786144419415"><a name="p15786144419415"></a><a name="p15786144419415"></a>dev: 结构体指针,SDIO设备控制器;addr: uint32_t,地址值;size: uint32_t,大小;scatterLen: uint32_t,数据长度;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p9786124418414"><a name="p9786124418414"></a><a name="p9786124418414"></a>data: uint8_t指针,传出值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p2078614441842"><a name="p2078614441842"></a><a name="p2078614441842"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p107861744143"><a name="p107861744143"></a><a name="p107861744143"></a>从固定SDIO地址读取给定长度的数据。</p>
</td>
</tr>
<tr id="row278618441241"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p137861244448"><a name="p137861244448"></a><a name="p137861244448"></a>fixedAddrWriteBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p77861444341"><a name="p77861444341"></a><a name="p77861444341"></a>dev: 结构体指针,SDIO设备控制器;data: uint8_t指针,传入值;addr: uint32_t,地址值;size: uint32_t,大小;scatterLen: uint32_t,数据长度;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p5786244345"><a name="p5786244345"></a><a name="p5786244345"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p147868442416"><a name="p147868442416"></a><a name="p147868442416"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1478615441948"><a name="p1478615441948"></a><a name="p1478615441948"></a>将给定长度的数据写入固定SDIO地址</p>
</td>
</tr>
<tr id="row1078694416418"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p12786154414413"><a name="p12786154414413"></a><a name="p12786154414413"></a>func0ReadBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p4786244541"><a name="p4786244541"></a><a name="p4786244541"></a>dev: 结构体指针,SDIO设备控制器;addr: uint32_t,地址值;size: uint32_t,大小;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p37868445420"><a name="p37868445420"></a><a name="p37868445420"></a>data: uint8_t指针,传出值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p197874442416"><a name="p197874442416"></a><a name="p197874442416"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p107877441146"><a name="p107877441146"></a><a name="p107877441146"></a>从SDIO函数0的地址空间读取给定长度的数据。</p>
</td>
</tr>
<tr id="row1478794415414"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p12787644548"><a name="p12787644548"></a><a name="p12787644548"></a>func0WriteBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p67871544242"><a name="p67871544242"></a><a name="p67871544242"></a>dev: 结构体指针,SDIO设备控制器;data: uint8_t指针,传入值;addr: uint32_t,地址值;size: uint32_t,大小;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p678774413416"><a name="p678774413416"></a><a name="p678774413416"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p207871944648"><a name="p207871944648"></a><a name="p207871944648"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p57876441415"><a name="p57876441415"></a><a name="p57876441415"></a>将给定长度的数据写入SDIO函数0的地址空间。</p>
</td>
</tr>
<tr id="row157871441145"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1878714442417"><a name="p1878714442417"></a><a name="p1878714442417"></a>setBlockSize</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p187872445410"><a name="p187872445410"></a><a name="p187872445410"></a>dev: 结构体指针,SDIO设备控制器;blockSize: uint32_t,Block大小</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p77878444415"><a name="p77878444415"></a><a name="p77878444415"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p37871244243"><a name="p37871244243"></a><a name="p37871244243"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p378710441647"><a name="p378710441647"></a><a name="p378710441647"></a>设置block大小</p>
</td>
</tr>
<tr id="row15787344349"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p878819441048"><a name="p878819441048"></a><a name="p878819441048"></a>getCommonInfo</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1078820442419"><a name="p1078820442419"></a><a name="p1078820442419"></a>dev: 联合体指针,SDIO设备控制器;infoType: uint32_t,info类型;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p678814411418"><a name="p678814411418"></a><a name="p678814411418"></a>info: 结构体指针,传出SdioFuncInfo信息;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1578894410419"><a name="p1578894410419"></a><a name="p1578894410419"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p7788444140"><a name="p7788444140"></a><a name="p7788444140"></a>获取CommonInfo,说明见下</p>
</td>
</tr>
<tr id="row7788154410416"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p6788104410419"><a name="p6788104410419"></a><a name="p6788104410419"></a>setCommonInfo</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p2078815442417"><a name="p2078815442417"></a><a name="p2078815442417"></a>dev: 结构体指针,SDIO设备控制器;info: 联合体指针,SdioFuncInfo信息传入;infoType: uint32_t,info类型;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p13788644043"><a name="p13788644043"></a><a name="p13788644043"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p19788134418420"><a name="p19788134418420"></a><a name="p19788134418420"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1278814415412"><a name="p1278814415412"></a><a name="p1278814415412"></a>设置CommonInfo,说明见下</p>
</td>
</tr>
<tr id="row1788344744"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p2078819441745"><a name="p2078819441745"></a><a name="p2078819441745"></a>flushData</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p67888441442"><a name="p67888441442"></a><a name="p67888441442"></a>dev: 结构体指针,SDIO设备控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1478812441147"><a name="p1478812441147"></a><a name="p1478812441147"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p3789174418420"><a name="p3789174418420"></a><a name="p3789174418420"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p578912441445"><a name="p578912441445"></a><a name="p578912441445"></a>当SDIO需要重新初始化或发生意外错误时调用的函数</p>
</td>
</tr>
<tr id="row19789244142"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p778913441417"><a name="p778913441417"></a><a name="p778913441417"></a>enableFunc</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p12789144418412"><a name="p12789144418412"></a><a name="p12789144418412"></a>dev: 结构体指针,SDIO设备控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p678964419417"><a name="p678964419417"></a><a name="p678964419417"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p97891744946"><a name="p97891744946"></a><a name="p97891744946"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p127891445415"><a name="p127891445415"></a><a name="p127891445415"></a>使能SDIO设备</p>
</td>
</tr>
<tr id="row177898441647"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p978917447412"><a name="p978917447412"></a><a name="p978917447412"></a>disableFunc</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1978911449418"><a name="p1978911449418"></a><a name="p1978911449418"></a>dev: 结构体指针,SDIO设备控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p57898448413"><a name="p57898448413"></a><a name="p57898448413"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p77893441341"><a name="p77893441341"></a><a name="p77893441341"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1479019449414"><a name="p1479019449414"></a><a name="p1479019449414"></a>去使能SDIO设备</p>
</td>
</tr>
<tr id="row17908444415"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1279017441140"><a name="p1279017441140"></a><a name="p1279017441140"></a>claimIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1279018442419"><a name="p1279018442419"></a><a name="p1279018442419"></a>dev: 结构体指针,SDIO设备控制器;irqHandler: void函数指针;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p379084411411"><a name="p379084411411"></a><a name="p379084411411"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1179074410416"><a name="p1179074410416"></a><a name="p1179074410416"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p6790124418410"><a name="p6790124418410"></a><a name="p6790124418410"></a>注册SDIO中断</p>
</td>
</tr>
<tr id="row177909441647"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p77900441411"><a name="p77900441411"></a><a name="p77900441411"></a>releaseIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p27902441414"><a name="p27902441414"></a><a name="p27902441414"></a>dev: 结构体指针,SDIO设备控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p87906441742"><a name="p87906441742"></a><a name="p87906441742"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p147906446419"><a name="p147906446419"></a><a name="p147906446419"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p77901544440"><a name="p77901544440"></a><a name="p77901544440"></a>释放SDIO中断</p>
</td>
</tr>
<tr id="row97906449416"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p579024419411"><a name="p579024419411"></a><a name="p579024419411"></a>findFunc</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p5791184417414"><a name="p5791184417414"></a><a name="p5791184417414"></a>dev: 结构体指针,SDIO设备控制器;configData: 结构体指针, SDIO函数关键信息</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1079112441345"><a name="p1079112441345"></a><a name="p1079112441345"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p17916446420"><a name="p17916446420"></a><a name="p17916446420"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p779119441549"><a name="p779119441549"></a><a name="p779119441549"></a>寻找匹配的funcNum</p>
</td>
</tr>
<tr id="row779116446417"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p679119448412"><a name="p679119448412"></a><a name="p679119448412"></a>claimHost</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p179116441547"><a name="p179116441547"></a><a name="p179116441547"></a>dev: 结构体指针,SDIO设备控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p97911144944"><a name="p97911144944"></a><a name="p97911144944"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p12791244341"><a name="p12791244341"></a><a name="p12791244341"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p5791134412417"><a name="p5791134412417"></a><a name="p5791134412417"></a>独占HOST</p>
</td>
</tr>
<tr id="row47911344746"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p279113441046"><a name="p279113441046"></a><a name="p279113441046"></a>releaseHost</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p67916449413"><a name="p67916449413"></a><a name="p67916449413"></a>dev: 结构体指针,SDIO设备控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p37916441244"><a name="p37916441244"></a><a name="p37916441244"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p97911044948"><a name="p97911044948"></a><a name="p97911044948"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1792184413412"><a name="p1792184413412"></a><a name="p1792184413412"></a>释放HOST</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>CommonInfo包括maxBlockNum\(单个request中最大block数\), maxBlockSize\(单个block最大字节数\), maxRequestSize\(单个Request最大字节数\), enTimeout\(最大超时时间,毫秒\), funcNum\(功能编号1\~7\), irqCap\(IRQ capabilities\), \(void \*\)data.
## 开发步骤<a name="section581179475150053"></a>
SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加sdio\_config.hcs器件属性文件。 - 【可选】添加sdio_config.hcs器件属性文件。
3. **实例化SDIO控制器对象:** 3. **实例化SDIO控制器对象:**
- 初始化SdioDevice成员。 - 初始化SdioDevice成员。
- 实例化SdioDevice成员SdioDeviceOps。 - 实例化SdioDevice成员SdioDeviceOps。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化SdioDevice成员SdioDeviceOps,其定义和成员说明见[接口说明](#接口说明)。
>实例化SdioDevice成员SdioDeviceOps,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如SDIO控制状态,中断响应情况等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如SDIO控制状态,中断响应情况等。
## 开发实例<a name="section2112250242150053"></a> ## 开发实例
下方将以sdio\_adapter.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以sdio_adapter.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
SDIO 驱动入口参考: SDIO 驱动入口参考:
...@@ -294,11 +106,10 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -294,11 +106,10 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
HDF_INIT(g_sdioDriverEntry); HDF_INIT(g_sdioDriverEntry);
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 sdio\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SdioDevice成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 sdio_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SdioDevice成员的默认值或限制范围有密切关系。
本例只有一个SDIO控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在sdio_config文件中增加对应的器件属性。
本例只有一个SDIO控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在sdio\_config文件中增加对应的器件属性。 - device_info.hcs 配置参考:
- device\_info.hcs 配置参考:
``` ```
root { root {
...@@ -322,7 +133,8 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -322,7 +133,8 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
} }
``` ```
- sdio\_config.hcs 配置参考: - sdio_config.hcs 配置参考:
``` ```
root { root {
...@@ -343,7 +155,8 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -343,7 +155,8 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
3. 完成驱动入口注册之后,最后一步就是以核心层SdioDevice对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化SdioDevice成员SdioDeviceOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层SdioDevice对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化SdioDevice成员SdioDeviceOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考: - 自定义结构体参考:
从驱动的角度看,自定义结构体是参数和数据的载体,而且sdio\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象。 从驱动的角度看,自定义结构体是参数和数据的载体,而且sdio_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象。
``` ```
typedef struct { typedef struct {
...@@ -370,9 +183,9 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -370,9 +183,9 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
bool threadRunning; bool threadRunning;
}; };
``` ```
- SdioDevice成员回调函数结构体SdioDeviceOps的实例化,其他成员在Init函数中初始化。 - SdioDevice成员回调函数结构体SdioDeviceOps的实例化,其他成员在Init函数中初始化。
``` ```
static struct SdioDeviceOps g_sdioDeviceOps = { static struct SdioDeviceOps g_sdioDeviceOps = {
.incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes, .incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes,
...@@ -394,7 +207,6 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -394,7 +207,6 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
.releaseHost = Hi35xxLinuxSdioReleaseHost, .releaseHost = Hi35xxLinuxSdioReleaseHost,
}; };
``` ```
- Bind函数参考 - Bind函数参考
入参: 入参:
...@@ -403,54 +215,23 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -403,54 +215,23 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
返回值: 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
**表2** Bind函数入参及返回值
**表 2** Bind函数入参及返回值
| 状态(值) | 问题描述 |
<a name="table297118388199"></a> | -------- | -------- |
<table><thead align="left"><tr id="row197133831916"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1972138191917"><a name="p1972138191917"></a><a name="p1972138191917"></a>状态(值)</p> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
</th> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p197213387192"><a name="p197213387192"></a><a name="p197213387192"></a>问题描述</p> | HDF_ERR_INVALID_PARAM | 参数非法 |
</th> | HDF_ERR_IO | I/O&nbsp;错误 |
</tr> | HDF_SUCCESS | 初始化成功 |
</thead> | HDF_FAILURE | 初始化失败 |
<tbody><tr id="row20972538191911"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p99721238181910"><a name="p99721238181910"></a><a name="p99721238181910"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1097243811914"><a name="p1097243811914"></a><a name="p1097243811914"></a>控制器对象非法</p>
</td>
</tr>
<tr id="row5972203811199"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16972838151919"><a name="p16972838151919"></a><a name="p16972838151919"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1397223817192"><a name="p1397223817192"></a><a name="p1397223817192"></a>内存分配失败</p>
</td>
</tr>
<tr id="row14972173831913"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7972538131919"><a name="p7972538131919"></a><a name="p7972538131919"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p15972138191913"><a name="p15972138191913"></a><a name="p15972138191913"></a>参数非法</p>
</td>
</tr>
<tr id="row59721938131918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p199733380196"><a name="p199733380196"></a><a name="p199733380196"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p179731038101914"><a name="p179731038101914"></a><a name="p179731038101914"></a>I/O 错误</p>
</td>
</tr>
<tr id="row1797316382198"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16973203812195"><a name="p16973203812195"></a><a name="p16973203812195"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p297318386196"><a name="p297318386196"></a><a name="p297318386196"></a>初始化成功</p>
</td>
</tr>
<tr id="row16973838151918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1497353819191"><a name="p1497353819191"></a><a name="p1497353819191"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p109732038171917"><a name="p109732038171917"></a><a name="p109732038171917"></a>初始化失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
初始化自定义结构体对象,初始化SdioCntlr成员,调用核心层SdioCntlrAdd函数,以及其他厂商自定义初始化操作。 初始化自定义结构体对象,初始化SdioCntlr成员,调用核心层SdioCntlrAdd函数,以及其他厂商自定义初始化操作。
``` ```
static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj) static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj)
{ {
...@@ -489,12 +270,13 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -489,12 +270,13 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
返回值: 返回值:
HDF\_STATUS相关状态。 HDF_STATUS相关状态。
函数说明: 函数说明:
无操作,可根据厂商需要添加。 无操作,可根据厂商需要添加。
``` ```
static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj) static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj)
{ {
...@@ -503,7 +285,6 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -503,7 +285,6 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
- Release函数参考 - Release函数参考
入参: 入参:
...@@ -518,6 +299,7 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -518,6 +299,7 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作前提是在Bind函数中具备对应赋值的操作。 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作前提是在Bind函数中具备对应赋值的操作。
``` ```
static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj) static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj)
{ {
...@@ -527,6 +309,3 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -527,6 +309,3 @@ SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动
Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);//【必要】自定义的内存释放函数,这里有HdfDeviceObject到MmcCntlr的强制转化 Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);//【必要】自定义的内存释放函数,这里有HdfDeviceObject到MmcCntlr的强制转化
} }
``` ```
# SPI<a name="ZH-CN_TOPIC_0000001206171293"></a> # SPI
- [概述](#section193356154511)
- [接口说明](#section1325964832615)
- [使用指导](#section71363452477)
- [使用流程](#section32846814820)
- [获取SPI设备句柄](#section1927265711481)
- [获取SPI设备属性](#section541133418493)
- [配置SPI设备属性](#section7870106145010)
- [进行SPI通信](#section13324155195013)
- [销毁SPI设备句柄](#section19661632135117)
- [使用实例](#section06541058155120) ## 概述
## 概述<a name="section193356154511"></a>
- SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线。 - SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线。
- SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信,常用于与闪存、实时时钟、传感器以及模数转换器等进行通信。 - SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信,常用于与闪存、实时时钟、传感器以及模数转换器等进行通信。
- SPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是: - SPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是:
- SCLK – 时钟信号,由主设备产生; - SCLK – 时钟信号,由主设备产生;
- MOSI – 主设备数据输出,从设备数据输入; - MOSI – 主设备数据输出,从设备数据输入;
- MISO – 主设备数据输入,从设备数据输出; - MISO – 主设备数据输入,从设备数据输出;
- CS – 片选,从设备使能信号,由主设备控制。 - CS – 片选,从设备使能信号,由主设备控制。
- 一个主设备和两个从设备的连接示意图如下所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。
- 一个主设备和两个从设备的连接示意图如[图1](#fig89085710359)所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 **图1** SPI主从设备连接示意图
**图 1** SPI主从设备连接示意图。<a name="fig89085710359"></a> ![zh-cn_image_0000001160971308](figures/zh-cn_image_0000001160971308.png)
![](figures/SPI主从设备连接示意图.png "SPI主从设备连接示意图")
- SPI通信通常由主设备发起,通过以下步骤完成一次通信: - SPI通信通常由主设备发起,通过以下步骤完成一次通信:
1. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。
1. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。 2. 通过SCLK给选中的从设备提供时钟信号。
2. 通过SCLK给选中的从设备提供时钟信号。 3. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。
3. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。
- 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式: - 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式:
- CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。 - CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。
...@@ -40,126 +30,63 @@ ...@@ -40,126 +30,63 @@
- CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。 - CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。
- CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。 - CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。
- SPI接口定义了操作SPI设备的通用方法集合,包括: - SPI接口定义了操作SPI设备的通用方法集合,包括:
- SPI设备句柄获取和释放。 - SPI设备句柄获取和释放。
- SPI读写: 从SPI设备读取或写入指定长度数据。 - SPI读写: 从SPI设备读取或写入指定长度数据。
- SPI自定义传输:通过消息传输结构体执行任意读写组合过程。 - SPI自定义传输:通过消息传输结构体执行任意读写组合过程。
- SPI设备配置:获取和设置SPI设备属性。 - SPI设备配置:获取和设置SPI设备属性。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 当前只支持主机模式,不支持从机模式。
## 接口说明
**表1** SPI驱动API接口功能介绍
| 功能分类 | 接口名 |
| -------- | -------- |
| SPI设备句柄获取释放接口 | -&nbsp;SpiOpen:获取SPI设备句柄<br/>-&nbsp;SpiClose:释放SPI设备句柄 |
| SPI读写接口 | -&nbsp;SpiRead:读取指定长度的数据<br/>-&nbsp;SpiWrite:写入指定长度的数据<br/>-&nbsp;SpiTransfer:SPI数据传输接口 |
| SPI设备配置接口 | -&nbsp;SpiSetCfg:根据指定参数,配置SPI设备<br/>-&nbsp;SpiGetCfg:获取SPI设备配置参数 |
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
## 使用指导
>![](../public_sys-resources/icon-note.gif) **说明:**
>当前只支持主机模式,不支持从机模式。 ### 使用流程
## 接口说明<a name="section1325964832615"></a> 使用SPI的一般流程如下图所示。
**表 1** SPI驱动API接口功能介绍 **图2** SPI使用流程图
<a name="table1731550155318"></a> ![zh-cn_image_0000001206291275](figures/zh-cn_image_0000001206291275.png)
<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" align="left" valign="top" width="20.857914208579142%" id="mcps1.2.4.1.1"><p id="p641050105320"><a name="p641050105320"></a><a name="p641050105320"></a>功能分类</p>
</th>
<th class="cellrowborder" align="left" valign="top" width="23.36766323367663%" id="mcps1.2.4.1.2"><p id="p54150165315"><a name="p54150165315"></a><a name="p54150165315"></a>接口名</p> ### 获取SPI设备句柄
</th>
<th class="cellrowborder" align="left" valign="top" width="55.77442255774422%" id="mcps1.2.4.1.3"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row1651292212306"><td class="cellrowborder" rowspan="2" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p1387414255305"><a name="p1387414255305"></a><a name="p1387414255305"></a>SPI设备句柄获取释放接口</p>
</td>
<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p8874825143014"><a name="p8874825143014"></a><a name="p8874825143014"></a>SpiOpen</p>
</td>
<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p1087432513307"><a name="p1087432513307"></a><a name="p1087432513307"></a>获取SPI设备句柄</p>
</td>
</tr>
<tr id="row1429083612305"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1956614106311"><a name="p1956614106311"></a><a name="p1956614106311"></a>SpiClose</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p829111362306"><a name="p829111362306"></a><a name="p829111362306"></a>释放SPI设备句柄</p>
</td>
</tr>
<tr id="row34145016535"><td class="cellrowborder" rowspan="3" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>SPI读写接口</p>
</td>
<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p19389143041518"><a name="p19389143041518"></a><a name="p19389143041518"></a>SpiRead</p>
</td>
<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p8738101941716"><a name="p8738101941716"></a><a name="p8738101941716"></a>读取指定长度的数据</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>SpiWrite</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p573815197171"><a name="p573815197171"></a><a name="p573815197171"></a>写入指定长度的数据</p>
</td>
</tr>
<tr id="row1766145611414"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p183904373018"><a name="p183904373018"></a><a name="p183904373018"></a>SpiTransfer</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1639011313303"><a name="p1639011313303"></a><a name="p1639011313303"></a>SPI数据传输接口</p>
</td>
</tr>
<tr id="row1020919129159"><td class="cellrowborder" rowspan="2" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p82092126154"><a name="p82092126154"></a><a name="p82092126154"></a>SPI设备配置接口</p>
<p id="p6794153701111"><a name="p6794153701111"></a><a name="p6794153701111"></a></p>
</td>
<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p1739013012154"><a name="p1739013012154"></a><a name="p1739013012154"></a>SpiSetCfg</p>
</td>
<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p073910197173"><a name="p073910197173"></a><a name="p073910197173"></a>根据指定参数,配置SPI设备</p>
</td>
</tr>
<tr id="row379443710118"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p4333154919111"><a name="p4333154919111"></a><a name="p4333154919111"></a>SpiGetCfg</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p11333649171117"><a name="p11333649171117"></a><a name="p11333649171117"></a>获取SPI设备配置参数</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
## 使用指导<a name="section71363452477"></a>
### 使用流程<a name="section32846814820"></a>
使用SPI的一般流程如[图2](#fig1586912310348)所示。
**图 2** SPI使用流程图<a name="fig1586912310348"></a>
![](figures/SPI使用流程图.png "SPI使用流程图")
### 获取SPI设备句柄<a name="section1927265711481"></a>
在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。 在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。
DevHandle SpiOpen\(const struct SpiDevInfo \*info\);
```
**表 2** SpiOpen参数和返回值描述 DevHandle SpiOpen(const struct SpiDevInfo *info);
```
<a name="table7603619123820"></a>
<table><tbody><tr id="row1060351914386"><td class="cellrowborder" valign="top" width="50%"><p id="p14603181917382"><a name="p14603181917382"></a><a name="p14603181917382"></a><strong id="b743851872411"><a name="b743851872411"></a><a name="b743851872411"></a>参数</strong></p> **表2** SpiOpen参数和返回值描述
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p36031519183819"><a name="p36031519183819"></a><a name="p36031519183819"></a><strong id="b545016183242"><a name="b545016183242"></a><a name="b545016183242"></a>参数描述</strong></p> | **参数** | **参数描述** |
</td> | -------- | -------- |
</tr> | info | SPI设备描述符 |
<tr id="row1960431983813"><td class="cellrowborder" valign="top" width="50%"><p id="p3604719123817"><a name="p3604719123817"></a><a name="p3604719123817"></a>info</p> | **返回值** | **返回值描述** |
</td> | NULL | 获取SPI设备句柄失败 |
<td class="cellrowborder" valign="top" width="50%"><p id="p1560441923818"><a name="p1560441923818"></a><a name="p1560441923818"></a>SPI设备描述符</p> | 设备句柄 | 对应的SPI设备句柄 |
</td>
</tr>
<tr id="row380484160"><td class="cellrowborder" valign="top" width="50%"><p id="p460381915385"><a name="p460381915385"></a><a name="p460381915385"></a><strong id="b209091422131617"><a name="b209091422131617"></a><a name="b209091422131617"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p96031619153812"><a name="p96031619153812"></a><a name="p96031619153812"></a><strong id="b126401632121619"><a name="b126401632121619"></a><a name="b126401632121619"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row5793818161"><td class="cellrowborder" valign="top" width="50%"><p id="p1060418195389"><a name="p1060418195389"></a><a name="p1060418195389"></a>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p760471912388"><a name="p760471912388"></a><a name="p760471912388"></a>获取SPI设备句柄失败</p>
</td>
</tr>
<tr id="row187914871618"><td class="cellrowborder" valign="top" width="50%"><p id="p5604719133811"><a name="p5604719133811"></a><a name="p5604719133811"></a>设备句柄</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p3604181933818"><a name="p3604181933818"></a><a name="p3604181933818"></a>对应的SPI设备句柄</p>
</td>
</tr>
</tbody>
</table>
假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下: 假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下:
``` ```
struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */
DevHandle spiHandle = NULL; /* SPI设备句柄 */ DevHandle spiHandle = NULL; /* SPI设备句柄 */
...@@ -174,47 +101,26 @@ if (spiHandle == NULL) { ...@@ -174,47 +101,26 @@ if (spiHandle == NULL) {
} }
``` ```
### 获取SPI设备属性<a name="section541133418493"></a>
### 获取SPI设备属性
在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示: 在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示:
int32\_t SpiGetCfg\(DevHandle handle, struct SpiCfg \*cfg\);
```
**表 3** SpiGetCfg参数和返回值描述 int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg);
```
<a name="table14209152141313"></a>
<table><tbody><tr id="row1420918529133"><td class="cellrowborder" valign="top" width="50%"><p id="p42091852141314"><a name="p42091852141314"></a><a name="p42091852141314"></a><strong id="b2209135217139"><a name="b2209135217139"></a><a name="b2209135217139"></a>参数</strong></p> **表3** SpiGetCfg参数和返回值描述
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p202099523137"><a name="p202099523137"></a><a name="p202099523137"></a><strong id="b16209195201319"><a name="b16209195201319"></a><a name="b16209195201319"></a>参数描述</strong></p> | **参数** | **参数描述** |
</td> | -------- | -------- |
</tr> | handle | SPI设备句柄 |
<tr id="row142091352171310"><td class="cellrowborder" valign="top" width="50%"><p id="p1520915529131"><a name="p1520915529131"></a><a name="p1520915529131"></a>handle</p> | cfg | SPI设备配置参数 |
</td> | **返回值** | **返回值描述** |
<td class="cellrowborder" valign="top" width="50%"><p id="p720995291310"><a name="p720995291310"></a><a name="p720995291310"></a>SPI设备句柄</p> | 0 | 获取配置成功 |
</td> | 负数 | 获取配置失败 |
</tr>
<tr id="row6209152161314"><td class="cellrowborder" valign="top" width="50%"><p id="p720916522139"><a name="p720916522139"></a><a name="p720916522139"></a>cfg</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p172091452131319"><a name="p172091452131319"></a><a name="p172091452131319"></a>SPI设备配置参数</p>
</td>
</tr>
<tr id="row12092522139"><td class="cellrowborder" valign="top" width="50%"><p id="p18209125211134"><a name="p18209125211134"></a><a name="p18209125211134"></a><strong id="b2209155219132"><a name="b2209155219132"></a><a name="b2209155219132"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p420975231318"><a name="p420975231318"></a><a name="p420975231318"></a><strong id="b4209165210132"><a name="b4209165210132"></a><a name="b4209165210132"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row8209155251310"><td class="cellrowborder" valign="top" width="50%"><p id="p13210145291312"><a name="p13210145291312"></a><a name="p13210145291312"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p152101952141315"><a name="p152101952141315"></a><a name="p152101952141315"></a>获取配置成功</p>
</td>
</tr>
<tr id="row102101452121320"><td class="cellrowborder" valign="top" width="50%"><p id="p10210175219134"><a name="p10210175219134"></a><a name="p10210175219134"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p72101252101312"><a name="p72101252101312"></a><a name="p72101252101312"></a>获取配置失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -225,47 +131,26 @@ if (ret != 0) { ...@@ -225,47 +131,26 @@ if (ret != 0) {
} }
``` ```
### 配置SPI设备属性<a name="section7870106145010"></a>
### 配置SPI设备属性
在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示: 在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示:
int32\_t SpiSetCfg\(DevHandle handle, struct SpiCfg \*cfg\);
```
**表 4** SpiSetCfg参数和返回值描述 int32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg);
```
<a name="table219052945210"></a>
<table><tbody><tr id="row14191192918522"><td class="cellrowborder" valign="top" width="50%"><p id="p17424155016529"><a name="p17424155016529"></a><a name="p17424155016529"></a><strong id="b13808393249"><a name="b13808393249"></a><a name="b13808393249"></a>参数</strong></p> **表4** SpiSetCfg参数和返回值描述
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p942512508520"><a name="p942512508520"></a><a name="p942512508520"></a><strong id="b78202962416"><a name="b78202962416"></a><a name="b78202962416"></a>参数描述</strong></p> | **参数** | **参数描述** |
</td> | -------- | -------- |
</tr> | handle | SPI设备句柄 |
<tr id="row219152915524"><td class="cellrowborder" valign="top" width="50%"><p id="p2191122985218"><a name="p2191122985218"></a><a name="p2191122985218"></a>handle</p> | cfg | SPI设备配置参数 |
</td> | **返回值** | **返回值描述** |
<td class="cellrowborder" valign="top" width="50%"><p id="p1519162913524"><a name="p1519162913524"></a><a name="p1519162913524"></a>SPI设备句柄</p> | 0 | 配置成功 |
</td> | 负数 | 配置失败 |
</tr>
<tr id="row1719110297526"><td class="cellrowborder" valign="top" width="50%"><p id="p181911292523"><a name="p181911292523"></a><a name="p181911292523"></a>cfg</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p91911729155216"><a name="p91911729155216"></a><a name="p91911729155216"></a>SPI设备配置参数</p>
</td>
</tr>
<tr id="row036524131716"><td class="cellrowborder" valign="top" width="50%"><p id="p6425165035214"><a name="p6425165035214"></a><a name="p6425165035214"></a><strong id="b61219451173"><a name="b61219451173"></a><a name="b61219451173"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p18425650165215"><a name="p18425650165215"></a><a name="p18425650165215"></a><strong id="b826124514172"><a name="b826124514172"></a><a name="b826124514172"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row43653411178"><td class="cellrowborder" valign="top" width="50%"><p id="p1319132918520"><a name="p1319132918520"></a><a name="p1319132918520"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1719117292522"><a name="p1719117292522"></a><a name="p1719117292522"></a>配置成功</p>
</td>
</tr>
<tr id="row536594171715"><td class="cellrowborder" valign="top" width="50%"><p id="p719119296522"><a name="p719119296522"></a><a name="p719119296522"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p20191192925212"><a name="p20191192925212"></a><a name="p20191192925212"></a>配置失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -280,218 +165,137 @@ if (ret != 0) { ...@@ -280,218 +165,137 @@ if (ret != 0) {
} }
``` ```
### 进行SPI通信<a name="section13324155195013"></a>
### 进行SPI通信
- 向SPI设备写入指定长度的数据 - 向SPI设备写入指定长度的数据
如果只向SPI设备写一次数据,则可以通过以下函数完成: 如果只向SPI设备写一次数据,则可以通过以下函数完成:
int32\_t SpiWrite\(DevHandle handle, uint8\_t \*buf, uint32\_t len\);
**表 5** SpiWrite参数和返回值描述
<a name="table1018490043"></a>
<table><tbody><tr id="row31848013417"><td class="cellrowborder" valign="top" width="50%"><p id="p1415816132411"><a name="p1415816132411"></a><a name="p1415816132411"></a><strong id="b011110449230"><a name="b011110449230"></a><a name="b011110449230"></a>参数</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p11158111316410"><a name="p11158111316410"></a><a name="p11158111316410"></a><strong id="b18123204410230"><a name="b18123204410230"></a><a name="b18123204410230"></a>参数描述</strong></p>
</td>
</tr>
<tr id="row10184701945"><td class="cellrowborder" valign="top" width="50%"><p id="p104891871157"><a name="p104891871157"></a><a name="p104891871157"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p204891671156"><a name="p204891671156"></a><a name="p204891671156"></a>SPI设备句柄</p>
</td>
</tr>
<tr id="row928111518418"><td class="cellrowborder" valign="top" width="50%"><p id="p4282955412"><a name="p4282955412"></a><a name="p4282955412"></a>buf</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p7282752412"><a name="p7282752412"></a><a name="p7282752412"></a>待写入数据的指针</p>
</td>
</tr>
<tr id="row149041113651"><td class="cellrowborder" valign="top" width="50%"><p id="p139051213357"><a name="p139051213357"></a><a name="p139051213357"></a>len</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p16905313854"><a name="p16905313854"></a><a name="p16905313854"></a>待写入的数据长度</p>
</td>
</tr>
<tr id="row1148818622017"><td class="cellrowborder" valign="top" width="50%"><p id="p8158313248"><a name="p8158313248"></a><a name="p8158313248"></a><strong id="b1197324122018"><a name="b1197324122018"></a><a name="b1197324122018"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p161591413741"><a name="p161591413741"></a><a name="p161591413741"></a><strong id="b15219182419209"><a name="b15219182419209"></a><a name="b15219182419209"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row14488762202"><td class="cellrowborder" valign="top" width="50%"><p id="p103191916578"><a name="p103191916578"></a><a name="p103191916578"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1231981611712"><a name="p1231981611712"></a><a name="p1231981611712"></a>写入成功</p>
</td>
</tr>
<tr id="row164881464201"><td class="cellrowborder" valign="top" width="50%"><p id="p531916166716"><a name="p531916166716"></a><a name="p531916166716"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p93191161174"><a name="p93191161174"></a><a name="p93191161174"></a>写入失败</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret; ```
uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78}; int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len);
/* 向SPI设备写入指定长度的数据 */ ```
ret = SpiWrite(spiHandle, wbuff, 4);
if (ret != 0) { **表5** SpiWrite参数和返回值描述
| **参数** | **参数描述** |
| -------- | -------- |
| handle | SPI设备句柄 |
| buf | 待写入数据的指针 |
| len | 待写入的数据长度 |
| **返回值** | **返回值描述** |
| 0 | 写入成功 |
| 负数 | 写入失败 |
```
int32_t ret;
uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78};
/* 向SPI设备写入指定长度的数据 */
ret = SpiWrite(spiHandle, wbuff, 4);
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret); HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
} }
``` ```
- 从SPI设备读取指定长度的数据 - 从SPI设备读取指定长度的数据
如果只读取一次数据,则可以通过以下函数完成: 如果只读取一次数据,则可以通过以下函数完成:
int32\_t SpiRead\(DevHandle handle, uint8\_t \*buf, uint32\_t len\);
**表 6** SpiRead参数和返回值描述
<a name="table0265191412124"></a>
<table><tbody><tr id="row42651914141213"><td class="cellrowborder" valign="top" width="50%"><p id="p1483184123"><a name="p1483184123"></a><a name="p1483184123"></a><strong id="b81201431172318"><a name="b81201431172318"></a><a name="b81201431172318"></a>参数</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p9831871216"><a name="p9831871216"></a><a name="p9831871216"></a><strong id="b31321731122316"><a name="b31321731122316"></a><a name="b31321731122316"></a>参数描述</strong></p>
</td>
</tr>
<tr id="row1926651415123"><td class="cellrowborder" valign="top" width="50%"><p id="p389183129"><a name="p389183129"></a><a name="p389183129"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p168151817124"><a name="p168151817124"></a><a name="p168151817124"></a>SPI设备句柄</p>
</td>
</tr>
<tr id="row202661414201220"><td class="cellrowborder" valign="top" width="50%"><p id="p158161821210"><a name="p158161821210"></a><a name="p158161821210"></a>buf</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p98131811126"><a name="p98131811126"></a><a name="p98131811126"></a>待读取数据的指针</p>
</td>
</tr>
<tr id="row1926621451212"><td class="cellrowborder" valign="top" width="50%"><p id="p2918182124"><a name="p2918182124"></a><a name="p2918182124"></a>len</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p169718191220"><a name="p169718191220"></a><a name="p169718191220"></a>待读取的数据长度</p>
</td>
</tr>
<tr id="row05841310206"><td class="cellrowborder" valign="top" width="50%"><p id="p38171818128"><a name="p38171818128"></a><a name="p38171818128"></a><strong id="b33485467201"><a name="b33485467201"></a><a name="b33485467201"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p881918161220"><a name="p881918161220"></a><a name="p881918161220"></a><strong id="b13361846112013"><a name="b13361846112013"></a><a name="b13361846112013"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row15584173192016"><td class="cellrowborder" valign="top" width="50%"><p id="p14871820128"><a name="p14871820128"></a><a name="p14871820128"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p88118101211"><a name="p88118101211"></a><a name="p88118101211"></a>读取成功</p>
</td>
</tr>
<tr id="row1058418317204"><td class="cellrowborder" valign="top" width="50%"><p id="p10841817125"><a name="p10841817125"></a><a name="p10841817125"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p986183127"><a name="p986183127"></a><a name="p986183127"></a>读取失败</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret; ```
uint8_t rbuff[4] = {0}; int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len);
/* 从SPI设备读取指定长度的数据 */ ```
ret = SpiRead(spiHandle, rbuff, 4);
if (ret != 0) { **表6** SpiRead参数和返回值描述
| **参数** | **参数描述** |
| -------- | -------- |
| handle | SPI设备句柄 |
| buf | 待读取数据的指针 |
| len | 待读取的数据长度 |
| **返回值** | **返回值描述** |
| 0 | 读取成功 |
| 负数 | 读取失败 |
```
int32_t ret;
uint8_t rbuff[4] = {0};
/* 从SPI设备读取指定长度的数据 */
ret = SpiRead(spiHandle, rbuff, 4);
if (ret != 0) {
HDF_LOGE("SpiRead: failed, ret %d\n", ret); HDF_LOGE("SpiRead: failed, ret %d\n", ret);
} }
``` ```
- 自定义传输 - 自定义传输
如果需要发起一次自定义传输,则可以通过以下函数完成: 如果需要发起一次自定义传输,则可以通过以下函数完成:
int32\_t SpiTransfer\(DevHandle handle, struct SpiMsg \*msgs, uint32\_t count\);
**表 7** SpiTransfer参数和返回值描述
<a name="table1934414174212"></a>
<table><tbody><tr id="row1134415176216"><td class="cellrowborder" valign="top" width="50%"><p id="p13295152320217"><a name="p13295152320217"></a><a name="p13295152320217"></a><strong id="b14726194114224"><a name="b14726194114224"></a><a name="b14726194114224"></a>参数</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1295112352115"><a name="p1295112352115"></a><a name="p1295112352115"></a><strong id="b6744541162218"><a name="b6744541162218"></a><a name="b6744541162218"></a>参数描述</strong></p>
</td>
</tr>
<tr id="row5344101702113"><td class="cellrowborder" valign="top" width="50%"><p id="p19295132382111"><a name="p19295132382111"></a><a name="p19295132382111"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p829510232213"><a name="p829510232213"></a><a name="p829510232213"></a>SPI设备句柄</p>
</td>
</tr>
<tr id="row17344171722117"><td class="cellrowborder" valign="top" width="50%"><p id="p9295122332113"><a name="p9295122332113"></a><a name="p9295122332113"></a>msgs</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p202951238218"><a name="p202951238218"></a><a name="p202951238218"></a>待传输数据的数组</p>
</td>
</tr>
<tr id="row45812466213"><td class="cellrowborder" valign="top" width="50%"><p id="p1659246112117"><a name="p1659246112117"></a><a name="p1659246112117"></a>count</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p259124622119"><a name="p259124622119"></a><a name="p259124622119"></a>msgs数组长度</p>
</td>
</tr>
<tr id="row45187318214"><td class="cellrowborder" valign="top" width="50%"><p id="p17295142322113"><a name="p17295142322113"></a><a name="p17295142322113"></a><strong id="b6754144472117"><a name="b6754144472117"></a><a name="b6754144472117"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p142959232211"><a name="p142959232211"></a><a name="p142959232211"></a><strong id="b107682446216"><a name="b107682446216"></a><a name="b107682446216"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row175186313217"><td class="cellrowborder" valign="top" width="50%"><p id="p929532313211"><a name="p929532313211"></a><a name="p929532313211"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p829512237217"><a name="p829512237217"></a><a name="p829512237217"></a>执行成功</p>
</td>
</tr>
<tr id="row1451803152114"><td class="cellrowborder" valign="top" width="50%"><p id="p12958234217"><a name="p12958234217"></a><a name="p12958234217"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1295192312112"><a name="p1295192312112"></a><a name="p1295192312112"></a>执行失败</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret; ```
uint8_t wbuff[1] = {0x12}; int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count);
uint8_t rbuff[1] = {0}; ```
struct SpiMsg msg; /* 自定义传输的消息*/
msg.wbuf = wbuff; /* 写入的数据 */ **表7** SpiTransfer参数和返回值描述
msg.rbuf = rbuff; /* 读取的数据 */
msg.len = 1; /* 读取、写入数据的长度都是1 */ | **参数** | **参数描述** |
msg.csChange = 1; /* 进行下一次传输前关闭片选 */ | -------- | -------- |
msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ | handle | SPI设备句柄 |
msg.speed = 115200; /* 本次传输的速度 */ | msgs | 待传输数据的数组 |
/* 进行一次自定义传输,传输的msg个数为1 */ | count | msgs数组长度 |
ret = SpiTransfer(spiHandle, &msg, 1); | **返回值** | **返回值描述** |
if (ret != 0) { | 0 | 执行成功 |
| 负数 | 执行失败 |
```
int32_t ret;
uint8_t wbuff[1] = {0x12};
uint8_t rbuff[1] = {0};
struct SpiMsg msg; /* 自定义传输的消息*/
msg.wbuf = wbuff; /* 写入的数据 */
msg.rbuf = rbuff; /* 读取的数据 */
msg.len = 1; /* 读取、写入数据的长度都是1 */
msg.csChange = 1; /* 进行下一次传输前关闭片选 */
msg.delayUs = 0; /* 进行下一次传输前不进行延时 */
msg.speed = 115200; /* 本次传输的速度 */
/* 进行一次自定义传输,传输的msg个数为1 */
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
} }
``` ```
### 销毁SPI设备句柄<a name="section19661632135117"></a> ### 销毁SPI设备句柄
SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示: SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示:
void SpiClose\(DevHandle handle\);
```
void SpiClose(DevHandle handle);
```
该函数会释放掉申请的资源。 该函数会释放掉申请的资源。
**表 8** SpiClose参数描述 **表8** SpiClose参数描述
<a name="table72517953115"></a> | **参数** | **参数描述** |
<table><tbody><tr id="row1525793312"><td class="cellrowborder" valign="top" width="50%"><p id="p115402031153111"><a name="p115402031153111"></a><a name="p115402031153111"></a><strong id="b691142582513"><a name="b691142582513"></a><a name="b691142582513"></a>参数</strong></p> | -------- | -------- |
</td> | handle | SPI设备句柄 |
<td class="cellrowborder" valign="top" width="50%"><p id="p65406313319"><a name="p65406313319"></a><a name="p65406313319"></a><strong id="b1892414252254"><a name="b1892414252254"></a><a name="b1892414252254"></a>参数描述</strong></p>
</td>
</tr>
<tr id="row1926109193116"><td class="cellrowborder" valign="top" width="50%"><p id="p105419317318"><a name="p105419317318"></a><a name="p105419317318"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p16541153110317"><a name="p16541153110317"></a><a name="p16541153110317"></a>SPI设备句柄</p>
</td>
</tr>
</tbody>
</table>
``` ```
SpiClose(spiHandle); /* 销毁SPI设备句柄 */ SpiClose(spiHandle); /* 销毁SPI设备句柄 */
``` ```
## 使用实例<a name="section06541058155120"></a>
SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。 ## 使用实例
SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。
``` ```
#include "hdf_log.h" #include "hdf_log.h"
...@@ -558,4 +362,3 @@ err: ...@@ -558,4 +362,3 @@ err:
SpiClose(spiHandle); SpiClose(spiHandle);
} }
``` ```
# SPI<a name="ZH-CN_TOPIC_0000001222282191"></a> # SPI
- [概述](#section84922229152909)
- [接口说明](#section752964871810)
- [开发步骤](#section799667984152909)
- [开发实例](#section956157227152909)
## 概述<a name="section84922229152909"></a> ## 概述
SPI即串行外设接口(Serial Peripheral Interface),在HDF框架中,SPI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 SPI即串行外设接口(Serial Peripheral Interface),在HDF框架中,SPI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
**图 1** SPI独立服务模式结构图<a name="fig666465313303"></a> **图1** SPI独立服务模式结构图
![](figures/独立服务模式结构图.png "SPI独立服务模式结构图")
## 接口说明<a name="section752964871810"></a> ![zh-cn_image_0000001176603992](figures/zh-cn_image_0000001176603992.png)
## 接口说明
SpiCntlrMethod定义: SpiCntlrMethod定义:
``` ```
struct SpiCntlrMethod { struct SpiCntlrMethod {
int32_t (*GetCfg)(struct SpiCntlr *cntlr, struct SpiCfg *cfg); int32_t (*GetCfg)(struct SpiCntlr *cntlr, struct SpiCfg *cfg);
...@@ -26,98 +25,44 @@ struct SpiCntlrMethod { ...@@ -26,98 +25,44 @@ struct SpiCntlrMethod {
}; };
``` ```
**表 1** SpiCntlrMethod结构体成员的回调函数功能说明 **表1** SpiCntlrMethod结构体成员的回调函数功能说明
<a name="table7167123615321"></a> | 成员函数 | 入参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row816783615326"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p8167193643218"><a name="p8167193643218"></a><a name="p8167193643218"></a>成员函数</p> | -------- | -------- | -------- | -------- |
</th> | Transfer | cntlr:结构体指针,核心层spi控制器。<br/>msg:结构体指针,Spi消息。<br/>count:uint32_t,消息个数。 | HDF_STATUS相关状态 | 传输消息 |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p31672362325"><a name="p31672362325"></a><a name="p31672362325"></a>入参</p> | SetCfg | cntlr:结构体指针,核心层spi控制器。<br/>cfg:结构体指针,Spi属性。 | HDF_STATUS相关状态 | 设置控制器属性 |
</th> | GetCfg | cntlr:结构体指针,核心层spi控制器。<br/>cfg:结构体指针,Spi属性。 | HDF_STATUS相关状态 | 获取控制器属性 |
<th class="cellrowborder" valign="top" width="24.98%" id="mcps1.2.5.1.3"><p id="p51673367328"><a name="p51673367328"></a><a name="p51673367328"></a>返回值</p> | Open | cntlr:结构体指针,核心层spi控制器。 | HDF_STATUS相关状态 | 打开SPI |
</th> | Close | cntlr:结构体指针,核心层spi控制器。 | HDF_STATUS相关状态 | 关闭SPI |
<th class="cellrowborder" valign="top" width="25.019999999999996%" id="mcps1.2.5.1.4"><p id="p1116883619322"><a name="p1116883619322"></a><a name="p1116883619322"></a>功能</p>
</th>
</tr> ## 开发步骤
</thead>
<tbody><tr id="row816883693214"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p11683369329"><a name="p11683369329"></a><a name="p11683369329"></a>Transfer</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p6168736173213"><a name="p6168736173213"></a><a name="p6168736173213"></a>cntlr:结构体指针,核心层spi控制器;</br>msg:结构体指针,Spi消息;</br>count:uint32_t,消息个数;</p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p19168736113216"><a name="p19168736113216"></a><a name="p19168736113216"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p18168236143218"><a name="p18168236143218"></a><a name="p18168236143218"></a>传输消息</p>
</td>
</tr>
<tr id="row3168113633211"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p4168636193212"><a name="p4168636193212"></a><a name="p4168636193212"></a>SetCfg</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p11168163643217"><a name="p11168163643217"></a><a name="p11168163643217"></a>cntlr;结构体指针,核心层spi控制器;</br>cfg:结构体指针,Spi属性;</p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p101683367325"><a name="p101683367325"></a><a name="p101683367325"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p1216815368329"><a name="p1216815368329"></a><a name="p1216815368329"></a>设置控制器属性</p>
</td>
</tr>
<tr id="row13168183683215"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p11168436123220"><a name="p11168436123220"></a><a name="p11168436123220"></a>GetCfg</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p3168936133218"><a name="p3168936133218"></a><a name="p3168936133218"></a>cntlr:结构体指针,核心层spi控制器;</br>cfg:结构体指针,Spi属性;</p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p18169036193219"><a name="p18169036193219"></a><a name="p18169036193219"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p3169136173219"><a name="p3169136173219"></a><a name="p3169136173219"></a>获取控制器属性</p>
</td>
</tr>
<tr id="row9169133643218"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p13169163615320"><a name="p13169163615320"></a><a name="p13169163615320"></a>Open</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p181697365327"><a name="p181697365327"></a><a name="p181697365327"></a>cntlr:结构体指针,核心层spi控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p1169163693216"><a name="p1169163693216"></a><a name="p1169163693216"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p1116963693218"><a name="p1116963693218"></a><a name="p1116963693218"></a>打开SPI</p>
</td>
</tr>
<tr id="row11169436153214"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p0169736153219"><a name="p0169736153219"></a><a name="p0169736153219"></a>Close</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p31691936193210"><a name="p31691936193210"></a><a name="p31691936193210"></a>cntlr:结构体指针,核心层spi控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p2169123617322"><a name="p2169123617322"></a><a name="p2169123617322"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p1169636103220"><a name="p1169636103220"></a><a name="p1169636103220"></a>关闭SPI</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section799667984152909"></a>
SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加spi\_config.hcs器件属性文件。 - 【可选】添加spi_config.hcs器件属性文件。
3. **实例化SPI控制器对象:** 3. **实例化SPI控制器对象:**
- 初始化SpiCntlr成员。 - 初始化SpiCntlr成员。
- 实例化SpiCntlr成员SpiCntlrMethod。 - 实例化SpiCntlr成员SpiCntlrMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化SpiCntlr成员SpiCntlrMethod,其定义和成员说明见[接口说明](#接口说明)。
>实例化SpiCntlr成员SpiCntlrMethod,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如spi控制状态,中断响应情况等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如spi控制状态,中断响应情况等。
## 开发实例<a name="section956157227152909"></a> ## 开发实例
下方将以spi\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以spi_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
SPI驱动入口参考: SPI驱动入口参考:
...@@ -134,11 +79,10 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -134,11 +79,10 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
HDF_INIT(g_hdfSpiDevice); HDF_INIT(g_hdfSpiDevice);
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 spi\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SpiCntlr 成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 spi_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SpiCntlr 成员的默认值或限制范围有密切关系。
本例只有一个SPI控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在spi_config文件中增加对应的器件属性。
本例只有一个SPI控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在spi\_config文件中增加对应的器件属性 - device_info.hcs 配置参考
- device\_info.hcs 配置参考。
``` ```
root { root {
...@@ -171,7 +115,8 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -171,7 +115,8 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
} }
``` ```
- spi\_config.hcs 配置参考。 - spi_config.hcs 配置参考。
``` ```
root { root {
...@@ -223,7 +168,8 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -223,7 +168,8 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
3. 完成驱动入口注册之后,最后一步就是以核心层SpiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化SpiCntlr成员SpiCntlrMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层SpiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化SpiCntlr成员SpiCntlrMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考。 - 自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且spi\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号、总线号等。 从驱动的角度看,自定义结构体是参数和数据的载体,而且spi_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号、总线号等。
``` ```
struct Pl022 {//对应于hcs中的参数 struct Pl022 {//对应于hcs中的参数
...@@ -268,6 +214,7 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -268,6 +214,7 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
- SpiCntlr成员回调函数结构体SpiCntlrMethod的实例化,其他成员在Init函数中初始化。 - SpiCntlr成员回调函数结构体SpiCntlrMethod的实例化,其他成员在Init函数中初始化。
``` ```
// spi_hi35xx.c 中的示例:钩子函数的实例化 // spi_hi35xx.c 中的示例:钩子函数的实例化
struct SpiCntlrMethod g_method = { struct SpiCntlrMethod g_method = {
...@@ -287,12 +234,13 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -287,12 +234,13 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
返回值: 返回值:
HDF\_STATUS相关状态。 HDF_STATUS相关状态。
函数说明: 函数说明:
将 SpiCntlr 对象同 HdfDeviceObject 进行了关联。 将 SpiCntlr 对象同 HdfDeviceObject 进行了关联。
``` ```
static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device) static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device)
{ {
...@@ -323,54 +271,24 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -323,54 +271,24 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
返回值: 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见/drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
**表 2** init函数入参和返回值 **表2** Init函数入参和返回值
<a name="table4311552173914"></a> | 状态(值) | 问题描述 |
<table><thead align="left"><tr id="row8314152103916"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p331413523392"><a name="p331413523392"></a><a name="p331413523392"></a>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p7314145220390"><a name="p7314145220390"></a><a name="p7314145220390"></a>问题描述</p> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</th> | HDF_ERR_INVALID_PARAM | 参数非法 |
</tr> | HDF_ERR_IO | I/O&nbsp;错误 |
</thead> | HDF_SUCCESS | 初始化成功 |
<tbody><tr id="row93142052183918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p93141252123914"><a name="p93141252123914"></a><a name="p93141252123914"></a>HDF_ERR_INVALID_OBJECT</p> | HDF_FAILURE | 初始化失败 |
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p331485215390"><a name="p331485215390"></a><a name="p331485215390"></a>控制器对象非法</p>
</td>
</tr>
<tr id="row331445211399"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p83141352183917"><a name="p83141352183917"></a><a name="p83141352183917"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p15314175220397"><a name="p15314175220397"></a><a name="p15314175220397"></a>内存分配失败</p>
</td>
</tr>
<tr id="row20314175213918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p9314352113917"><a name="p9314352113917"></a><a name="p9314352113917"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p131535273910"><a name="p131535273910"></a><a name="p131535273910"></a>参数非法</p>
</td>
</tr>
<tr id="row1431565233911"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p0315052103915"><a name="p0315052103915"></a><a name="p0315052103915"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1831585215398"><a name="p1831585215398"></a><a name="p1831585215398"></a>I/O 错误</p>
</td>
</tr>
<tr id="row2315152193914"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7315185263919"><a name="p7315185263919"></a><a name="p7315185263919"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1731585213910"><a name="p1731585213910"></a><a name="p1731585213910"></a>初始化成功</p>
</td>
</tr>
<tr id="row5315752163916"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p6315105211392"><a name="p6315105211392"></a><a name="p6315105211392"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p83157528399"><a name="p83157528399"></a><a name="p83157528399"></a>初始化失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
初始化自定义结构体对象,初始化SpiCntlr成员。 初始化自定义结构体对象,初始化SpiCntlr成员。
``` ```
static int32_t HdfSpiDeviceInit(struct HdfDeviceObject *device) static int32_t HdfSpiDeviceInit(struct HdfDeviceObject *device)
{ {
...@@ -415,7 +333,6 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -415,7 +333,6 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
return 0; return 0;
} }
``` ```
- Release函数参考 - Release函数参考
入参: 入参:
...@@ -430,6 +347,7 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -430,6 +347,7 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。
``` ```
static void HdfSpiDeviceRelease(struct HdfDeviceObject *device) static void HdfSpiDeviceRelease(struct HdfDeviceObject *device)
{ {
...@@ -444,6 +362,3 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -444,6 +362,3 @@ SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动
SpiCntlrDestroy(cntlr); //释放Pl022对象 SpiCntlrDestroy(cntlr); //释放Pl022对象
} }
``` ```
# UART<a name="ZH-CN_TOPIC_0000001160652800"></a> # UART
- [概述](#section833012453535)
- [接口说明](#section1928742202715) ## 概述
- [使用指导](#section12779050105412)
- [使用流程](#section1858116395510)
- [获取UART设备句柄](#section124512065617)
- [UART设置波特率](#section86881004579)
- [UART获取波特率](#section897032965712)
- [UART设置设备属性](#section129141884588)
- [UART获取设备属性](#section18689637165812)
- [设置UART传输模式](#section72713435918)
- [向UART设备写入指定长度的数据](#section128001736155919)
- [从UART设备中读取指定长度的数据](#section92851601604)
- [销毁UART设备句柄](#section1477410521406)
- [使用实例](#section35404241311)
## 概述<a name="section833012453535"></a>
- UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。 - UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。
- UART应用比较广泛,常用于输出打印信息,也可以外接各种模块,如GPS、蓝牙等。 - UART应用比较广泛,常用于输出打印信息,也可以外接各种模块,如GPS、蓝牙等。
- 两个UART设备的连接示意图如下,UART与其他模块一般用2线(图1)或4线(图2)相连,它们分别是: - 两个UART设备的连接示意图如下,UART与其他模块一般用2线(图1)或4线(图2)相连,它们分别是:
- TX:发送数据端,和对端的RX相连; - TX:发送数据端,和对端的RX相连;
- RX:接收数据端,和对端的TX相连; - RX:接收数据端,和对端的TX相连;
- RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连; - RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连;
- CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连; - CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连;
**图 1** 2线UART设备连接示意图<a name="fig68294715408"></a> **图1** 2线UART设备连接示意图
![](figures/2线UART设备连接示意图.png "2线UART设备连接示意图")
![zh-cn_image_0000001160812804](figures/zh-cn_image_0000001160812804.png)
**图 2** 4线UART设备连接示意图<a name="fig179241542163112"></a> **图2** 4线UART设备连接示意图
![](figures/4线UART设备连接示意图.png "4线UART设备连接示意图")
![zh-cn_image_0000001206372789](figures/zh-cn_image_0000001206372789.png)
- UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。 - UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。
- UART接口定义了操作UART端口的通用方法集合,包括获取、释放设备句柄、读写数据、获取和设置波特率、获取和设置设备属性。 - UART接口定义了操作UART端口的通用方法集合,包括获取、释放设备句柄、读写数据、获取和设置波特率、获取和设置设备属性。
## 接口说明<a name="section1928742202715"></a>
## 接口说明
**表 1** UART驱动API接口功能介绍
**表1** UART驱动API接口功能介绍
<a name="table1731550155318"></a>
<table><thead align="left"><tr id="row1223152681611"><th class="cellrowborder" valign="top" width="26.619999999999997%" id="mcps1.2.4.1.1"><p id="p210413571619"><a name="p210413571619"></a><a name="p210413571619"></a>功能分类</p> | 功能分类 | 接口名 |
</th> | -------- | -------- |
<th class="cellrowborder" valign="top" width="31.369999999999997%" id="mcps1.2.4.1.2"><p id="p810403511614"><a name="p810403511614"></a><a name="p810403511614"></a>接口名</p> | UART获取/释放设备句柄 | -&nbsp;UartOpen:UART获取设备句柄<br/>-&nbsp;UartClose:UART释放设备句柄 |
</th> | UART读写接口 | -&nbsp;UartRead:从UART设备中读取指定长度的数据<br/>-&nbsp;UartWrite:向UART设备中写入指定长度的数据 |
<th class="cellrowborder" valign="top" width="42.01%" id="mcps1.2.4.1.3"><p id="p110418354161"><a name="p110418354161"></a><a name="p110418354161"></a>描述</p> | UART获取/设置波特率接口 | -&nbsp;UartGetBaud:UART获取波特率<br/>-&nbsp;UartSetBaud:UART设置波特率 |
</th> | UART获取/设置设备属性 | -&nbsp;UartGetAttribute:UART获取设备属性<br/>-&nbsp;UartSetAttribute:UART设置设备属性 |
</tr> | UART设置传输模式 | UartSetTransMode:UART设置传输模式 |
</thead>
<tbody><tr id="row1638573613415"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p917154316414"><a name="p917154316414"></a><a name="p917154316414"></a>UART获取/释放设备句柄</p> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
<p id="p9596111154212"><a name="p9596111154212"></a><a name="p9596111154212"></a></p> > 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p20385163614412"><a name="p20385163614412"></a><a name="p20385163614412"></a>UartOpen</p>
</td> ## 使用指导
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p12101135184213"><a name="p12101135184213"></a><a name="p12101135184213"></a>UART获取设备句柄</p>
</td>
</tr> ### 使用流程
<tr id="row5950143316415"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p149501733134113"><a name="p149501733134113"></a><a name="p149501733134113"></a>UartClose</p>
</td> 使用UART的一般流程如下图所示。
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p371073520422"><a name="p371073520422"></a><a name="p371073520422"></a>UART释放设备句柄</p>
</td> **图3** UART使用流程图
</tr>
<tr id="row34145016535"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>UART读写接口</p> ![zh-cn_image_0000001206092753](figures/zh-cn_image_0000001206092753.png)
<p id="p131072201215"><a name="p131072201215"></a><a name="p131072201215"></a></p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p8296182221219"><a name="p8296182221219"></a><a name="p8296182221219"></a>UartRead</p> ### 获取UART设备句柄
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p16297172213125"><a name="p16297172213125"></a><a name="p16297172213125"></a>从UART设备中读取指定长度的数据</p>
</td>
</tr>
<tr id="row11585016539"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1095722493616"><a name="p1095722493616"></a><a name="p1095722493616"></a>UartWrite</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p15297162215122"><a name="p15297162215122"></a><a name="p15297162215122"></a>向UART设备中写入指定长度的数据</p>
</td>
</tr>
<tr id="row8687115843715"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p196317143813"><a name="p196317143813"></a><a name="p196317143813"></a>UART获取/设置波特率接口</p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p166885582375"><a name="p166885582375"></a><a name="p166885582375"></a>UartGetBaud</p>
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p13688358183716"><a name="p13688358183716"></a><a name="p13688358183716"></a>UART获取波特率</p>
</td>
</tr>
<tr id="row18987529382"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p698719214383"><a name="p698719214383"></a><a name="p698719214383"></a>UartSetBaud</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1398712123810"><a name="p1398712123810"></a><a name="p1398712123810"></a>UART设置波特率</p>
</td>
</tr>
<tr id="row1551850115317"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p1629782201218"><a name="p1629782201218"></a><a name="p1629782201218"></a>UART获取/设置设备属性</p>
<p id="p10308192211216"><a name="p10308192211216"></a><a name="p10308192211216"></a></p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p32972022151218"><a name="p32972022151218"></a><a name="p32972022151218"></a>UartGetAttribute</p>
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p13297122216123"><a name="p13297122216123"></a><a name="p13297122216123"></a>UART获取设备属性</p>
</td>
</tr>
<tr id="row7545065311"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p102974224120"><a name="p102974224120"></a><a name="p102974224120"></a>UartSetAttribute</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p152971322111219"><a name="p152971322111219"></a><a name="p152971322111219"></a>UART设置设备属性</p>
</td>
</tr>
<tr id="row14614115403"><td class="cellrowborder" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p1746281144010"><a name="p1746281144010"></a><a name="p1746281144010"></a>UART设置传输模式</p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p1146215112405"><a name="p1146215112405"></a><a name="p1146215112405"></a>UartSetTransMode</p>
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p11303181216414"><a name="p11303181216414"></a><a name="p11303181216414"></a>UART设置传输模式</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
## 使用指导<a name="section12779050105412"></a>
### 使用流程<a name="section1858116395510"></a>
使用UART的一般流程如[图3](#fig99673244388)所示。
**图 3** UART使用流程图<a name="fig99673244388"></a>
![](figures/UART使用流程图.png "UART使用流程图")
### 获取UART设备句柄<a name="section124512065617"></a>
在使用UART进行通信时,首先要调用UartOpen获取UART设备句柄,该函数会返回指定端口号的UART设备句柄。 在使用UART进行通信时,首先要调用UartOpen获取UART设备句柄,该函数会返回指定端口号的UART设备句柄。
DevHandle UartOpen\(uint32\_t port\);
```
**表 2** UartOpen参数和返回值描述 DevHandle UartOpen(uint32_t port);
```
<a name="table14222165114310"></a>
<table><thead align="left"><tr id="row1022175133111"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p13221551153117"><a name="p13221551153117"></a><a name="p13221551153117"></a>参数</p> **表2** UartOpen参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p122211251103111"><a name="p122211251103111"></a><a name="p122211251103111"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | port | UART设备号 |
</thead> | **返回值** | **返回值描述** |
<tbody><tr id="row6222451133114"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p92221518315"><a name="p92221518315"></a><a name="p92221518315"></a>port</p> | NULL | 获取UART设备句柄失败 |
</td> | 设备句柄 | UART设备句柄 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1322217518318"><a name="p1322217518318"></a><a name="p1322217518318"></a>UART设备号</p>
</td> 假设系统中的UART端口号为3,获取该UART设备句柄的示例如下:
</tr>
<tr id="row1122245153112"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p102221451123118"><a name="p102221451123118"></a><a name="p102221451123118"></a><strong id="b1922235110318"><a name="b1922235110318"></a><a name="b1922235110318"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1122215143113"><a name="p1122215143113"></a><a name="p1122215143113"></a><strong id="b19222205193117"><a name="b19222205193117"></a><a name="b19222205193117"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row522275114317"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p422235114313"><a name="p422235114313"></a><a name="p422235114313"></a>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p5222351203112"><a name="p5222351203112"></a><a name="p5222351203112"></a>获取UART设备句柄失败</p>
</td>
</tr>
<tr id="row1222212513311"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p5222125115316"><a name="p5222125115316"></a><a name="p5222125115316"></a>设备句柄</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p192228515311"><a name="p192228515311"></a><a name="p192228515311"></a>UART设备句柄</p>
</td>
</tr>
</tbody>
</table>
假设系统中的UART端口号为3,获取该UART设备句柄的示例如下:
``` ```
DevHandle handle = NULL; /* UART设备句柄 */ DevHandle handle = NULL; /* UART设备句柄 */
...@@ -172,51 +84,29 @@ if (handle == NULL) { ...@@ -172,51 +84,29 @@ if (handle == NULL) {
} }
``` ```
### UART设置波特率<a name="section86881004579"></a>
### UART设置波特率
在通信之前,需要设置UART的波特率,设置波特率的函数如下所示: 在通信之前,需要设置UART的波特率,设置波特率的函数如下所示:
int32\_t UartSetBaud\(DevHandle handle, uint32\_t baudRate\);
```
**表 3** UartSetBaud参数和返回值描述 int32_t UartSetBaud(DevHandle handle, uint32_t baudRate);
```
<a name="table539135313325"></a>
<table><thead align="left"><tr id="row15391205311323"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p11390453103216"><a name="p11390453103216"></a><a name="p11390453103216"></a>参数</p> **表3** UartSetBaud参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p839065316328"><a name="p839065316328"></a><a name="p839065316328"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | UART设备句柄 |
</thead> | baudRate | 待设置的波特率值 |
<tbody><tr id="row2039115373216"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1639165310324"><a name="p1639165310324"></a><a name="p1639165310324"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | UART设置波特率成功 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p539115320328"><a name="p539115320328"></a><a name="p539115320328"></a>UART设备句柄</p> | 负数 | UART设置波特率失败 |
</td>
</tr>
<tr id="row163911753143214"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p13911653203215"><a name="p13911653203215"></a><a name="p13911653203215"></a>baudRate</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p163919537322"><a name="p163919537322"></a><a name="p163919537322"></a>待设置的波特率值</p>
</td>
</tr>
<tr id="row539155343218"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1039185313321"><a name="p1039185313321"></a><a name="p1039185313321"></a><strong id="b139195343217"><a name="b139195343217"></a><a name="b139195343217"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p123911753143213"><a name="p123911753143213"></a><a name="p123911753143213"></a><strong id="b143911353163218"><a name="b143911353163218"></a><a name="b143911353163218"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row2391853153218"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17391185310322"><a name="p17391185310322"></a><a name="p17391185310322"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p14391653193210"><a name="p14391653193210"></a><a name="p14391653193210"></a>UART设置波特率成功</p>
</td>
</tr>
<tr id="row23912053143211"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7391165320321"><a name="p7391165320321"></a><a name="p7391165320321"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p639185318322"><a name="p639185318322"></a><a name="p639185318322"></a>UART设置波特率失败</p>
</td>
</tr>
</tbody>
</table>
假设需要设置的UART波特率为9600,设置波特率的实例如下: 假设需要设置的UART波特率为9600,设置波特率的实例如下:
``` ```
int32_t ret; int32_t ret;
/* 设置UART波特率 */ /* 设置UART波特率 */
...@@ -226,51 +116,29 @@ if (ret != 0) { ...@@ -226,51 +116,29 @@ if (ret != 0) {
} }
``` ```
### UART获取波特率<a name="section897032965712"></a>
### UART获取波特率
设置UART的波特率后,可以通过获取波特率接口来查看UART当前的波特率,获取波特率的函数如下所示: 设置UART的波特率后,可以通过获取波特率接口来查看UART当前的波特率,获取波特率的函数如下所示:
int32\_t UartGetBaud\(DevHandle handle, uint32\_t \*baudRate\);
```
**表 4** UartGetBaud参数和返回值描述 int32_t UartGetBaud(DevHandle handle, uint32_t *baudRate);
```
<a name="table20393185311326"></a>
<table><thead align="left"><tr id="row19392653123215"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p6392105315326"><a name="p6392105315326"></a><a name="p6392105315326"></a>参数</p> **表4** UartGetBaud参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p53920531329"><a name="p53920531329"></a><a name="p53920531329"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | UART设备句柄 |
</thead> | baudRate | 接收波特率值的指针 |
<tbody><tr id="row103921553103211"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1539220536326"><a name="p1539220536326"></a><a name="p1539220536326"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | UART获取波特率成功 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p6392553203217"><a name="p6392553203217"></a><a name="p6392553203217"></a>UART设备句柄</p> | 负数 | UART获取波特率失败 |
</td>
</tr>
<tr id="row1539211532322"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p93921053123210"><a name="p93921053123210"></a><a name="p93921053123210"></a>baudRate</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p93926536328"><a name="p93926536328"></a><a name="p93926536328"></a>接收波特率值的指针</p>
</td>
</tr>
<tr id="row1239318531326"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17392653123213"><a name="p17392653123213"></a><a name="p17392653123213"></a><strong id="b3392165383219"><a name="b3392165383219"></a><a name="b3392165383219"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1339365316327"><a name="p1339365316327"></a><a name="p1339365316327"></a><strong id="b63932053183218"><a name="b63932053183218"></a><a name="b63932053183218"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row143939531328"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p2393953153213"><a name="p2393953153213"></a><a name="p2393953153213"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p8393165383218"><a name="p8393165383218"></a><a name="p8393165383218"></a>UART获取波特率成功</p>
</td>
</tr>
<tr id="row5393105363210"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17393125363215"><a name="p17393125363215"></a><a name="p17393125363215"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1539325393211"><a name="p1539325393211"></a><a name="p1539325393211"></a>UART获取波特率失败</p>
</td>
</tr>
</tbody>
</table>
获取波特率的实例如下: 获取波特率的实例如下:
``` ```
int32_t ret; int32_t ret;
uint32_t baudRate; uint32_t baudRate;
...@@ -281,51 +149,29 @@ if (ret != 0) { ...@@ -281,51 +149,29 @@ if (ret != 0) {
} }
``` ```
### UART设置设备属性<a name="section129141884588"></a>
### UART设置设备属性
在通信之前,需要设置UART的设备属性,设置设备属性的函数如下图所示: 在通信之前,需要设置UART的设备属性,设置设备属性的函数如下图所示:
int32\_t UartSetAttribute\(DevHandle handle, struct UartAttribute \*attribute\)
```
**表 5** UartSetAttribute参数和返回值描述 int32_t UartSetAttribute(DevHandle handle, struct UartAttribute *attribute);
```
<a name="table1453119335341"></a>
<table><thead align="left"><tr id="row3530433103416"><th class="cellrowborder" valign="top" width="49.980000000000004%" id="mcps1.2.3.1.1"><p id="p1853073310341"><a name="p1853073310341"></a><a name="p1853073310341"></a>参数</p> **表5** UartSetAttribute参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50.019999999999996%" id="mcps1.2.3.1.2"><p id="p553083393417"><a name="p553083393417"></a><a name="p553083393417"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | UART设备句柄 |
</thead> | attribute | 待设置的设备属性 |
<tbody><tr id="row55303331347"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p1530113313341"><a name="p1530113313341"></a><a name="p1530113313341"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | UART设置设备属性成功 |
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p3530173313346"><a name="p3530173313346"></a><a name="p3530173313346"></a>UART设备句柄</p> | 负数 | UART设置设备属性失败 |
</td>
</tr>
<tr id="row45309337342"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p553083319348"><a name="p553083319348"></a><a name="p553083319348"></a>attribute</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p5530133314343"><a name="p5530133314343"></a><a name="p5530133314343"></a>待设置的设备属性</p>
</td>
</tr>
<tr id="row12530833103415"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p185309331345"><a name="p185309331345"></a><a name="p185309331345"></a><strong id="b145302033193410"><a name="b145302033193410"></a><a name="b145302033193410"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p145309332344"><a name="p145309332344"></a><a name="p145309332344"></a><strong id="b553018331348"><a name="b553018331348"></a><a name="b553018331348"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row14530203310348"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p1653014339343"><a name="p1653014339343"></a><a name="p1653014339343"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1453023323419"><a name="p1453023323419"></a><a name="p1453023323419"></a>UART设置设备属性成功</p>
</td>
</tr>
<tr id="row6531163373412"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p16530123310345"><a name="p16530123310345"></a><a name="p16530123310345"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1953118334347"><a name="p1953118334347"></a><a name="p1953118334347"></a>UART设置设备属性失败</p>
</td>
</tr>
</tbody>
</table>
设置UART的设备属性的实例如下: 设置UART的设备属性的实例如下:
``` ```
int32_t ret; int32_t ret;
struct UartAttribute attribute; struct UartAttribute attribute;
...@@ -343,51 +189,29 @@ if (ret != 0) { ...@@ -343,51 +189,29 @@ if (ret != 0) {
} }
``` ```
### UART获取设备属性<a name="section18689637165812"></a>
### UART获取设备属性
设置UART的设备属性后,可以通过获取设备属性接口来查看UART当前的设备属性,获取设备属性的函数如下图所示: 设置UART的设备属性后,可以通过获取设备属性接口来查看UART当前的设备属性,获取设备属性的函数如下图所示:
int32\_t UartGetAttribute\(DevHandle handle, struct UartAttribute \*attribute\);
```
**表 6** UartGetAttribute参数和返回值描述 int32_t UartGetAttribute(DevHandle handle, struct UartAttribute *attribute);
```
<a name="table17532123316342"></a>
<table><thead align="left"><tr id="row18531193383420"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p85311833143420"><a name="p85311833143420"></a><a name="p85311833143420"></a>参数</p> **表6** UartGetAttribute参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p17531103319348"><a name="p17531103319348"></a><a name="p17531103319348"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | UART设备句柄 |
</thead> | attribute | 接收UART设备属性的指针 |
<tbody><tr id="row35311533153413"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p453133333418"><a name="p453133333418"></a><a name="p453133333418"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | UART获取设备属性成功 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p753193323420"><a name="p753193323420"></a><a name="p753193323420"></a>UART设备句柄</p> | 负数 | UART获取设备属性失败 |
</td>
</tr>
<tr id="row1953103315344"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p35315333346"><a name="p35315333346"></a><a name="p35315333346"></a>attribute</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p14531633133416"><a name="p14531633133416"></a><a name="p14531633133416"></a>接收UART设备属性的指针</p>
</td>
</tr>
<tr id="row45321433143415"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p653273363417"><a name="p653273363417"></a><a name="p653273363417"></a><strong id="b19531153314349"><a name="b19531153314349"></a><a name="b19531153314349"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1653203312347"><a name="p1653203312347"></a><a name="p1653203312347"></a><strong id="b185321330348"><a name="b185321330348"></a><a name="b185321330348"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row175320339342"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p10532163383412"><a name="p10532163383412"></a><a name="p10532163383412"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p5532143319341"><a name="p5532143319341"></a><a name="p5532143319341"></a>UART获取设备属性成功</p>
</td>
</tr>
<tr id="row125327337340"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19532153317345"><a name="p19532153317345"></a><a name="p19532153317345"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p175321933163410"><a name="p175321933163410"></a><a name="p175321933163410"></a>UART获取设备属性失败</p>
</td>
</tr>
</tbody>
</table>
获取UART的设备属性的实例如下: 获取UART的设备属性的实例如下:
``` ```
int32_t ret; int32_t ret;
struct UartAttribute attribute; struct UartAttribute attribute;
...@@ -398,50 +222,28 @@ if (ret != 0) { ...@@ -398,50 +222,28 @@ if (ret != 0) {
} }
``` ```
### 设置UART传输模式<a name="section72713435918"></a>
### 设置UART传输模式
在通信之前,需要设置UART的传输模式,设置传输模式的函数如下图所示: 在通信之前,需要设置UART的传输模式,设置传输模式的函数如下图所示:
int32\_t UartSetTransMode\(DevHandle handle, enum UartTransMode mode\)
```
**表 7** UartSetTransMode参数和返回值描述 int32_t UartSetTransMode(DevHandle handle, enum UartTransMode mode);
```
<a name="table131892266313"></a>
<table><thead align="left"><tr id="row018922615318"><th class="cellrowborder" valign="top" width="49.980000000000004%" id="mcps1.2.3.1.1"><p id="p131891826835"><a name="p131891826835"></a><a name="p131891826835"></a>参数</p> **表7** UartSetTransMode参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50.019999999999996%" id="mcps1.2.3.1.2"><p id="p101894269314"><a name="p101894269314"></a><a name="p101894269314"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | UART设备句柄 |
</thead> | mode | 待设置的传输模式, |
<tbody><tr id="row11893261734"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p81897261333"><a name="p81897261333"></a><a name="p81897261333"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | UART设置传输模式成功 |
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p5190142618310"><a name="p5190142618310"></a><a name="p5190142618310"></a>UART设备句柄</p> | 负数 | UART设置传输模式失败 |
</td>
</tr> 假设需要设置的UART传输模式为UART_MODE_RD_BLOCK,设置传输模式的实例如下:
<tr id="row1119082615317"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p1519012261314"><a name="p1519012261314"></a><a name="p1519012261314"></a>mode</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p121901026632"><a name="p121901026632"></a><a name="p121901026632"></a>待设置的传输模式,</p>
</td>
</tr>
<tr id="row19190152612317"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p131900266316"><a name="p131900266316"></a><a name="p131900266316"></a><strong id="b61902026833"><a name="b61902026833"></a><a name="b61902026833"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1519022616315"><a name="p1519022616315"></a><a name="p1519022616315"></a><strong id="b319014261837"><a name="b319014261837"></a><a name="b319014261837"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row919016261932"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p10190526334"><a name="p10190526334"></a><a name="p10190526334"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1219012264318"><a name="p1219012264318"></a><a name="p1219012264318"></a>UART设置传输模式成功</p>
</td>
</tr>
<tr id="row1219017262313"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p15190162616316"><a name="p15190162616316"></a><a name="p15190162616316"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p131906262311"><a name="p131906262311"></a><a name="p131906262311"></a>UART设置传输模式失败</p>
</td>
</tr>
</tbody>
</table>
假设需要设置的UART传输模式为UART\_MODE\_RD\_BLOCK,设置传输模式的实例如下:
``` ```
int32_t ret; int32_t ret;
...@@ -452,56 +254,30 @@ if (ret != 0) { ...@@ -452,56 +254,30 @@ if (ret != 0) {
} }
``` ```
### 向UART设备写入指定长度的数据<a name="section128001736155919"></a>
### 向UART设备写入指定长度的数据
对应的接口函数如下所示: 对应的接口函数如下所示:
int32\_t UartWrite\(DevHandle handle, uint8\_t \*data, uint32\_t size\);
```
**表 8** UartWrite参数和返回值描述 int32_t UartWrite(DevHandle handle, uint8_t *data, uint32_t size);
```
<a name="table27825111368"></a>
<table><thead align="left"><tr id="row1578171123619"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p078112115360"><a name="p078112115360"></a><a name="p078112115360"></a>参数</p> **表8** UartWrite参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p37811711163612"><a name="p37811711163612"></a><a name="p37811711163612"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | UART设备句柄 |
</thead> | data | 待写入数据的指针 |
<tbody><tr id="row1878291143611"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p07818112360"><a name="p07818112360"></a><a name="p07818112360"></a>handle</p> | size | 待写入数据的长度 |
</td> | **返回值** | **返回值描述** |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p178281113369"><a name="p178281113369"></a><a name="p178281113369"></a>UART设备句柄</p> | 0 | UART写数据成功 |
</td> | 负数 | UART写数据失败 |
</tr>
<tr id="row7782811123614"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8782911173610"><a name="p8782911173610"></a><a name="p8782911173610"></a>data</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17782171120366"><a name="p17782171120366"></a><a name="p17782171120366"></a>待写入数据的指针</p>
</td>
</tr>
<tr id="row1578251112367"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p3782911183612"><a name="p3782911183612"></a><a name="p3782911183612"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17782161110366"><a name="p17782161110366"></a><a name="p17782161110366"></a>待写入数据的长度</p>
</td>
</tr>
<tr id="row1378281113363"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p87821411183616"><a name="p87821411183616"></a><a name="p87821411183616"></a><strong id="b157825113363"><a name="b157825113363"></a><a name="b157825113363"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p13782111116361"><a name="p13782111116361"></a><a name="p13782111116361"></a><strong id="b978211113366"><a name="b978211113366"></a><a name="b978211113366"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row47822112365"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p107821011103613"><a name="p107821011103613"></a><a name="p107821011103613"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p11782191103610"><a name="p11782191103610"></a><a name="p11782191103610"></a>UART写数据成功</p>
</td>
</tr>
<tr id="row11782911113611"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1578221111367"><a name="p1578221111367"></a><a name="p1578221111367"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p9782151110366"><a name="p9782151110366"></a><a name="p9782151110366"></a>UART写数据失败</p>
</td>
</tr>
</tbody>
</table>
写入指定长度数据的实例如下: 写入指定长度数据的实例如下:
``` ```
int32_t ret; int32_t ret;
uint8_t wbuff[5] = {1, 2, 3, 4, 5}; uint8_t wbuff[5] = {1, 2, 3, 4, 5};
...@@ -512,56 +288,30 @@ if (ret != 0) { ...@@ -512,56 +288,30 @@ if (ret != 0) {
} }
``` ```
### 从UART设备中读取指定长度的数据<a name="section92851601604"></a>
### 从UART设备中读取指定长度的数据
对应的接口函数如下所示: 对应的接口函数如下所示:
int32\_t UartRead\(DevHandle handle, uint8\_t \*data, uint32\_t size\);
```
**表 9** UartRead参数和返回值描述 int32_t UartRead(DevHandle handle, uint8_t *data, uint32_t size);
```
<a name="table162341717123713"></a>
<table><thead align="left"><tr id="row023313171377"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1123331710376"><a name="p1123331710376"></a><a name="p1123331710376"></a>参数</p> **表9** UartRead参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p523321783715"><a name="p523321783715"></a><a name="p523321783715"></a>参数描述</p> | 参数 | 参数描述 |
</th> | -------- | -------- |
</tr> | handle | UART设备句柄 |
</thead> | data | 接收读取数据的指针 |
<tbody><tr id="row6234417133712"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7233121716379"><a name="p7233121716379"></a><a name="p7233121716379"></a>handle</p> | size | 待读取数据的长度 |
</td> | **返回值** | **返回值描述** |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17234101753712"><a name="p17234101753712"></a><a name="p17234101753712"></a>UART设备句柄</p> | 非负数 | UART读取到的数据长度 |
</td> | 负数 | UART读取数据失败 |
</tr>
<tr id="row18234151718372"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16234191783711"><a name="p16234191783711"></a><a name="p16234191783711"></a>data</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p923417175378"><a name="p923417175378"></a><a name="p923417175378"></a>接收读取数据的指针</p>
</td>
</tr>
<tr id="row82341017193711"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p13234917103717"><a name="p13234917103717"></a><a name="p13234917103717"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p182341817153717"><a name="p182341817153717"></a><a name="p182341817153717"></a>待读取数据的长度</p>
</td>
</tr>
<tr id="row102341617123717"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p172341617163712"><a name="p172341617163712"></a><a name="p172341617163712"></a><strong id="b1323411179373"><a name="b1323411179373"></a><a name="b1323411179373"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1623431763718"><a name="p1623431763718"></a><a name="p1623431763718"></a><strong id="b1123411173377"><a name="b1123411173377"></a><a name="b1123411173377"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row4234151719372"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p3234131716375"><a name="p3234131716375"></a><a name="p3234131716375"></a>非负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p7234171783718"><a name="p7234171783718"></a><a name="p7234171783718"></a>UART读取到的数据长度</p>
</td>
</tr>
<tr id="row112340173378"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1423431743714"><a name="p1423431743714"></a><a name="p1423431743714"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p32349178378"><a name="p32349178378"></a><a name="p32349178378"></a>UART读取数据失败</p>
</td>
</tr>
</tbody>
</table>
读取指定长度数据的实例如下: 读取指定长度数据的实例如下:
``` ```
int32_t ret; int32_t ret;
uint8_t rbuff[5] = {0}; uint8_t rbuff[5] = {0};
...@@ -572,43 +322,38 @@ if (ret < 0) { ...@@ -572,43 +322,38 @@ if (ret < 0) {
} }
``` ```
>![](../public_sys-resources/icon-caution.gif) **注意:** > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:**
>UART返回值为非负值,表示UART读取成功。若返回值等于0,表示UART无有效数据可以读取。若返回值大于0,表示实际读取到的数据长度,该长度小于或等于传入的参数size的大小,并且不超过当前正在使用的UART控制器规定的最大单次读取数据长度的值。 > UART返回值为非负值,表示UART读取成功。若返回值等于0,表示UART无有效数据可以读取。若返回值大于0,表示实际读取到的数据长度,该长度小于或等于传入的参数size的大小,并且不超过当前正在使用的UART控制器规定的最大单次读取数据长度的值。
### 销毁UART设备句柄<a name="section1477410521406"></a> ### 销毁UART设备句柄
UART通信完成之后,需要销毁UART设备句柄,函数如下所示: UART通信完成之后,需要销毁UART设备句柄,函数如下所示:
void UartClose\(DevHandle handle\);
```
void UartClose(DevHandle handle);
```
该函数会释放申请的资源。 该函数会释放申请的资源。
**表 10** UartClose参数和返回值描述 **表10** UartClose参数和返回值描述
<a name="table03348317351"></a> | 参数 | 参数描述 |
<table><thead align="left"><tr id="row15334837351"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p933411316354"><a name="p933411316354"></a><a name="p933411316354"></a>参数</p> | -------- | -------- |
</th> | handle | UART设备句柄 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p16334103143517"><a name="p16334103143517"></a><a name="p16334103143517"></a>参数描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row733483103513"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7334530358"><a name="p7334530358"></a><a name="p7334530358"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p133341331356"><a name="p133341331356"></a><a name="p133341331356"></a>UART设备句柄</p>
</td>
</tr>
</tbody>
</table>
销毁UART设备句柄的实例如下: 销毁UART设备句柄的实例如下:
``` ```
UartClose(handle); /* 销毁UART设备句柄 * UartClose(handle); /* 销毁UART设备句柄 *
``` ```
## 使用实例<a name="section35404241311"></a>
UART设备完整的使用示例如下所示,首先获取UART设备句柄,接着设置波特率、设备属性和传输模式,之后进行UART通信,最后销毁UART设备句柄。 ## 使用实例
UART设备完整的使用示例如下所示,首先获取UART设备句柄,接着设置波特率、设备属性和传输模式,之后进行UART通信,最后销毁UART设备句柄。
``` ```
#include "hdf_log.h" #include "hdf_log.h"
...@@ -672,4 +417,3 @@ _ERR: ...@@ -672,4 +417,3 @@ _ERR:
UartClose(handle); UartClose(handle);
} }
``` ```
# UART<a name="ZH-CN_TOPIC_0000001222082257"></a> # UART
- [概述](#section1761881586154520)
- [接口说明](#section752964871810)
- [开发步骤](#section944397404154520)
- [开发实例](#section774610224154520)
## 概述<a name="section1761881586154520"></a> ## 概述
UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,在HDF框架中,UART的接口适配模式采用独立服务模式。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,在HDF框架中,UART的接口适配模式采用独立服务模式。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
**图 1** UART独立服务模式结构图<a name="fig1474518243468"></a> **图1** UART独立服务模式结构图
![](figures/独立服务模式结构图.png "UART独立服务模式结构图")
## 接口说明<a name="section752964871810"></a> ![zh-cn_image_0000001176603980](figures/zh-cn_image_0000001176603980.png)
## 接口说明
UartHostMethod定义: UartHostMethod定义:
``` ```
struct UartHostMethod { struct UartHostMethod {
int32_t (*Init)(struct UartHost *host); int32_t (*Init)(struct UartHost *host);
...@@ -31,165 +30,49 @@ struct UartHostMethod { ...@@ -31,165 +30,49 @@ struct UartHostMethod {
}; };
``` ```
**表 1** UartHostMethod结构体成员的回调函数功能说明 **表1** UartHostMethod结构体成员的回调函数功能说明
<a name="table22862114719"></a> | 函数 | 入参 | 出参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row5297211471"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p12291121134710"><a name="p12291121134710"></a><a name="p12291121134710"></a>函数</p> | -------- | -------- | -------- | -------- | -------- |
</th> | Init | host:&nbsp;结构体指针,核心层uart控制器; | 无 | HDF_STATUS相关状态 | 初始化Uart设备 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p3291921164712"><a name="p3291921164712"></a><a name="p3291921164712"></a>入参</p> | Deinit | host:&nbsp;结构体指针,核心层uart控制器; | 无 | HDF_STATUS相关状态 | 去初始化Uart设备 |
</th> | Read | host:&nbsp;结构体指针,核心层uart控制器;size:uint32_t,数据大小; | data:&nbsp;uint8_t指针,传出的数据 | HDF_STATUS相关状态 | 接收数据&nbsp;RX |
<th class="cellrowborder" valign="top" width="19.98%" id="mcps1.2.6.1.3"><p id="p15291321114718"><a name="p15291321114718"></a><a name="p15291321114718"></a>出参</p> | Write | host:&nbsp;结构体指针,核心层uart控制器;data:uint8_t指针,传入数据;size:uint32_t,数据大小; | 无 | HDF_STATUS相关状态 | 发送数据&nbsp;TX |
</th> | SetBaud | host:&nbsp;结构体指针,核心层uart控制器;baudRate:&nbsp;uint32_t指针,波特率传入值; | 无 | HDF_STATUS相关状态 | 设置波特率 |
<th class="cellrowborder" valign="top" width="20.02%" id="mcps1.2.6.1.4"><p id="p03092115478"><a name="p03092115478"></a><a name="p03092115478"></a>返回值</p> | GetBaud | host:&nbsp;结构体指针,核心层uart控制器; | baudRate:&nbsp;uint32_t指针,传出的波特率; | HDF_STATUS相关状态 | 获取当前设置的波特率 |
</th> | GetAttribute | host:&nbsp;结构体指针,核心层uart控制器; | attribute:&nbsp;结构体指针,传出的属性值(见uart_if.h中UartAttribute定义) | HDF_STATUS相关状态 | 获取设备uart相关属性 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p230172113475"><a name="p230172113475"></a><a name="p230172113475"></a>功能</p> | SetAttribute | host:&nbsp;结构体指针,核心层uart控制器;attribute:&nbsp;结构体指针,属性传入值; | 无 | HDF_STATUS相关状态 | 设置设备uart相关属性 |
</th> | SetTransMode | host:&nbsp;结构体指针,核心层uart控制器;mode:&nbsp;枚举值(见uart_if.h中UartTransMode定义),传输模式 | 无 | HDF_STATUS相关状态 | 设置传输模式 |
</tr> | PollEvent | host:&nbsp;结构体指针,核心层uart控制器;filep:&nbsp;void&nbsp;指针,file&nbsp;;table:&nbsp;void&nbsp;指针,poll_table&nbsp;; | 无 | HDF_STATUS相关状态 | poll机制 |
</thead>
<tbody><tr id="row13305217472"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p193012104714"><a name="p193012104714"></a><a name="p193012104714"></a>Init</p>
</td> ## 开发步骤
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p53082134713"><a name="p53082134713"></a><a name="p53082134713"></a>host: 结构体指针,核心层uart控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p14301121174719"><a name="p14301121174719"></a><a name="p14301121174719"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p83092116473"><a name="p83092116473"></a><a name="p83092116473"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p173032124713"><a name="p173032124713"></a><a name="p173032124713"></a>初始化Uart设备</p>
</td>
</tr>
<tr id="row530121144713"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p12301215474"><a name="p12301215474"></a><a name="p12301215474"></a>Deinit</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p14301921174718"><a name="p14301921174718"></a><a name="p14301921174718"></a>host: 结构体指针,核心层uart控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p143142110477"><a name="p143142110477"></a><a name="p143142110477"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p1531162174719"><a name="p1531162174719"></a><a name="p1531162174719"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p203162110478"><a name="p203162110478"></a><a name="p203162110478"></a>去初始化Uart设备</p>
</td>
</tr>
<tr id="row93172118476"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1231102194712"><a name="p1231102194712"></a><a name="p1231102194712"></a>Read</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p13318214472"><a name="p13318214472"></a><a name="p13318214472"></a>host: 结构体指针,核心层uart控制器;size:uint32_t,数据大小;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p1313213473"><a name="p1313213473"></a><a name="p1313213473"></a>data: uint8_t指针,传出的数据</p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p193110216473"><a name="p193110216473"></a><a name="p193110216473"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1331102115475"><a name="p1331102115475"></a><a name="p1331102115475"></a>接收数据 RX</p>
</td>
</tr>
<tr id="row1731102120479"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p731321204711"><a name="p731321204711"></a><a name="p731321204711"></a>Write</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p15311321204719"><a name="p15311321204719"></a><a name="p15311321204719"></a>host: 结构体指针,核心层uart控制器;data:uint8_t指针,传入数据;size:uint32_t,数据大小;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p143142114478"><a name="p143142114478"></a><a name="p143142114478"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p143212110477"><a name="p143212110477"></a><a name="p143212110477"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p123216211477"><a name="p123216211477"></a><a name="p123216211477"></a>发送数据 TX</p>
</td>
</tr>
<tr id="row73215214478"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1032112119475"><a name="p1032112119475"></a><a name="p1032112119475"></a>SetBaud</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p3321521134717"><a name="p3321521134717"></a><a name="p3321521134717"></a>host: 结构体指针,核心层uart控制器;baudRate: uint32_t指针,波特率传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p18327218478"><a name="p18327218478"></a><a name="p18327218478"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p23242111475"><a name="p23242111475"></a><a name="p23242111475"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p7321521114711"><a name="p7321521114711"></a><a name="p7321521114711"></a>设置波特率</p>
</td>
</tr>
<tr id="row113252104713"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p9323219476"><a name="p9323219476"></a><a name="p9323219476"></a>GetBaud</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p132821184711"><a name="p132821184711"></a><a name="p132821184711"></a>host: 结构体指针,核心层uart控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p63262112477"><a name="p63262112477"></a><a name="p63262112477"></a>baudRate: uint32_t指针,传出的波特率;</p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p13262174719"><a name="p13262174719"></a><a name="p13262174719"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p163232154717"><a name="p163232154717"></a><a name="p163232154717"></a>获取当前设置的波特率</p>
</td>
</tr>
<tr id="row2032102118472"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p9331321154714"><a name="p9331321154714"></a><a name="p9331321154714"></a>GetAttribute</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p15331721164715"><a name="p15331721164715"></a><a name="p15331721164715"></a>host: 结构体指针,核心层uart控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p23313219472"><a name="p23313219472"></a><a name="p23313219472"></a>attribute: 结构体指针,传出的属性值(见uart_if.h中UartAttribute定义)</p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p833142115476"><a name="p833142115476"></a><a name="p833142115476"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p63342119476"><a name="p63342119476"></a><a name="p63342119476"></a>获取设备uart相关属性</p>
</td>
</tr>
<tr id="row1133112144717"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p14331421114715"><a name="p14331421114715"></a><a name="p14331421114715"></a>SetAttribute</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p16331210473"><a name="p16331210473"></a><a name="p16331210473"></a>host: 结构体指针,核心层uart控制器;attribute: 结构体指针,属性传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p3331721204710"><a name="p3331721204710"></a><a name="p3331721204710"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p03302111471"><a name="p03302111471"></a><a name="p03302111471"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1933152113478"><a name="p1933152113478"></a><a name="p1933152113478"></a>设置设备uart相关属性</p>
</td>
</tr>
<tr id="row834221114716"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1934821104719"><a name="p1934821104719"></a><a name="p1934821104719"></a>SetTransMode</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1034621104717"><a name="p1034621104717"></a><a name="p1034621104717"></a>host: 结构体指针,核心层uart控制器;mode: 枚举值(见uart_if.h中UartTransMode定义),传输模式</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p173442110475"><a name="p173442110475"></a><a name="p173442110475"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p1734721194720"><a name="p1734721194720"></a><a name="p1734721194720"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p15341021194715"><a name="p15341021194715"></a><a name="p15341021194715"></a>设置传输模式</p>
</td>
</tr>
<tr id="row434192119479"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p133442184717"><a name="p133442184717"></a><a name="p133442184717"></a>PollEvent</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p634121104712"><a name="p634121104712"></a><a name="p634121104712"></a>host: 结构体指针,核心层uart控制器;filep: void 指针,file ;table: void 指针,poll_table ;</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p1334142111479"><a name="p1334142111479"></a><a name="p1334142111479"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p133472110473"><a name="p133472110473"></a><a name="p133472110473"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p63522174720"><a name="p63522174720"></a><a name="p63522174720"></a>poll机制</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section944397404154520"></a>
UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加uart\_config.hcs器件属性文件。 - 【可选】添加uart_config.hcs器件属性文件。
3. **实例化UART控制器对象:** 3. **实例化UART控制器对象:**
- 初始化UartHost成员。 - 初始化UartHost成员。
- 实例化UartHost成员UartHostMethod。 - 实例化UartHost成员UartHostMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化UartHost成员UartHostMethod,其定义和成员说明见[接口说明](#接口说明)。
>实例化UartHost成员UartHostMethod,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如UART控制状态,中断响应情况等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如UART控制状态,中断响应情况等。
## 开发实例<a name="section774610224154520"></a> ## 开发实例
下方将以uart\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 下方将以uart_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
UART驱动入口参考: UART驱动入口参考:
...@@ -206,11 +89,10 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -206,11 +89,10 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
HDF_INIT(g_hdfUartDevice); HDF_INIT(g_hdfUartDevice);
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 uart\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层UartHost成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 uart_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层UartHost成员的默认值或限制范围有密切关系。
本例只有一个UART控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在uart_config文件中增加对应的器件属性。
本例只有一个UART控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在uart\_config文件中增加对应的器件属性 - device_info.hcs 配置参考
- device\_info.hcs 配置参考。
``` ```
root { root {
...@@ -243,7 +125,8 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -243,7 +125,8 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
} }
``` ```
- uart\_config.hcs 配置参考。 - uart_config.hcs 配置参考。
``` ```
root { root {
...@@ -278,7 +161,8 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -278,7 +161,8 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
3. 完成驱动入口注册之后,最后一步就是以核心层UartHost对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化UartHost成员UartHostMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层UartHost对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化UartHost成员UartHostMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考。 - 自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且uart\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号等。 从驱动的角度看,自定义结构体是参数和数据的载体,而且uart_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号等。
``` ```
struct UartPl011Port { //接口相关的结构体 struct UartPl011Port { //接口相关的结构体
...@@ -324,9 +208,9 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -324,9 +208,9 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
struct UartHostMethod *method; //核心层钩子函数,厂商需要实现其成员函数功能并实例化 struct UartHostMethod *method; //核心层钩子函数,厂商需要实现其成员函数功能并实例化
}; };
``` ```
- UartHost成员回调函数结构体UartHostMethod的实例化,其他成员在Bind函数中初始化。 - UartHost成员回调函数结构体UartHostMethod的实例化,其他成员在Bind函数中初始化。
``` ```
// uart_hi35xx.c 中的示例:钩子函数的实例化 // uart_hi35xx.c 中的示例:钩子函数的实例化
struct UartHostMethod g_uartHostMethod = { struct UartHostMethod g_uartHostMethod = {
...@@ -349,56 +233,26 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -349,56 +233,26 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
HdfDeviceObject 这个是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 HdfDeviceObject 这个是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。
**返回值:** 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
**表 2** Bind函数入参和返回值 **表2** Bind函数入参和返回值
<a name="table69781823185619"></a> | 状态(值) | 问题描述 |
<table><thead align="left"><tr id="row997916234569"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p99801123205616"><a name="p99801123205616"></a><a name="p99801123205616"></a>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 控制器对象非法 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p698092355615"><a name="p698092355615"></a><a name="p698092355615"></a>问题描述</p> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</th> | HDF_ERR_INVALID_PARAM | 参数非法 |
</tr> | HDF_ERR_IO | I/O&nbsp;错误 |
</thead> | HDF_SUCCESS | 初始化成功 |
<tbody><tr id="row39803236568"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8980123175613"><a name="p8980123175613"></a><a name="p8980123175613"></a>HDF_ERR_INVALID_OBJECT</p> | HDF_FAILURE | 初始化失败 |
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p79801423165611"><a name="p79801423165611"></a><a name="p79801423165611"></a>控制器对象非法</p>
</td>
</tr>
<tr id="row3980023165617"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p698011239568"><a name="p698011239568"></a><a name="p698011239568"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p798082395610"><a name="p798082395610"></a><a name="p798082395610"></a>内存分配失败</p>
</td>
</tr>
<tr id="row10980223165610"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1980172365614"><a name="p1980172365614"></a><a name="p1980172365614"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p14980223145614"><a name="p14980223145614"></a><a name="p14980223145614"></a>参数非法</p>
</td>
</tr>
<tr id="row7980142315612"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17980152385611"><a name="p17980152385611"></a><a name="p17980152385611"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17980182385611"><a name="p17980182385611"></a><a name="p17980182385611"></a>I/O 错误</p>
</td>
</tr>
<tr id="row9980122312564"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p10981323155616"><a name="p10981323155616"></a><a name="p10981323155616"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p11981423175614"><a name="p11981423175614"></a><a name="p11981423175614"></a>初始化成功</p>
</td>
</tr>
<tr id="row15981122365618"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19981122311567"><a name="p19981122311567"></a><a name="p19981122311567"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p199811723105615"><a name="p199811723105615"></a><a name="p199811723105615"></a>初始化失败</p>
</td>
</tr>
</tbody>
</table>
函数说明: 函数说明:
初始化自定义结构体对象,初始化UartHost成员。 初始化自定义结构体对象,初始化UartHost成员。
``` ```
//uart_hi35xx.c //uart_hi35xx.c
static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device) static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device)
...@@ -425,18 +279,19 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -425,18 +279,19 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
- Init函数参考 - Init函数参考
入参**:** 入参:
HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。
返回值: 返回值:
HDF\_STATUS相关状态。 HDF_STATUS相关状态。
函数说明: 函数说明:
初始化自定义结构体对象,初始化UartHost成员,调用核心层UartAddDev函数,接入VFS。 初始化自定义结构体对象,初始化UartHost成员,调用核心层UartAddDev函数,接入VFS。
``` ```
int32_t HdfUartDeviceInit(struct HdfDeviceObject *device) int32_t HdfUartDeviceInit(struct HdfDeviceObject *device)
{ {
...@@ -494,7 +349,6 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -494,7 +349,6 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
return 0; return 0;
} }
``` ```
- Release函数参考 - Release函数参考
入参: 入参:
...@@ -507,7 +361,8 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -507,7 +361,8 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
函数说明: 函数说明:
该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。
``` ```
void HdfUartDeviceRelease(struct HdfDeviceObject *device) void HdfUartDeviceRelease(struct HdfDeviceObject *device)
...@@ -535,13 +390,10 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动 ...@@ -535,13 +390,10 @@ UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动
if (port->physBase != 0) { if (port->physBase != 0) {
OsalIoUnmap((void *)port->physBase);//地址反映射 OsalIoUnmap((void *)port->physBase);//地址反映射
} }
(void)OsalMemFree(port); OsalMemFree(port);
udd->private = NULL; udd->private = NULL;
} }
(void)OsalMemFree(udd);//释放UartDriverData OsalMemFree(udd);//释放UartDriverData
host->priv = NULL; host->priv = NULL;
} }
``` ```
# WATCHDOG<a name="ZH-CN_TOPIC_0000001206372825"></a> # WatchDog
- [概述](#section14918241977)
- [接口说明](#section1180575010271) ## 概述
- [使用指导](#section10103184312813)
- [使用流程](#section10181195910815) 看门狗(Watchdog),又叫看门狗计时器(Watchdog timer),是一种硬件的计时设备。当系统主程序发生错误导致未及时清除看门狗计时器的计时值时,看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。
- [打开看门狗设备](#section66089201107)
- [获取看门狗状态](#section786624341011)
- [设置超时时间](#section182386137111) ## 接口说明
- [获取超时时间](#section1883310371114)
- [启动看门狗](#section82501405123) **表1** 看门狗API接口功能介绍
- [喂狗](#section3547530101211)
- [停止看门狗](#section944595841217) | 功能分类 | 接口描述 |
- [关闭看门狗设备](#section96561824121311) | -------- | -------- |
| 打开/关闭看门狗 | WatchdogOpen:打开看门狗设备<br/>WatchdogClose:关闭看门狗设备 |
- [使用实例](#section1724514523135) | 启动/停止看门狗 | WatchdogStart:启动看门狗<br/>WatchdogStop:停止看门狗 |
| 设置/获取超时时间 | WatchdogSetTimeout:设置看门狗超时时间<br/>WatchdogGetTimeout:获取看门狗超时时间 |
## 概述<a name="section14918241977"></a> | 获取看门狗状态 | WatchdogGetStatus:获取看门狗状态 |
| 清除看门狗定时器 | WatchdogFeed:清除看门狗定时器(喂狗) |
看门狗(watchdog),又叫看门狗计时器(watchdog timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器的计时值,这时看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
## 接口说明<a name="section1180575010271"></a> > 本文涉及的看门狗的所有接口,仅限内核态使用,不支持在用户态使用。
**表 1** 看门狗 API接口功能介绍
## 使用指导
<a name="table1731550155318"></a>
<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" valign="top" width="26.619999999999997%" 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="32.800000000000004%" 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="40.58%" id="mcps1.2.4.1.3"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>描述</p>
</th> **图1** 看门狗使用流程图
</tr> ![zh-cn_image_0000001160652842](figures/zh-cn_image_0000001160652842.png)
</thead>
<tbody><tr id="row837081981712"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p681292481718"><a name="p681292481718"></a><a name="p681292481718"></a>打开/关闭看门狗</p>
</td> ### 打开看门狗设备
<td class="cellrowborder" valign="top" width="32.800000000000004%" headers="mcps1.2.4.1.2 "><p id="p183701419141710"><a name="p183701419141710"></a><a name="p183701419141710"></a>WatchdogOpen</p>
</td>
<td class="cellrowborder" valign="top" width="40.58%" headers="mcps1.2.4.1.3 "><p id="p17370161911710"><a name="p17370161911710"></a><a name="p17370161911710"></a>打开看门狗设备</p>
</td>
</tr>
<tr id="row5610415171719"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p661171510173"><a name="p661171510173"></a><a name="p661171510173"></a>WatchdogClose</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p11611715161713"><a name="p11611715161713"></a><a name="p11611715161713"></a>关闭看门狗设备</p>
</td>
</tr>
<tr id="row337105133315"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p07631557153319"><a name="p07631557153319"></a><a name="p07631557153319"></a>启动/停止看门狗</p>
</td>
<td class="cellrowborder" valign="top" width="32.800000000000004%" headers="mcps1.2.4.1.2 "><p id="p163765113337"><a name="p163765113337"></a><a name="p163765113337"></a>WatchdogStart</p>
</td>
<td class="cellrowborder" valign="top" width="40.58%" headers="mcps1.2.4.1.3 "><p id="p18376517332"><a name="p18376517332"></a><a name="p18376517332"></a>启动看门狗</p>
</td>
</tr>
<tr id="row18399184610337"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1740010461335"><a name="p1740010461335"></a><a name="p1740010461335"></a>WatchdogStop</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p19400194633318"><a name="p19400194633318"></a><a name="p19400194633318"></a>停止看门狗</p>
</td>
</tr>
<tr id="row34145016535"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>设置/获取超时时间</p>
</td>
<td class="cellrowborder" valign="top" width="32.800000000000004%" headers="mcps1.2.4.1.2 "><p id="p8296182221219"><a name="p8296182221219"></a><a name="p8296182221219"></a>WatchdogSetTimeout</p>
</td>
<td class="cellrowborder" valign="top" width="40.58%" headers="mcps1.2.4.1.3 "><p id="p16297172213125"><a name="p16297172213125"></a><a name="p16297172213125"></a>设置看门狗超时时间</p>
</td>
</tr>
<tr id="row11585016539"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1095722493616"><a name="p1095722493616"></a><a name="p1095722493616"></a>WatchdogGetTimeout</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p15297162215122"><a name="p15297162215122"></a><a name="p15297162215122"></a>获取看门狗超时时间</p>
</td>
</tr>
<tr id="row105701653185811"><td class="cellrowborder" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p2571145325819"><a name="p2571145325819"></a><a name="p2571145325819"></a>获取看门狗状态</p>
</td>
<td class="cellrowborder" valign="top" width="32.800000000000004%" headers="mcps1.2.4.1.2 "><p id="p175711953195814"><a name="p175711953195814"></a><a name="p175711953195814"></a>WatchdogGetStatus</p>
</td>
<td class="cellrowborder" valign="top" width="40.58%" headers="mcps1.2.4.1.3 "><p id="p331961319210"><a name="p331961319210"></a><a name="p331961319210"></a>获取看门狗状态</p>
</td>
</tr>
<tr id="row1028182217215"><td class="cellrowborder" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p182818227214"><a name="p182818227214"></a><a name="p182818227214"></a>清除看门狗定时器</p>
</td>
<td class="cellrowborder" valign="top" width="32.800000000000004%" headers="mcps1.2.4.1.2 "><p id="p17281223219"><a name="p17281223219"></a><a name="p17281223219"></a>WatchdogFeed</p>
</td>
<td class="cellrowborder" valign="top" width="40.58%" headers="mcps1.2.4.1.3 "><p id="p62815221125"><a name="p62815221125"></a><a name="p62815221125"></a>清除看门狗定时器(喂狗)</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **说明:**
>本文涉及看门狗的所有接口,仅限内核态使用,不支持在用户态使用。
## 使用指导<a name="section10103184312813"></a>
### 使用流程<a name="section10181195910815"></a>
使用看门狗的一般流程如[图1](#fig430533913392)所示。
**图 1** 看门狗使用流程图<a name="fig430533913392"></a>
![](figures/看门狗使用流程图.png "看门狗使用流程图")
### 打开看门狗设备<a name="section66089201107"></a>
在操作看门狗之前,需要使用WatchdogOpen打开一个看门狗设备,一个系统可能有多个看门狗,通过ID号来打开指定的看门狗设备: 在操作看门狗之前,需要使用WatchdogOpen打开一个看门狗设备,一个系统可能有多个看门狗,通过ID号来打开指定的看门狗设备:
DevHandle WatchdogOpen\(int16\_t wdtId\);
```
**表 2** WatchdogOpen参数和返回值描述 DevHandle WatchdogOpen(int16_t wdtId);
```
<a name="table1413702552814"></a>
<table><thead align="left"><tr id="row131371325142819"><th class="cellrowborder" valign="top" width="44.99%" id="mcps1.2.3.1.1"><p id="p191372254283"><a name="p191372254283"></a><a name="p191372254283"></a><strong id="b1913716253285"><a name="b1913716253285"></a><a name="b1913716253285"></a>参数</strong></p> **表2** WatchdogOpen参数和返回值描述
</th>
<th class="cellrowborder" valign="top" width="55.010000000000005%" id="mcps1.2.3.1.2"><p id="p113819255284"><a name="p113819255284"></a><a name="p113819255284"></a><strong id="b151381725172812"><a name="b151381725172812"></a><a name="b151381725172812"></a>参数描述</strong></p> | **参数** | **参数描述** |
</th> | -------- | -------- |
</tr> | wdtId | 看门狗设备号 |
</thead> | **返回值** | **返回值描述** |
<tbody><tr id="row813812259282"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p101381625162813"><a name="p101381625162813"></a><a name="p101381625162813"></a>wdtId</p> | NULL | 打开失败 |
</td> | DevHandle类型指针 | 看门狗设备句柄 |
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p191381425142813"><a name="p191381425142813"></a><a name="p191381425142813"></a>看门狗设备号</p>
</td>
</tr>
<tr id="row2138202515281"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p141387252287"><a name="p141387252287"></a><a name="p141387252287"></a><strong id="b11381325172810"><a name="b11381325172810"></a><a name="b11381325172810"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p12138192512281"><a name="p12138192512281"></a><a name="p12138192512281"></a><strong id="b81380254286"><a name="b81380254286"></a><a name="b81380254286"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row9138182519287"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p5138102532814"><a name="p5138102532814"></a><a name="p5138102532814"></a>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p3138192512815"><a name="p3138192512815"></a><a name="p3138192512815"></a>打开失败</p>
</td>
</tr>
<tr id="row15138192518283"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p1850115512916"><a name="p1850115512916"></a><a name="p1850115512916"></a>DevHandle类型指针</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p16138122512817"><a name="p16138122512817"></a><a name="p16138122512817"></a>看门狗设备句柄</p>
</td>
</tr>
</tbody>
</table>
``` ```
DevHandle handle = NULL; DevHandle handle = NULL;
...@@ -144,46 +61,24 @@ if (handle == NULL) { ...@@ -144,46 +61,24 @@ if (handle == NULL) {
} }
``` ```
### 获取看门狗状态<a name="section786624341011"></a>
### 获取看门狗状态
int32\_t WatchdogGetStatus\(DevHandle handle, int32\_t \*status\);
**表 3** WatchdogGetStatus参数和返回值描述 ```
int32_t WatchdogGetStatus(DevHandle handle, int32_t *status);
<a name="table1018490043"></a> ```
<table><thead align="left"><tr id="row31848013417"><th class="cellrowborder" valign="top" width="44.99%" id="mcps1.2.3.1.1"><p id="p1415816132411"><a name="p1415816132411"></a><a name="p1415816132411"></a><strong id="b129796117337"><a name="b129796117337"></a><a name="b129796117337"></a>参数</strong></p>
</th> **表3** WatchdogGetStatus参数和返回值描述
<th class="cellrowborder" valign="top" width="55.010000000000005%" id="mcps1.2.3.1.2"><p id="p11158111316410"><a name="p11158111316410"></a><a name="p11158111316410"></a><strong id="b1699118123314"><a name="b1699118123314"></a><a name="b1699118123314"></a>参数描述</strong></p>
</th> | **参数** | **参数描述** |
</tr> | -------- | -------- |
</thead> | handle | 看门狗设备句柄 |
<tbody><tr id="row3264122711222"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p15264727182211"><a name="p15264727182211"></a><a name="p15264727182211"></a>handle</p> | status | 获取到的看门狗状态的指针 |
</td> | **返回值** | **返回值描述** |
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p2026452772210"><a name="p2026452772210"></a><a name="p2026452772210"></a>看门狗设备句柄</p> | 0 | 获取成功 |
</td> | 负数 | 获取失败 |
</tr>
<tr id="row928111518418"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p4282955412"><a name="p4282955412"></a><a name="p4282955412"></a>status</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p7282752412"><a name="p7282752412"></a><a name="p7282752412"></a>获取到的启动状态指针</p>
</td>
</tr>
<tr id="row17393154515328"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p8158313248"><a name="p8158313248"></a><a name="p8158313248"></a><strong id="b18542051332"><a name="b18542051332"></a><a name="b18542051332"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p161591413741"><a name="p161591413741"></a><a name="p161591413741"></a><strong id="b45520523313"><a name="b45520523313"></a><a name="b45520523313"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row339324593215"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p103191916578"><a name="p103191916578"></a><a name="p103191916578"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p1231981611712"><a name="p1231981611712"></a><a name="p1231981611712"></a>获取成功</p>
</td>
</tr>
<tr id="row15393184519323"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p531916166716"><a name="p531916166716"></a><a name="p531916166716"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p93191161174"><a name="p93191161174"></a><a name="p93191161174"></a>获取失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -196,46 +91,24 @@ if (ret != 0) { ...@@ -196,46 +91,24 @@ if (ret != 0) {
} }
``` ```
### 设置超时时间<a name="section182386137111"></a>
### 设置超时时间
int32\_t WatchdogSetTimeout\(DevHandle \*handle, uint32\_t seconds\);
**表 4** WatchdogSetTimeout参数和返回值描述 ```
int32_t WatchdogSetTimeout(DevHandle *handle, uint32_t seconds);
<a name="table9159112182210"></a> ```
<table><thead align="left"><tr id="row1216012212212"><th class="cellrowborder" valign="top" width="44.99%" id="mcps1.2.3.1.1"><p id="p1416017262215"><a name="p1416017262215"></a><a name="p1416017262215"></a><strong id="b181604212216"><a name="b181604212216"></a><a name="b181604212216"></a>参数</strong></p>
</th> **表4** WatchdogSetTimeout参数和返回值描述
<th class="cellrowborder" valign="top" width="55.010000000000005%" id="mcps1.2.3.1.2"><p id="p16160182192213"><a name="p16160182192213"></a><a name="p16160182192213"></a><strong id="b16160142162216"><a name="b16160142162216"></a><a name="b16160142162216"></a>参数描述</strong></p>
</th> | **参数** | **参数描述** |
</tr> | -------- | -------- |
</thead> | handle | 看门狗设备句柄 |
<tbody><tr id="row199536232314"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p17685481236"><a name="p17685481236"></a><a name="p17685481236"></a>handle</p> | seconds | 超时时间,单位为秒 |
</td> | **返回值** | **返回值描述** |
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p196852811232"><a name="p196852811232"></a><a name="p196852811232"></a>看门狗设备句柄</p> | 0 | 设置成功 |
</td> | 负数 | 设置失败 |
</tr>
<tr id="row141601729228"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p191601126226"><a name="p191601126226"></a><a name="p191601126226"></a>seconds</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p5160172182214"><a name="p5160172182214"></a><a name="p5160172182214"></a>超时时间,单位为秒</p>
</td>
</tr>
<tr id="row18160192172212"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p101601123222"><a name="p101601123222"></a><a name="p101601123222"></a><strong id="b516062172215"><a name="b516062172215"></a><a name="b516062172215"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p17160192182212"><a name="p17160192182212"></a><a name="p17160192182212"></a><strong id="b141601022227"><a name="b141601022227"></a><a name="b141601022227"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row171600202220"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p121601226224"><a name="p121601226224"></a><a name="p121601226224"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p151607218222"><a name="p151607218222"></a><a name="p151607218222"></a>设置成功</p>
</td>
</tr>
<tr id="row916012252211"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p19160026224"><a name="p19160026224"></a><a name="p19160026224"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p816092142210"><a name="p816092142210"></a><a name="p816092142210"></a>设置失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -248,46 +121,24 @@ if (ret != 0) { ...@@ -248,46 +121,24 @@ if (ret != 0) {
} }
``` ```
### 获取超时时间<a name="section1883310371114"></a>
### 获取超时时间
int32\_t WatchdogGetTimeout\(DevHandle \*handle, uint32\_t \*seconds\);
**表 5** WatchdogGetTimeout参数和返回值描述 ```
int32_t WatchdogGetTimeout(DevHandle *handle, uint32_t *seconds);
<a name="table10147164819233"></a> ```
<table><thead align="left"><tr id="row14147848142313"><th class="cellrowborder" valign="top" width="44.99%" id="mcps1.2.3.1.1"><p id="p4147124892316"><a name="p4147124892316"></a><a name="p4147124892316"></a><strong id="b214784813238"><a name="b214784813238"></a><a name="b214784813238"></a>参数</strong></p>
</th> **表5** WatchdogGetTimeout参数和返回值描述
<th class="cellrowborder" valign="top" width="55.010000000000005%" id="mcps1.2.3.1.2"><p id="p12147144817232"><a name="p12147144817232"></a><a name="p12147144817232"></a><strong id="b51476482234"><a name="b51476482234"></a><a name="b51476482234"></a>参数描述</strong></p>
</th> | **参数** | **参数描述** |
</tr> | -------- | -------- |
</thead> | handle | 看门狗设备句柄 |
<tbody><tr id="row8147124819230"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p21471248142313"><a name="p21471248142313"></a><a name="p21471248142313"></a>handle</p> | seconds | 接收超时时间的指针,单位为秒 |
</td> | **返回值** | **返回值描述** |
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p12147134815233"><a name="p12147134815233"></a><a name="p12147134815233"></a>看门狗设备句柄</p> | 0 | 获取成功 |
</td> | 负数 | 获取失败 |
</tr>
<tr id="row514754818232"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p1614713484235"><a name="p1614713484235"></a><a name="p1614713484235"></a>seconds</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p71478484238"><a name="p71478484238"></a><a name="p71478484238"></a>接收超时时间的指针,单位为秒</p>
</td>
</tr>
<tr id="row214784814239"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p5147848152314"><a name="p5147848152314"></a><a name="p5147848152314"></a><strong id="b17147124822310"><a name="b17147124822310"></a><a name="b17147124822310"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p914724811236"><a name="p914724811236"></a><a name="p914724811236"></a><strong id="b614704813231"><a name="b614704813231"></a><a name="b614704813231"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row714744892312"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p1014764832315"><a name="p1014764832315"></a><a name="p1014764832315"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p1314824872310"><a name="p1314824872310"></a><a name="p1314824872310"></a>获取成功</p>
</td>
</tr>
<tr id="row1514884815230"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p10148114822319"><a name="p10148114822319"></a><a name="p10148114822319"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p1314864822311"><a name="p1314864822311"></a><a name="p1314864822311"></a>获取失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -300,41 +151,23 @@ if (ret != 0) { ...@@ -300,41 +151,23 @@ if (ret != 0) {
} }
``` ```
### 启动看门狗<a name="section82501405123"></a>
### 启动看门狗
int32\_t WatchdogStart\(DevHandle handle\);
**表 6** WatchdogStart参数和返回值描述 ```
int32_t WatchdogStart(DevHandle handle);
<a name="table529165182515"></a> ```
<table><thead align="left"><tr id="row92915122513"><th class="cellrowborder" valign="top" width="44.99%" id="mcps1.2.3.1.1"><p id="p5292582517"><a name="p5292582517"></a><a name="p5292582517"></a><strong id="b12293510259"><a name="b12293510259"></a><a name="b12293510259"></a>参数</strong></p>
</th> **表6** WatchdogStart参数和返回值描述
<th class="cellrowborder" valign="top" width="55.010000000000005%" id="mcps1.2.3.1.2"><p id="p929554258"><a name="p929554258"></a><a name="p929554258"></a><strong id="b82913542514"><a name="b82913542514"></a><a name="b82913542514"></a>参数描述</strong></p>
</th> | **参数** | **参数描述** |
</tr> | -------- | -------- |
</thead> | handle | 看门狗设备句柄 |
<tbody><tr id="row629852250"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p22975122515"><a name="p22975122515"></a><a name="p22975122515"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | 启动成功 |
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p7290515256"><a name="p7290515256"></a><a name="p7290515256"></a>看门狗设备句柄</p> | 负数 | 启动失败 |
</td>
</tr>
<tr id="row183035162514"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p8302511255"><a name="p8302511255"></a><a name="p8302511255"></a><strong id="b183018513251"><a name="b183018513251"></a><a name="b183018513251"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p16307522515"><a name="p16307522515"></a><a name="p16307522515"></a><strong id="b23010542510"><a name="b23010542510"></a><a name="b23010542510"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row12305552510"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p1730175132513"><a name="p1730175132513"></a><a name="p1730175132513"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p630754259"><a name="p630754259"></a><a name="p630754259"></a>启动成功</p>
</td>
</tr>
<tr id="row4306516252"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p15304502515"><a name="p15304502515"></a><a name="p15304502515"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p0301559254"><a name="p0301559254"></a><a name="p0301559254"></a>启动失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -346,41 +179,23 @@ if (ret != 0) { ...@@ -346,41 +179,23 @@ if (ret != 0) {
} }
``` ```
### 喂狗<a name="section3547530101211"></a>
### 喂狗
int32\_t WatchdogFeed\(DevHandle handle\);
**表 7** WatchdogFeed参数和返回值描述 ```
int32_t WatchdogFeed(DevHandle handle);
<a name="table091163515394"></a> ```
<table><thead align="left"><tr id="row891133515393"><th class="cellrowborder" valign="top" width="44.99%" id="mcps1.2.3.1.1"><p id="p1911143513918"><a name="p1911143513918"></a><a name="p1911143513918"></a><strong id="b1791193553911"><a name="b1791193553911"></a><a name="b1791193553911"></a>参数</strong></p>
</th> **表7** WatchdogFeed参数和返回值描述
<th class="cellrowborder" valign="top" width="55.010000000000005%" id="mcps1.2.3.1.2"><p id="p1191173553917"><a name="p1191173553917"></a><a name="p1191173553917"></a><strong id="b4911835183910"><a name="b4911835183910"></a><a name="b4911835183910"></a>参数描述</strong></p>
</th> | **参数** | **参数描述** |
</tr> | -------- | -------- |
</thead> | handle | 看门狗设备句柄 |
<tbody><tr id="row189111635143918"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p189111435173917"><a name="p189111435173917"></a><a name="p189111435173917"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | 喂狗成功 |
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p11911143511397"><a name="p11911143511397"></a><a name="p11911143511397"></a>看门狗设备句柄</p> | 负数 | 喂狗失败 |
</td>
</tr>
<tr id="row15911835173916"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p7911123516396"><a name="p7911123516396"></a><a name="p7911123516396"></a><strong id="b59112352394"><a name="b59112352394"></a><a name="b59112352394"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p169118356399"><a name="p169118356399"></a><a name="p169118356399"></a><strong id="b1091193593910"><a name="b1091193593910"></a><a name="b1091193593910"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row189119352393"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p1391113513917"><a name="p1391113513917"></a><a name="p1391113513917"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p149111435143911"><a name="p149111435143911"></a><a name="p149111435143911"></a>喂狗成功</p>
</td>
</tr>
<tr id="row5911123520392"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p49111335143920"><a name="p49111335143920"></a><a name="p49111335143920"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p1891216356391"><a name="p1891216356391"></a><a name="p1891216356391"></a>喂狗失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -392,41 +207,23 @@ if (ret != 0) { ...@@ -392,41 +207,23 @@ if (ret != 0) {
} }
``` ```
### 停止看门狗<a name="section944595841217"></a>
### 停止看门狗
int32\_t WatchdogStop\(DevHandle handle\);
**表 8** WatchdogStop参数和返回值描述 ```
int32_t WatchdogStop(DevHandle handle);
<a name="table1286810515254"></a> ```
<table><thead align="left"><tr id="row28687517259"><th class="cellrowborder" valign="top" width="44.99%" id="mcps1.2.3.1.1"><p id="p6868185120254"><a name="p6868185120254"></a><a name="p6868185120254"></a><strong id="b986815142510"><a name="b986815142510"></a><a name="b986815142510"></a>参数</strong></p>
</th> **表8** WatchdogStop参数和返回值描述
<th class="cellrowborder" valign="top" width="55.010000000000005%" id="mcps1.2.3.1.2"><p id="p15868185114252"><a name="p15868185114252"></a><a name="p15868185114252"></a><strong id="b148681451142517"><a name="b148681451142517"></a><a name="b148681451142517"></a>参数描述</strong></p>
</th> | **参数** | **参数描述** |
</tr> | -------- | -------- |
</thead> | handle | 看门狗设备句柄 |
<tbody><tr id="row1868165114256"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p6869105115256"><a name="p6869105115256"></a><a name="p6869105115256"></a>handle</p> | **返回值** | **返回值描述** |
</td> | 0 | 停止成功 |
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p19869951202513"><a name="p19869951202513"></a><a name="p19869951202513"></a>看门狗设备句柄</p> | 负数 | 停止失败 |
</td>
</tr>
<tr id="row68696510259"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p2869165114256"><a name="p2869165114256"></a><a name="p2869165114256"></a><strong id="b386935117258"><a name="b386935117258"></a><a name="b386935117258"></a>返回值</strong></p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p158691551142517"><a name="p158691551142517"></a><a name="p158691551142517"></a><strong id="b78691751152513"><a name="b78691751152513"></a><a name="b78691751152513"></a>返回值描述</strong></p>
</td>
</tr>
<tr id="row9869851192516"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p686916516252"><a name="p686916516252"></a><a name="p686916516252"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p7869115192510"><a name="p7869115192510"></a><a name="p7869115192510"></a>停止成功</p>
</td>
</tr>
<tr id="row15869951122519"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p486925112518"><a name="p486925112518"></a><a name="p486925112518"></a>负数</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p086945172518"><a name="p086945172518"></a><a name="p086945172518"></a>停止失败</p>
</td>
</tr>
</tbody>
</table>
``` ```
int32_t ret; int32_t ret;
...@@ -438,44 +235,40 @@ if (ret != 0) { ...@@ -438,44 +235,40 @@ if (ret != 0) {
} }
``` ```
### 关闭看门狗设备<a name="section96561824121311"></a>
### 关闭看门狗设备
当操作完毕时,使用WatchdogClose关闭打开的设备句柄: 当操作完毕时,使用WatchdogClose关闭打开的设备句柄:
void WatchdogClose\(DevHandle handle\);
**表 9** WatchdogClose参数和返回值描述 ```
void WatchdogClose(DevHandle handle);
```
**表9** WatchdogClose参数和返回值描述
| **参数** | **参数描述** |
| -------- | -------- |
| handle | 看门狗设备句柄 |
<a name="table1017315185320"></a>
<table><thead align="left"><tr id="row417314182327"><th class="cellrowborder" valign="top" width="44.99%" id="mcps1.2.3.1.1"><p id="p117310184320"><a name="p117310184320"></a><a name="p117310184320"></a><strong id="b141734185327"><a name="b141734185327"></a><a name="b141734185327"></a>参数</strong></p>
</th>
<th class="cellrowborder" valign="top" width="55.010000000000005%" id="mcps1.2.3.1.2"><p id="p7173191812324"><a name="p7173191812324"></a><a name="p7173191812324"></a><strong id="b2017318188327"><a name="b2017318188327"></a><a name="b2017318188327"></a>参数描述</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row1617331823211"><td class="cellrowborder" valign="top" width="44.99%" headers="mcps1.2.3.1.1 "><p id="p17173191811326"><a name="p17173191811326"></a><a name="p17173191811326"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="55.010000000000005%" headers="mcps1.2.3.1.2 "><p id="p538814308323"><a name="p538814308323"></a><a name="p538814308323"></a>看门狗设备句柄</p>
</td>
</tr>
</tbody>
</table>
``` ```
/* 关闭看门狗 */ /* 关闭看门狗 */
ret = WatchdogClose(handle); ret = WatchdogClose(handle);
``` ```
## 使用实例<a name="section1724514523135"></a>
## 使用实例
本例程提供看门狗的完整使用流程。 本例程提供看门狗的完整使用流程。
在本例程中,我们打开一个看门狗设备,设置超时时间并启动计时: 在本例程中,我们打开一个看门狗设备,设置超时时间并启动计时:
- 首先定期喂狗,即按时清除看门狗定时器,确保系统不会因定时器超时而复位。 - 首先定期喂狗,即按时清除看门狗定时器,确保系统不会因定时器超时而复位。
- 接着再停止喂狗,观察定时器到期后系统是否发生复位行为。 - 接着再停止喂狗,观察定时器到期后系统是否发生复位行为。
示例如下: 示例如下:
``` ```
#include "watchdog_if.h" #include "watchdog_if.h"
...@@ -496,7 +289,7 @@ static int32_t TestCaseWatchdog(void) ...@@ -496,7 +289,7 @@ static int32_t TestCaseWatchdog(void)
/* 打开0号看门狗设备 */ /* 打开0号看门狗设备 */
handle = WatchdogOpen(0); handle = WatchdogOpen(0);
if (handle == NULL) { if (handle == NULL) {
HDF_LOGE("Open watchdog fail!"); HDF_LOGE("Open watchdog failed!");
return -1; return -1;
} }
...@@ -520,14 +313,14 @@ static int32_t TestCaseWatchdog(void) ...@@ -520,14 +313,14 @@ static int32_t TestCaseWatchdog(void)
/* 启动看门狗,开始计时 */ /* 启动看门狗,开始计时 */
ret = WatchdogStart(handle); ret = WatchdogStart(handle);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: satrt fail! ret:%d\n", __func__, ret); HDF_LOGE("%s: start fail! ret:%d\n", __func__, ret);
WatchdogClose(handle); WatchdogClose(handle);
return ret; return ret;
} }
/* 每隔1S喂狗一次 */ /* 每隔1S喂狗一次 */
for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) {
HDF_LOGE("%s: feeding watchdog %d times... \n", __func__, i); HDF_LOGI("%s: feeding watchdog %d times... \n", __func__, i);
ret = WatchdogFeed(handle); ret = WatchdogFeed(handle);
if (ret != HDF_SUCCESS) { if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: feed dog fail! ret:%d\n", __func__, ret); HDF_LOGE("%s: feed dog fail! ret:%d\n", __func__, ret);
...@@ -537,18 +330,17 @@ static int32_t TestCaseWatchdog(void) ...@@ -537,18 +330,17 @@ static int32_t TestCaseWatchdog(void)
OsalSleep(1); OsalSleep(1);
} }
/* 由于喂狗间隔小于超时时间,系统不会发生复位,此日志可以正常打印 */ /* 由于喂狗间隔小于超时时间,系统不会发生复位,此日志可以正常打印 */
HDF_LOGE("%s: no reset ... feeding test OK!!!\n", __func__); HDF_LOGI("%s: no reset ... feeding test OK!!!\n", __func__);
/* 接下来持续不喂狗,使得看门狗计时器超时 */ /* 接下来持续不喂狗,使得看门狗计时器超时 */
for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) {
HDF_LOGE("%s: watiting dog buck %d times... \n", __func__, i); HDF_LOGI("%s: waiting dog buck %d times... \n", __func__, i);
OsalSleep(1); OsalSleep(1);
} }
/* 当不喂狗时间到达之前设定的超时时间的时候,系统会发生复位,理论上观察不到此日志的打印 */ /* 当不喂狗时间到达之前设定的超时时间的时候,系统会发生复位,理论上观察不到此日志的打印 */
HDF_LOGE("%s: dog has't buck!!! \n", __func__, i); HDF_LOGI("%s: dog hasn't back!!! \n", __func__, i);
WatchdogClose(handle); WatchdogClose(handle);
return -1; return -1;
} }
``` ```
# WatchDog<a name="ZH-CN_TOPIC_0000001176922470"></a> # WatchDog
- [概述](#section1315827527160117)
- [接口说明](#section752964871810)
- [开发步骤](#section477974542160117)
- [开发实例](#section1832270347160117)
## 概述<a name="section1315827527160117"></a> ## 概述
看门狗(Watchdog),又叫看门狗计时器(Watchdog timer),是一种硬件的计时设备,在HDF框架中,Watchdog接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 看门狗(Watchdog),又叫看门狗计时器(Watchdog timer),是一种硬件的计时设备,在HDF框架中,Watchdog接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
**图 1** Watchdog独立服务模式结构图<a name="fig61584136211"></a> **图1** Watchdog独立服务模式结构图
![](figures/独立服务模式结构图.png "Watchdog独立服务模式结构图")
## 接口说明<a name="section752964871810"></a> ![zh-cn_image_0000001177082396](figures/zh-cn_image_0000001177082396.png)
## 接口说明
WatchdogMethod定义: WatchdogMethod定义:
``` ```
struct WatchdogMethod { struct WatchdogMethod {
int32_t (*getStatus)(struct WatchdogCntlr *wdt, int32_t *status); int32_t (*getStatus)(struct WatchdogCntlr *wdt, int32_t *status);
...@@ -29,121 +28,45 @@ struct WatchdogMethod { ...@@ -29,121 +28,45 @@ struct WatchdogMethod {
}; };
``` ```
**表 1** WatchdogMethod成员的回调函数功能说明 **表1** WatchdogMethod成员的回调函数功能说明
<a name="table1370451732"></a> | 成员函数 | 入参 | 出参 | 返回值 | 功能 |
<table><thead align="left"><tr id="row370511435"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p170681939"><a name="p170681939"></a><a name="p170681939"></a>成员函数</p> | -------- | -------- | -------- | -------- | -------- |
</th> | getStatus | wdt:&nbsp;结构体指针,核心层WDG控制器; | status:&nbsp;int32_t指针,表示狗的状态(打开或关闭); | HDF_STATUS相关状态 | 获取看门狗所处的状态 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p870641434"><a name="p870641434"></a><a name="p870641434"></a>入参</p> | start | wdt:&nbsp;结构体指针,核心层WDG控制器; | 无 | HDF_STATUS相关状态 | 打开开门狗 |
</th> | stop | wdt:&nbsp;结构体指针,核心层WDG控制器; | 无 | HDF_STATUS相关状态 | 关闭开门狗 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p27061011739"><a name="p27061011739"></a><a name="p27061011739"></a>出参</p> | setTimeout | wdt:&nbsp;结构体指针,核心层WDG控制器;seconds:&nbsp;uint32_t,时间传入值; | 无 | HDF_STATUS相关状态 | 设置超时时间值,单位秒,需要保证看门狗实际运行的时间符合该值 |
</th> | getTimeout | wdt:&nbsp;结构体指针,核心层WDG控制器; | seconds:&nbsp;uint32_t,传出的时间值 | HDF_STATUS相关状态 | 回读设置的超时时间值 |
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p10707618315"><a name="p10707618315"></a><a name="p10707618315"></a>返回值</p> | feed | wdt:&nbsp;结构体指针,核心层WDG控制器; | 无 | HDF_STATUS相关状态 | 喂狗 |
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p37071516316"><a name="p37071516316"></a><a name="p37071516316"></a>功能</p>
</th> ## 开发步骤
</tr>
</thead>
<tbody><tr id="row18707191835"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p970720118311"><a name="p970720118311"></a><a name="p970720118311"></a>getStatus</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p124968261413"><a name="p124968261413"></a><a name="p124968261413"></a>wdt: 结构体指针,核心层WDG控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p17071515316"><a name="p17071515316"></a><a name="p17071515316"></a>status: int32_t指针,表示狗的状态(打开或关闭);</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p5707319312"><a name="p5707319312"></a><a name="p5707319312"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p2707511312"><a name="p2707511312"></a><a name="p2707511312"></a>获取看门狗所处的状态</p>
</td>
</tr>
<tr id="row27071911538"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p370701533"><a name="p370701533"></a><a name="p370701533"></a>start</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p117071316317"><a name="p117071316317"></a><a name="p117071316317"></a>wdt: 结构体指针,核心层WDG控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p127071411735"><a name="p127071411735"></a><a name="p127071411735"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p19707111331"><a name="p19707111331"></a><a name="p19707111331"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p170811111319"><a name="p170811111319"></a><a name="p170811111319"></a>打开开门狗</p>
</td>
</tr>
<tr id="row17708191130"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p11708113315"><a name="p11708113315"></a><a name="p11708113315"></a>stop</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p870841138"><a name="p870841138"></a><a name="p870841138"></a>wdt: 结构体指针,核心层WDG控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p770841533"><a name="p770841533"></a><a name="p770841533"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p18708115313"><a name="p18708115313"></a><a name="p18708115313"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p3708121738"><a name="p3708121738"></a><a name="p3708121738"></a>关闭开门狗</p>
</td>
</tr>
<tr id="row107081818310"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p10708181136"><a name="p10708181136"></a><a name="p10708181136"></a>setTimeout</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1870801834"><a name="p1870801834"></a><a name="p1870801834"></a>wdt: 结构体指针,核心层WDG控制器;seconds: uint32_t,时间传入值;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p77081011731"><a name="p77081011731"></a><a name="p77081011731"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p470871436"><a name="p470871436"></a><a name="p470871436"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p57091717315"><a name="p57091717315"></a><a name="p57091717315"></a>设置超时时间值,单位秒,需要保证看门狗实际运行的时间符合该值</p>
</td>
</tr>
<tr id="row3709911938"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p2070911932"><a name="p2070911932"></a><a name="p2070911932"></a>getTimeout</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p47091711732"><a name="p47091711732"></a><a name="p47091711732"></a>wdt: 结构体指针,核心层WDG控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p57091411632"><a name="p57091411632"></a><a name="p57091411632"></a>seconds: uint32_t,传出的时间值</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1470941838"><a name="p1470941838"></a><a name="p1470941838"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p17091511139"><a name="p17091511139"></a><a name="p17091511139"></a>回读设置的超时时间值</p>
</td>
</tr>
<tr id="row1770919112319"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1270913116313"><a name="p1270913116313"></a><a name="p1270913116313"></a>feed</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p570971736"><a name="p570971736"></a><a name="p570971736"></a>wdt: 结构体指针,核心层WDG控制器;</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p67091517315"><a name="p67091517315"></a><a name="p67091517315"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1670915111312"><a name="p1670915111312"></a><a name="p1670915111312"></a>HDF_STATUS相关状态</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p10709818316"><a name="p10709818316"></a><a name="p10709818316"></a>喂狗</p>
</td>
</tr>
</tbody>
</table>
## 开发步骤<a name="section477974542160117"></a>
Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。
1. **实例化驱动入口:** 1. **实例化驱动入口:**
- 实例化HdfDriverEntry结构体成员。 - 实例化HdfDriverEntry结构体成员。
- 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
2. **配置属性文件:** 2. **配置属性文件:**
- 在device\_info.hcs文件中添加deviceNode描述。 - 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加watchdog\_config.hcs器件属性文件。 - 【可选】添加watchdog_config.hcs器件属性文件。
3. **实例化Watchdog控制器对象:** 3. **实例化Watchdog控制器对象:**
- 初始化WatchdogCntlr成员。 - 初始化WatchdogCntlr成员。
- 实例化WatchdogCntlr成员WatchdogMethod。 - 实例化WatchdogCntlr成员WatchdogMethod。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>![](../public_sys-resources/icon-note.gif) **说明:** > 实例化WatchdogCntlr成员WatchdogMethod,其定义和成员说明见[接口说明](#接口说明)。
>实例化WatchdogCntlr成员WatchdogMethod,其定义和成员说明见[接口说明](#section752964871810)。
4. **驱动调试:** 4. **驱动调试:**
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,超时时间设置的成功与否等。 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,超时时间设置的成功与否等。
## 开发实例<a name="section1832270347160117"></a> ## 开发实例
下方将以watchdog\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用 下方将以watchdog_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能
1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
Watchdog驱动入口参考: Watchdog驱动入口参考:
...@@ -159,11 +82,10 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱 ...@@ -159,11 +82,10 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱
HDF_INIT(g_watchdogDriverEntry);//调用HDF_INIT将驱动入口注册到HDF框架中 HDF_INIT(g_watchdogDriverEntry);//调用HDF_INIT将驱动入口注册到HDF框架中
``` ```
2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 watchdog\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层WatchdogCntlr 成员的默认值或限制范围有密切关系。 2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 watchdog_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层WatchdogCntlr 成员的默认值或限制范围有密切关系。
本例只有一个Watchdog控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在watchdog_config文件中增加对应的器件属性。
- device_info.hcs 配置参考。
本例只有一个Watchdog控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在watchdog\_config文件中增加对应的器件属性。
- device\_info.hcs 配置参考。
``` ```
root { root {
...@@ -186,7 +108,8 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱 ...@@ -186,7 +108,8 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱
} }
``` ```
- watchdog\_config.hcs 配置参考。 - watchdog_config.hcs 配置参考。
``` ```
root { root {
...@@ -209,7 +132,8 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱 ...@@ -209,7 +132,8 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱
3. 完成驱动入口注册之后,最后一步就是以核心层WatchdogCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化WatchdogCntlr成员WatchdogMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 3. 完成驱动入口注册之后,最后一步就是以核心层WatchdogCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化WatchdogCntlr成员WatchdogMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
- 自定义结构体参考。 - 自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且watchdog\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层WatchdogCntlr对象,例如索引、管脚数等。 从驱动的角度看,自定义结构体是参数和数据的载体,而且watchdog_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层WatchdogCntlr对象,例如索引、管脚数等。
``` ```
struct Hi35xxWatchdog { struct Hi35xxWatchdog {
...@@ -229,9 +153,9 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱 ...@@ -229,9 +153,9 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱
void *priv; //存储指针 void *priv; //存储指针
}; };
``` ```
- WatchdogCntlr成员回调函数结构体WatchdogMethod的实例化,其他成员在Init和Bind函数中初始化。 - WatchdogCntlr成员回调函数结构体WatchdogMethod的实例化,其他成员在Init和Bind函数中初始化。
``` ```
static struct WatchdogMethod g_method = { static struct WatchdogMethod g_method = {
.getStatus = Hi35xxWatchdogGetStatus, .getStatus = Hi35xxWatchdogGetStatus,
...@@ -245,55 +169,29 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱 ...@@ -245,55 +169,29 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱
- Init函数和Bind函数参考 - Init函数和Bind函数参考
入参**:** 入参:
HdfDeviceObject :HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。 HdfDeviceObject :HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。
返回值**:** 返回值:
HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
**表 2** Init函数和Bind函数入参和返回值 **表2** Init函数和Bind函数入参和返回值
<a name="table86931033998"></a> | 状态(值) | 问题描述 |
<table><thead align="left"><tr id="row10694203319911"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1669433319918"><a name="p1669433319918"></a><a name="p1669433319918"></a>状态(值)</p> | -------- | -------- |
</th> | HDF_ERR_INVALID_OBJECT | 找不到&nbsp;WDG&nbsp;设备 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p06945331911"><a name="p06945331911"></a><a name="p06945331911"></a>问题描述</p> | HDF_ERR_MALLOC_FAIL | 内存分配失败 |
</th> | HDF_ERR_IO | I/O&nbsp;错误 |
</tr> | HDF_SUCCESS | 初始化成功 |
</thead> | HDF_FAILURE | 初始化失败 |
<tbody><tr id="row869417338918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p96941433391"><a name="p96941433391"></a><a name="p96941433391"></a>HDF_ERR_INVALID_OBJECT</p>
</td> 函数说明:
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p4694333395"><a name="p4694333395"></a><a name="p4694333395"></a>找不到 WDG 设备</p>
</td>
</tr>
<tr id="row136941833091"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p66941336920"><a name="p66941336920"></a><a name="p66941336920"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1694133395"><a name="p1694133395"></a><a name="p1694133395"></a>内存分配失败</p>
</td>
</tr>
<tr id="row469443317913"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p116951933293"><a name="p116951933293"></a><a name="p116951933293"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p969511331918"><a name="p969511331918"></a><a name="p969511331918"></a>I/O 错误</p>
</td>
</tr>
<tr id="row369533318911"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p669511331891"><a name="p669511331891"></a><a name="p669511331891"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p136951233699"><a name="p136951233699"></a><a name="p136951233699"></a>初始化成功</p>
</td>
</tr>
<tr id="row17695633596"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1469583314910"><a name="p1469583314910"></a><a name="p1469583314910"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p10695193311919"><a name="p10695193311919"></a><a name="p10695193311919"></a>初始化失败</p>
</td>
</tr>
</tbody>
</table>
函数说明**:**
初始化自定义结构体对象,初始化WatchdogCntlr成员,调用核心层WatchdogCntlrAdd函数。 初始化自定义结构体对象,初始化WatchdogCntlr成员,调用核心层WatchdogCntlrAdd函数。
``` ```
//一般而言,Init函数需要根据入参(HdfDeviceObject对象)的属性值初始化Hi35xxWatchdog结构体的成员, //一般而言,Init函数需要根据入参(HdfDeviceObject对象)的属性值初始化Hi35xxWatchdog结构体的成员,
//但本例中是在bind函数中实现的 //但本例中是在bind函数中实现的
...@@ -325,20 +223,20 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱 ...@@ -325,20 +223,20 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
- Release函数参考 - Release函数参考
入参: 入参:
HdfDeviceObject :HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。 HdfDeviceObject :HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。
返回值**:** 返回值:
无。 无。
函数说明**:** 函数说明:
该函数需要在驱动入口结构体中赋值给Release,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。
该函数需要在驱动入口结构体中赋值给Release,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。
``` ```
static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device) static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device)
...@@ -360,6 +258,3 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱 ...@@ -360,6 +258,3 @@ Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱
OsalMemFree(hwdt); //释放厂商自定义对象占用的内存 OsalMemFree(hwdt); //释放厂商自定义对象占用的内存
} }
``` ```
# 平台驱动使用<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)**
- **[I3C](driver-platform-i3c-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)**
- **[RTC](driver-platform-rtc-des.md)** - **[RTC](driver-platform-rtc-des.md)**
- **[SDIO](driver-platform-sdio-des.md)** - **[SDIO](driver-platform-sdio-des.md)**
...@@ -28,4 +14,8 @@ ...@@ -28,4 +14,8 @@
- **[UART](driver-platform-uart-des.md)** - **[UART](driver-platform-uart-des.md)**
- **[WATCHDOG](driver-platform-watchdog-des.md)** - **[Watchdog](driver-platform-watchdog-des.md)**
- **[MIPI DSI](driver-platform-mipidsi-des.md)**
- **[PWM](driver-platform-pwm-des.md)**
\ No newline at end of file
# 驱动<a name="ZH-CN_TOPIC_0000001111039544"></a> # 驱动
- **[HDF驱动框架](driver-hdf.md)** - **[HDF驱动框架](driver-hdf.md)**
...@@ -7,5 +9,3 @@ ...@@ -7,5 +9,3 @@
- **[平台驱动使用](driver-platform.md)** - **[平台驱动使用](driver-platform.md)**
- **[外设驱动使用](driver-peripherals.md)** - **[外设驱动使用](driver-peripherals.md)**
\ No newline at end of file
# FAQs # faqs
- [常见问题概述](faqs-overview.md) - [常见问题概述](faqs-overview.md)
- [环境搭建常见问题](faqs-environment-setup.md) - [环境搭建常见问题](faqs-environment-setup.md)
- [编译构建子系统常见问题](faqs-building.md) - [编译构建子系统常见问题](faqs-building.md)
- [烧录常见问题](faqs-burning.md) - [烧录常见问题](faqs-burning.md)
- [内核常见问题](faqs-kernel.md) - [内核常见问题](faqs-kernel.md)
- [移植常见问题](faqs-porting.md) - [移植常见问题](faqs-transplant.md)
- [启动恢复常见问题](faqs-startup.md) - [启动恢复常见问题](faqs-init.md)
- [系统应用常见问题](faqs-system-applications.md) - [系统应用常见问题](faqs-system-using.md)
# 编译构建子系统常见问题<a name="ZH-CN_TOPIC_0000001215530845"></a> # 编译构建子系统常见问题
- [轻量和小型系统](#section78686441462)
- [编译构建过程中,提示“usr/sbin/ninja: invalid option -- w”](#section67961431372)
- [编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses”](#section199631617371)
- [编译构建过程中,提示“line 77: mcopy: command not found”](#section937435175)
- [编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”](#section1115535018713)
- [编译构建过程中,提示“No module named 'Crypto'”](#section17982573813)
- [编译构建过程中,提示“xx.sh : xx unexpected operator”](#section53663205819)
- [编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0”](#section1917790845)
- [编译构建过程中,提示找不到“-lgcc”](#section141771701647)
- [编译构建过程中,提示找不到“python”](#section51781202415)
- [编译构建过程中,提示找不到“python3”](#section1917950148)
## 轻量和小型系统
## 轻量和小型系统<a name="section78686441462"></a>
### 编译构建过程中,提示“usr/sbin/ninja: invalid option -- w”<a name="section67961431372"></a> ### 编译构建过程中,提示“usr/sbin/ninja: invalid option -- w”
- **现象描述:** - **现象描述:**
编译失败,提示“usr/sbin/ninja: invalid option -- w”。 编译失败,提示“usr/sbin/ninja: invalid option -- w”。
- **可能原因:** - **可能原因:**
编译环境中ninja版本太低,不支持--w选项。 编译环境中ninja版本太低,不支持--w选项。
- **解决办法:** - **解决办法:**
卸载环境中ninja和gn,按照[获取工具](../get-code/gettools-ide.md) 卸载环境中ninja和gn,按照[获取工具](../get-code/gettools-ide.md)
### 编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses”<a name="section199631617371"></a> ### 编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses”
- **现象描述:** - **现象描述:**
编译失败,提示“/usr/bin/ld: cannot find -lncurses”。 编译失败,提示“/usr/bin/ld: cannot find -lncurses”。
- **可能原因:** - **可能原因:**
编译环境ncurses库缺失。 编译环境ncurses库缺失。
- **解决办法:** - **解决办法:**
...@@ -47,14 +31,12 @@ ...@@ -47,14 +31,12 @@
``` ```
### 编译构建过程中,提示“line 77: mcopy: command not found”<a name="section937435175"></a> ### 编译构建过程中,提示“line 77: mcopy: command not found”
- **现象描述:** - **现象描述:**
​编译失败,提示“line 77: mcopy: command not found”。 ​编译失败,提示“line 77: mcopy: command not found”。
- **可能原因:** - **可能原因:**
编译环境未安装mcopy。 编译环境未安装mcopy。
- **解决办法:** - **解决办法:**
...@@ -64,19 +46,16 @@ ...@@ -64,19 +46,16 @@
``` ```
### 编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”<a name="section1115535018713"></a> ### 编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”
- **现象描述:** - **现象描述:**
编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”。 编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”。
-**可能原因:** -**可能原因:**
当前用户对riscv编译器路径下的文件访问权限不够。 当前用户对riscv编译器路径下的文件访问权限不够。
-**解决办法:** -**解决办法:**
查询gcc_riscv32所在目录。
查询gcc\_riscv32所在目录。
``` ```
which riscv32-unknown-elf-gcc which riscv32-unknown-elf-gcc
...@@ -85,14 +64,12 @@ ...@@ -85,14 +64,12 @@
使用chmod命令修改目录权限为755。 使用chmod命令修改目录权限为755。
### 编译构建过程中,提示“No module named 'Crypto'”<a name="section17982573813"></a> ### 编译构建过程中,提示“No module named 'Crypto'”
- **现象描述:** - **现象描述:**
编译失败,提示“No module named 'Crypto'”。 编译失败,提示“No module named 'Crypto'”。
- **可能原因:** - **可能原因:**
python3未安装Crypto。 python3未安装Crypto。
- **解决办法:** - **解决办法:**
...@@ -101,7 +78,6 @@ ...@@ -101,7 +78,6 @@
``` ```
python3 --version python3 --version
``` ```
2. 需使用python3.7以上版本,然后安装pycryptodome。 2. 需使用python3.7以上版本,然后安装pycryptodome。
``` ```
...@@ -109,15 +85,12 @@ ...@@ -109,15 +85,12 @@
``` ```
### 编译构建过程中,提示“xx.sh : xx unexpected operator”
### 编译构建过程中,提示“xx.sh : xx unexpected operator”<a name="section53663205819"></a>
- **现象描述:** - **现象描述:**
编译失败:“xx.sh [: xx unexpected operator”。
编译失败:“xx.sh \[: xx unexpected operator”。
- **可能原因:** - **可能原因:**
编译环境shell不是bash。 编译环境shell不是bash。
- **解决办法:** - **解决办法:**
...@@ -128,84 +101,77 @@ ...@@ -128,84 +101,77 @@
``` ```
### 编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0”<a name="section1917790845"></a> ### 编译构建过程中,提示“Could not find a version that satisfies the requirement six&gt;=1.9.0”
- **现象描述** - **现象描述**
编译构建过程中出现以下错误: 编译构建过程中出现以下错误:
``` ```
Could not find a version that satisfies the requirement six>=1.9.0 Could not find a version that satisfies the requirement six>=1.9.0
``` ```
- **可能原因** - **可能原因**
环境中未安装合适的“six”。 环境中未安装合适的“six”。
- **解决办法** - **解决办法**
方法1:通过命令“pip3 install six”,在线安装。 方法1:通过命令“pip3 install six”,在线安装。
方法2:离线安装 方法2:离线安装。
通过网页[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files),下载安装包。 通过网页[https://pypi.org/project/six/#files](https://pypi.org/project/six/#files),下载安装包。
![](figures/download-six.png) ![zh-cn_image_0000001251276115](figures/zh-cn_image_0000001251276115.png)
将源码放置在Linux服务器中,并安装“pip3 install six-1.14.0-py2.py3-none-any.whl”。 将源码放置在Linux服务器中,并安装“pip3 install six-1.14.0-py2.py3-none-any.whl”。
完成上述安装后,重新构建。 完成上述安装后,重新构建。
### 编译构建过程中,提示找不到“-lgcc”<a name="section141771701647"></a> ### 编译构建过程中,提示找不到“-lgcc”
- **现象描述** - **现象描述**
编译构建过程中出现以下错误: 编译构建过程中出现以下错误:
``` ```
riscv32-unknown-elf-ld: cannot find -lgcc riscv32-unknown-elf-ld: cannot find -lgcc
``` ```
- **可能原因** - **可能原因**
交叉编译器gcc_riscv32的PATH添加错误,如下,在"bin"后多添加了一个“/”,应该删除。
交叉编译器gcc\_riscv32的PATH添加错误,如下,在"bin"后多添加了一个“/”,应该删除。
``` ```
~/gcc_riscv32/bin/:/data/toolchain/ ~/gcc_riscv32/bin/:/data/toolchain/
``` ```
- **解决办法** - **解决办法**
重新修改gcc_riscv32的PATH,将多余的“/”删除。
重新修改gcc\_riscv32的PATH,将多余的“/”删除。
``` ```
~/gcc_riscv32/bin:/data/toolchain/ ~/gcc_riscv32/bin:/data/toolchain/
``` ```
### 编译构建过程中,提示找不到“python”<a name="section51781202415"></a> ### 编译构建过程中,提示找不到“python”
- **现象描述** - **现象描述**
编译构建过程中出现以下错误: 编译构建过程中出现以下错误:
``` ```
-bash: /usr/bin/python: No such file or directory -bash: /usr/bin/python: No such file or directory
``` ```
- **可能原因**1 - **可能原因**1
没有装python。 没有装python。
- **解决办法** - **解决办法**
请使用如下命令安装Python,下方以Python3.8为例。 请使用如下命令安装Python,下方以Python3.8为例。
``` ```
sudo apt-get install python3.8 sudo apt-get install python3.8
``` ```
...@@ -213,12 +179,12 @@ ...@@ -213,12 +179,12 @@
- **可能原因2** - **可能原因2**
usr/bin目录下没有python软链接 usr/bin目录下没有python软链接
![](figures/reason-no-python-soft-link.png) ![zh-cn_image_0000001243200677](figures/zh-cn_image_0000001243200677.png)
- **解决办法** - **解决办法**
请运行以下命令添加软链接: 请运行以下命令添加软链接:
``` ```
# cd /usr/bin/ # cd /usr/bin/
# which python3 # which python3
...@@ -228,24 +194,21 @@ ...@@ -228,24 +194,21 @@
例: 例:
![](figures/solution-add-soft-link.png) ![zh-cn_image_0000001243320787](figures/zh-cn_image_0000001243320787.png)
### 编译构建过程中,提示找不到“python3”<a name="section1917950148"></a> ### 编译构建过程中,提示找不到“python3”
- **现象描述** - **现象描述**
![zh-cn_image_0000001251276255](figures/zh-cn_image_0000001251276255.png)
安装python3过程中出现以下错误:
```
configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details
```
- **可能原因** - **可能原因**
没有装python3。
环境中未安装“gcc”。
- **解决办法** - **解决办法**
请使用如下命令安装Python3。
1. 通过命令“apt-get install gcc”在线安装。
2. 完成后,重新安装python3。
```
sudo apt-get install python3.8
```
# 烧录常见问题<a name="ZH-CN_TOPIC_0000001170009518"></a> # 烧录常见问题
- [轻量和小型系统](#section278314413530)
- [烧写选择串口后,提示“Error: Opening COMxx: Access denied”](#section18988185615914)
- [烧写失败](#section1370982513317)
- [串口无回显](#section183421944953)
- [Windows电脑与单板网络连接失败](#section1215410450215)
## 轻量和小型系统
## 轻量和小型系统<a name="section278314413530"></a>
### 烧写选择串口后,提示“Error: Opening COMxx: Access denied”<a name="section18988185615914"></a> ### 烧写选择串口后提示“Error: Opening COMxx: Access denied”
- **现象描述** - **现象描述**
点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。
点击烧写并选择串口后,出现“Error: Opening COMxx: Access denied”。 **图1** 打开串口失败图
![zh-cn_image_0000001243481961](figures/zh-cn_image_0000001243481961.png)
![](figures/Failed-to-open-the-serial-port.png)
- **可能原因** - **可能原因**
串口已经被占用。 串口已经被占用。
- 解决方法 - **解决办法**
检查主机中可能占用该端口的工具,关闭即可。若是当前工具占用,可按以下步骤排查并关闭: 1. 按图依次选择下拉框,查找带有serial-xx的终端。
1. 排查终端窗口列表,检查是否被monitor或其他终端占用。
![](figures/terminal-list.png) **图2** 查找是否存在占用串口的终端
![zh-cn_image_0000001243481989](figures/zh-cn_image_0000001243481989.png)
2. 找到占用,点击垃圾桶图标,关闭占用 2. 点击标号中的垃圾桶图标,关闭串口
**图3** 关闭串口终端
### 烧写失败<a name="section1370982513317"></a> ![zh-cn_image_0000001243082093](figures/zh-cn_image_0000001243082093.png)
- **现象描述** 3. 重新点击烧写,选择串口并开始烧写程序。
**图4** 重新启动烧写任务
![zh-cn_image_0000001198322224](figures/zh-cn_image_0000001198322224.png)
### 烧写失败
- **现象描述**
点击烧写并选择串口后,出现无法烧写的情况。 点击烧写并选择串口后,出现无法烧写的情况。
- **可能原因** - **可能原因**
安装IDE插件DevEco后未重启。 安装IDE插件DevEco后未重启。
- **解决方法** - **解决方法**
重启IDE。 重启IDE。
### 串口无回显<a name="section183421944953"></a> ### 串口无回显
- **现象描述** - **现象描述**
串口显示已连接,重启单板后,回车无任何回显。 串口显示已连接,重启单板后,回车无任何回显。
- **可能原因1** - **可能原因1**
串口连接错误。 串口连接错误。
- **解决办法** - **解决办法**
修改串口号。 修改串口号。
请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行修改串口号。 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内步骤1修改串口号。
- **可能原因2** - **可能原因2**
单板U-boot被损坏。 单板U-boot被损坏。
- **解决办法** - **解决办法**
烧写U-boot。 烧写U-boot。
若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。
1. 获取引导文件U-boot。 1. 获取引导文件U-boot。
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:**
>![](../public_sys-resources/icon-notice.gif) **须知:** > 单板的U-boot文件请在开源包中获取:
>单板的U-boot文件请在开源包中获取: >
>Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin > Hi3516DV300:device\hisilicon\hispark_taurus\sdk_liteos\uboot\out\boot\u-boot-hi3516dv300.bin
>Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin >
> Hi3518EV300:device\hisilicon\hispark_aries\sdk_liteos\uboot\out\boot\u-boot-hi3518ev300.bin
2. 根据USB烧写步骤烧写U-boot文件。 2. 根据USB烧写步骤烧写U-boot文件。
按照[Hi3516系列USB烧写步骤](../quick-start/quickstart-ide-lite-steps-hi3516-burn.md)中描述的烧写方法,选择对应单板的U-boot文件进行烧写。
按照[Hi3516系列USB烧写步骤](../quick-start/quickstart-lite-steps-hi3516-burn.md)/[Hi3518系列USB烧写步骤](../quick-start/quickstart-lite-steps-hi3518-burn.md)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。
3. 烧写完成后,登录串口如下图所示。 3. 烧写完成后,登录串口如下图所示。
**图 1** U-boot烧写完成串口显示图<a name="zh-cn_topic_0000001128470856_zh-cn_topic_0000001053466255_fig155914681910"></a> **图5** U-boot烧写完成串口显示图
![](figures/U-boot烧写完成串口显示图.png "U-boot烧写完成串口显示图")
![zh-cn_image_0000001243484907](figures/zh-cn_image_0000001243484907.png)
### Windows电脑与单板网络连接失败<a name="section1215410450215"></a>
- **现象描述** ### Windows电脑与单板网络连接失败
- **现象描述**
点击烧写并选择串口后,无法获取文件。 点击烧写并选择串口后,无法获取文件。
**图 2** 网络不通,Hi3516单板无法获取文件<a name="zh-cn_topic_0000001128470856_fig135261439195819"></a> **图6** 网络不通,单板无法获取文件图
![](figures/网络不通-Hi3516单板无法获取文件.png "网络不通-Hi3516单板无法获取文件")
- **可能原因** ![zh-cn_image_0000001198322428](figures/zh-cn_image_0000001198322428.png)
- **可能原因**
单板网络与Windows电脑不联通。 单板网络与Windows电脑不联通。
Windows电脑防火墙未允许Visual Studio Code联网。 Windows电脑防火墙未允许Visual Studio Code联网。
...@@ -110,20 +104,27 @@ ...@@ -110,20 +104,27 @@
- **解决方法** - **解决方法**
1. 检查网线是否连接。 1. 检查网线是否连接。
2. 点击Windows防火墙。 2. 点击Windows防火墙。
![](figures/hi3516-network-and-firewall-setting.png) **图7** 网络防火墙设置图
![zh-cn_image_0000001198162584](figures/zh-cn_image_0000001198162584.png)
3. 点击“允许应用通过防火墙”。 3. 点击“允许应用通过防火墙”。
![](figures/hi3516-firewall-and-network-protection.png) **图8** 防火墙和网络保护界面图
![zh-cn_image_0000001198323146](figures/zh-cn_image_0000001198323146.png)
4. 查找Visual Studio Code应用。 4. 查找Visual Studio Code应用。
![](figures/hi3516-selecting-the-visual-studio-code-application.png) **图9** 查找Visual Studio Code应用图
5. 勾选Visual Studio Code的专用和公用网络的访问权限。 ![zh-cn_image_0000001198003232](figures/zh-cn_image_0000001198003232.png)
![](figures/hi3516-allowing-the-visual-studio-code-application-to-access-the-network.png) 5. 勾选Visual Studio Code的专用和公用网络的访问权限。
**图10** 允许Visual Studio Code应用访问网络
![zh-cn_image_0000001243084579](figures/zh-cn_image_0000001243084579.png)
# 环境搭建常见问题
## 轻量和小型系统
### hb安装过程中出现乱码、段错误
- **现象描述**
执行“python3 -m pip install --user ohos-build”出现乱码、段错误(segmentation fault)。
- **可能原因**
pip版本过低。
- **解决办法**
执行如下命令升级pip。
```
python3 -m pip install -U pip
```
### hb安装过程中提示"cannot import 'sysconfig' from 'distutils'"
- **现象描述**
执行“python3 -m pip install --user ohos-build”提示"cannot import 'sysconfig' from 'distutils'"
- **可能原因**
缺少distutils模块。
- **解决办法**
执行如下命令安装。
```
sudo apt-get install python3.8-distutils
```
### hb安装过程中提示"module 'platform' has no attribute 'linux_distribution'"
- **现象描述**
执行“python3 -m pip install --user ohos-build”提示"module 'platform' has no attribute 'linux_distribution'"
- **可能原因**
python3 pip安装兼容性问题。
- **解决办法**
执行如下命令重新安装pip。
```
sudo apt remove python3-pip
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
```
### hb安装过程中提示"Could not find a version that satisfies the requirement ohos-build"
- **现象描述**
执行“python3 -m pip install --user ohos-build”提示"Could not find a version that satisfies the requirement ohos-build"
- **可能原因**
可能是网络环境较差导致的安装失败。
- **解决办法**
1. 请检查网络连接是否正常。如果网络有问题,请修复网络问题后重新安装。
2. 若网络正常,请尝试指定临时pypi源的方式安装:
```
python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ohos-build
```
### 安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH”
- **现象描述**
安装python3过程中出现以下错误:
```
configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details
```
- **可能原因**
环境中未安装“gcc”。
- **解决办法**
1. 通过命令“apt-get install gcc”在线安装。
2. 完成后,重新安装python3。
### 安装python3过程中,提示“-bash: make: command not found”
- **现象描述**
安装python3过程中出现以下错误:
```
-bash: make: command not found
```
- **可能原因**
环境中未安装“make”。
- **解决办法**
1. 通过命令“apt-get install make”在线安装。
2. 完成后,重新安装python3。
### 安装python3过程中,提示“zlib not available”
- **现象描述**
安装python3过程中出现以下错误:
```
zipimport.ZipImportError: can't decompress data; zlib not available
```
- **可能原因**
环境中未安装“zlib”。
- **解决办法**
方法1:通过命令“apt-get install zlib”在线安装。
方法2:如果软件源中没有该软件,请从“www.zlib.net”下载版本代码,并离线安装。
![zh-cn_image_0000001198001086](figures/zh-cn_image_0000001198001086.png)
完成下载后,通过以下命令安装:
```
# tar xvf zlib-1.2.11.tar.gz
# cd zlib-1.2.11
# ./configure
# make && make install
```
完成后,重新安装python3。
### 编译构建过程中,提示“No module named 'Crypto'”
- **现象描述**
编译构建过程中出现以下错误:
```
ModuleNotFoundError: No module named 'Crypto'
```
- **可能原因**
环境中未安装“Crypto”。
- **解决办法**
方法1:通过命令“pip3 install Crypto”,在线安装。
方法2:离线安装。
通过网页[https://pypi.org/project/pycrypto/#files](https://pypi.org/project/pycrypto/#files),下载源码。
![zh-cn_image_0000001251196005](figures/zh-cn_image_0000001251196005.png)
将源码放置在Linux服务器中,解压,并安装“python3 setup.py install”。
完成上述安装后,重新构建。
### 安装kconfiglib时,遇到lsb_release错误
- **现象描述**
安装kconfiglib过程中遇到如下错误打印:
```
subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1.
```
- **可能原因**
lsb_release模块基于的python版本与现有python版本不一致。
- **解决办法**
执行"find / -name lsb_release",找到lsb_release位置并删除,如:"sudo rm -rf /usr/bin/lsb_release"。
### Linux编译服务器终端输入不识别的命令时提示“ImportError: No module named apt_pkg”
- **现象描述**
Linux编译服务器终端输入不识别的命令时,提示"ImportError: No module named apt_pkg"
- **可能原因**
python3 apt安装兼容性问题。
- **解决办法**
执行如下命令重新安装python3-apt。
```
sudo apt-get remove python3-apt
sudo apt-get install python3-apt
```
# 启动恢复常见问题
## 系统启动过程中打印“parse failed!”错误后停止启动
**现象描述**
系统启动过程中,打印“[Init] InitReadCfg, parse failed! please check file /etc/init.cfg format.”错误,启动过程停止,如下图所示:
**图1** 运行报错图
![zh-cn_image_0000001200053087](figures/zh-cn_image_0000001200053087.png)
**可能原因**
修改init.cfg文件时,漏掉或多加了逗号或括号等,导致init.cfg文件的json格式被破坏。
**解决办法**
仔细检查init.cfg文件,确保其格式符合json格式要求。
## 系统启动过程未结束就自动重启,如此反复持续
**现象描述**
镜像烧写完成后系统启动,启动过程未完成即自动重新启动,如此反复持续。
**可能原因**
被init启动的服务都有一个叫做“importance”的属性(详见[第2章表3](../subsystems/subsys-boot-init.md)第二章节表3描述)。
- 当该属性为0时,表示若当前服务进程退出,init不需要重启单板。
- 当该属性为1时,表示若当前服务进程退出,init需要重启单板。
因此出现上述现象的可能原因:有“importance”属性为1的服务在每次启动的过程中都会退出(可能是进程崩溃或出错自动退出),导致init进程自动重启单板。
**解决办法**
1. 需要通过日志确认崩溃或报错退出的服务,并解决其崩溃/报错的问题,然后重新烧写镜像即可。
2. 也可以将崩溃/报错退出的服务的“importance”属性改为0,然后重新烧写镜像,这样即使其退出,init也不会重启单板。
## 参数正确的情况下调用SetParameter/GetParameter返回失败
**现象描述**
在各参数正确的情况下调用SetParameter/GetParameter返回失败。
**可能原因**
程序对SetParameter/GetParameter这两个接口做了权限校验,在各参数正确的情况下调用SetParameter/GetParameter返回操作失败,很有可能是调用者的uid大于1000,没有调用权限。
**解决办法**
无需处理
# 内核常见问题<a name="ZH-CN_TOPIC_0000001169850498"></a> # 内核常见问题
## 基础内核<a name="section263912372168"></a>
### LiteOS-A和LiteOS-M内核对外API的差异<a name="section447571122918"></a> ## 基础内核
### LiteOS-A和LiteOS-M内核对外API的差异
基础内核API存在差异,但是LiteOS-A提供标准POSIX接口,LiteOS-M提供标准POSIX和CMSIS接口。如果要支持跨平台,三方适配建议使用POSIX等标准接口。 基础内核API存在差异,但是LiteOS-A提供标准POSIX接口,LiteOS-M提供标准POSIX和CMSIS接口。如果要支持跨平台,三方适配建议使用POSIX等标准接口。
### 如何分析线程栈溢出<a name="section8623141711293"></a>
### 如何分析线程栈溢出
**问题现象** **问题现象**
...@@ -15,56 +18,71 @@ ...@@ -15,56 +18,71 @@
**解决措施** **解决措施**
1. 创建xxx线程的时候成倍加大栈空间,多次尝试如果问题不复现,则说明任务栈不够,需要调整; 1. 创建xxx线程的时候成倍加大栈空间,多次尝试如果问题不复现,则说明任务栈不够,需要调整;
2. 如果成倍加大线程栈,问题依旧复现,则排查xxx线程中是否定义超大数组,或者流程是否存在递归调用; 2. 如果成倍加大线程栈,问题依旧复现,则排查xxx线程中是否定义超大数组,或者流程是否存在递归调用;
3. 确认无前述问题,则需要排查是否存在踩内存的情况。 3. 确认无前述问题,则需要排查是否存在踩内存的情况。
## 文件系统<a name="section098519592162"></a>
### Hi3516开源板以写的模式打开同一个文件失败(LiteOS-A)<a name="section517972255311"></a> ## 文件系统
### Hi3516开源板以写的模式打开同一个文件失败(LiteOS-A)
Hi3516开源板使用FAT文件系统,不允许该操作。 Hi3516开源板使用FAT文件系统,不允许该操作。
### LiteOS内核已支持哪些硬件平台<a name="section868413518533"></a>
开源版本LiteOS-A已支持Hi3516/Hi3518开发板;LiteOS-M已支持Hi3861开发板、Nucleo\_f767zi等,详细查看kernel/liteos\_m目录下的README\_zh.md文件。 ### LiteOS内核已支持哪些硬件平台
开源版本LiteOS-A已支持Hi3516/Hi3518开发板;LiteOS-M已支持Hi3861开发板、STM32F103、野火挑战者STM32F429IGTb、Nucleo_f767zi等,详细查看kernel/liteos_m目录下的README_zh.md文件。
### LiteOS内核已支持哪几款芯片架构<a name="section1131661465417"></a> ### LiteOS内核已支持哪几款芯片架构
LiteOS-M已支持risc-v、Cortex-m3\\m4\\m7\\m33、arm9、c-sky、xtensa;LiteOS-A已支持armv7-a,待支持armv8-a,请关注开源社区更新。 LiteOS-M已支持risc-v、Cortex-m3\m4\m7\m33、arm9,待支持c-sky、xtensa;LiteOS-A已支持armv7-a,待支持armv8-a,请关注开源社区更新。
## 三方组件<a name="section971818231178"></a>
### OpenHarmony已支持哪些三方组件<a name="section74138185411"></a> ## 三方组件
### 已支持哪些三方组件
已提供mbedtls、lwip等开源组件和三方库,可以直接使用;另外提供标准的POSIX接口,可以自行适配。 已提供mbedtls、lwip等开源组件和三方库,可以直接使用;另外提供标准的POSIX接口,可以自行适配。
### 在OpenHarmony上使用OpenSSL,出现秘钥长度校验不正确<a name="section10564614135516"></a>
### 在上使用OpenSSL,出现秘钥长度校验不正确
OpenSSL编译选项中要注意架构类型(ARM,X86等)和系统位数(32、64位)是否选择正确。 OpenSSL编译选项中要注意架构类型(ARM,X86等)和系统位数(32、64位)是否选择正确。
### setsockopt是否支持SO\_RCVBUF和SO\_SNDBUF选项<a name="section2093373215556"></a>
### setsockopt是否支持SO_RCVBUF和SO_SNDBUF选项
不支持。 不支持。
## 编译链接<a name="section10955302179"></a>
### Arm Linux开发的应用程序,OpenHarmony如何在LiteOS-A上运行<a name="section1164175713557"></a> ## 编译链接
### Arm Linux开发的应用程序,如何在LiteOS-A上运行
需要用开源版本提供的交叉编译器重新编译应用程序,才可以运行。 需要用开源版本提供的交叉编译器重新编译应用程序,才可以运行。
### OpenHarmony在什么系统下编译,使用什么编译器<a name="section132287223567"></a>
### 在什么系统下编译,使用什么编译器
LiteOS-A在linux环境进行编译,使用LLVM编译器;LiteOS-M在Linux或Windows环境进行编译,使用IAR、Keil、GCC等编译工具。 LiteOS-A在linux环境进行编译,使用LLVM编译器;LiteOS-M在Linux或Windows环境进行编译,使用IAR、Keil、GCC等编译工具。
### LiteOS-M上使用单独编译成静态库的三方组件,出现三方组件中的全局变量值不正确,或调用三方组件的函数后系统卡死<a name="section15189154225619"></a>
### LiteOS-M上使用单独编译成静态库的三方组件,出现三方组件中的全局变量值不正确,或调用三方组件的函数后系统卡死
检查三方组件编译选项中是否有-fPIE -fpie -fPIC -fpic等地址无关编译选项,如果有,则去掉,重新编译成库使用。 检查三方组件编译选项中是否有-fPIE -fpie -fPIC -fpic等地址无关编译选项,如果有,则去掉,重新编译成库使用。
### LiteOS-A生成目标可执行文件时,提示 use VFP register arguments,xxx.o does not<a name="section193571012578"></a>
### LiteOS-A生成目标可执行文件时,提示 use VFP register arguments,xxx.o does not
请确认xxx.o编译时是否添加-mfloat-abi=xxx -mcpu=xxx -mfpu=xxx编译选项,若没有,则需要添加。 请确认xxx.o编译时是否添加-mfloat-abi=xxx -mcpu=xxx -mfpu=xxx编译选项,若没有,则需要添加。
### clock\_gettime接口获取的时间打印不对<a name="section8973152015717"></a>
struct timespec结构中tv\_sec为time\_t,而time\_t为long long类型,打印控制符为%lld,请确认实际打印控制符是否正确。 ### clock_gettime接口获取的时间打印不对
struct timespec结构中tv_sec为time_t,而time_t为long long类型,打印控制符为%lld,请确认实际打印控制符是否正确。
# 常见问题概述<a name="ZH-CN_TOPIC_0000001169691604"></a> # 常见问题概述
- [环境搭建](#section93289248249)
- [轻量和小型系统](#section197234983111)
- [编译构建子系统](#section18826114693810) 常见问题主要用于帮助开发者解决在开发过程中经常出现的一类问题。当前提供了如下常见问题供开发者进行查询。
- [轻量和小型系统](#section693410399)
- [烧录](#section6556741113712)
- [轻量和小型系统](#section1029933713812)
- [内核](#section13741125564211) ## 环境搭建
- [基础内核](#section1723365191114)
- [文件系统](#section14523145918136)
- [芯片适配](#section141541939159)
- [三方组件](#section4988163321816)
- [编译链接](#section080219574225)
- [移植](#section129331824154313)
- [启动恢复](#section83501764443)
- [系统服务](#section19567132114455)
- [公共基础库](#section3214181711465)
- [视觉应用常见问题](#section295651815466)
- [hdc](#section178081876506)
### 轻量和小型系统
常见问题主要用于帮助开发者解决在开发过程中经常出现的一类问题问题。当前提供了如下常见问题供开发者进行查询。 - [hb安装过程中出现乱码、段错误](../faqs/faqs-environment-building.md#hb安装过程中出现乱码段错误)
## 环境搭建<a name="section93289248249"></a> - [hb安装过程中提示"cannot import 'sysconfig' from 'distutils'"](../faqs/faqs-environment-building.md#hb安装过程中提示cannot-import-sysconfig-from-distutils)
### 轻量和小型系统<a name="section197234983111"></a> - [hb安装过程中提示"module 'platform' has no attribute 'linux_distribution'"](../faqs/faqs-environment-building.md#hb安装过程中提示module-platform-has-no-attribute-linuxdistribution)
- [安装hb过程中出现乱码、段错误](faqs-environment-setup.md#section36351051193919) - [hb安装过程中提示"Could not find a version that satisfies the requirement ohos-build"](../faqs/faqs-environment-building.md#hb安装过程中提示could-not-find-a-version-that-satisfies-the-requirement-ohos-build)
- [安装hb过程中,提示"cannot import 'sysconfig' from 'distutils'"](faqs-environment-setup.md#section48221013144011)
- [安装hb过程中,提示"module 'platform' has no attribute 'linux\_distribution'"](faqs-environment-setup.md#section8692735427)
- [安装hb过程中,提示"Could not find a version that satisfies the requirement ohos-build"](faqs-environment-setup.md#section8692735427)
- [安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH”](faqs-environment-setup.md#section870082884217)
- [安装python3过程中,提示“-bash: make: command not found”](faqs-environment-setup.md#section198707170455)
- [安装python3过程中,提示“zlib not available”](faqs-environment-setup.md#section85401445204518)
- [安装python3过程中,提示“No module named '\_ctypes'”](faqs-environment-setup.md#section12202694460)
- [安装 kconfiglib时,遇到lsb\_release错误](faqs-environment-setup.md#section5803174135115)
- [Linux编译服务器终端输入不识别的命令时提示“ImportError: No module named apt\_pkg”](faqs-environment-setup.md#section510820516515)
## 编译构建子系统<a name="section18826114693810"></a> - [安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH”](../faqs/faqs-environment-building.md#安装python3过程中提示configure-error-no-acceptable-c-compiler-found-in-path)
### 轻量和小型系统<a name="section693410399"></a> - [安装python3过程中,提示“-bash: make: command not found”](../faqs/faqs-environment-building.md#安装python3过程中提示-bash-make-command-not-found)
- [编译构建过程中,提示“usr/sbin/ninja: invalid option -- w”](faqs-building.md#section67961431372) - [安装python3过程中,提示“zlib not available”](../faqs/faqs-environment-building.md#安装python3过程中提示zlib-not-available)
- [编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses”](faqs-building.md#section199631617371)
- [编译构建过程中,提示“line 77: mcopy: command not found”](faqs-building.md#section937435175)
- [编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”](faqs-building.md#section1115535018713)
- [编译构建过程中,提示“No module named 'Crypto'”](faqs-building.md#section17982573813)
- [编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0”](faqs-building.md#section1917790845)
- [编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0”](faqs-building.md#section1917790845)
- [编译构建过程中,提示找不到“-lgcc”](faqs-building.md#section141771701647)
- [编译构建过程中,提示找不到“python”](faqs-building.md#section51781202415)
- [编译构建过程中,提示找不到“python3”](faqs-building.md#section1917950148)
## 烧录<a name="section6556741113712"></a> - [编译构建过程中,提示“No module named 'Crypto'”](../faqs/faqs-environment-building.md#编译构建过程中提示no-module-named-crypto)
### 轻量和小型系统<a name="section1029933713812"></a> - [安装kconfiglib时,遇到lsb_release错误](../faqs/faqs-environment-building.md#安装kconfiglib时遇到lsbrelease错误)
- [烧写选择串口后,提示“Error: Opening COMxx: Access denied”](faqs-burning.md#section18988185615914) - [Linux编译服务器终端输入不识别的命令时提示“ImportError: No module named apt_pkg”](../faqs/faqs-environment-building.md#linux编译服务器终端输入不识别的命令时提示importerror-no-module-named-aptpkg)
- [烧写失败](faqs-burning.md#section1370982513317)
- [串口无回显](faqs-burning.md#section183421944953)
- [Windows电脑与单板网络连接失败](faqs-burning.md#section1215410450215)
## 内核<a name="section13741125564211"></a> ## 编译构建子系统
### 基础内核<a name="section1723365191114"></a>
- [LiteOS-A和LiteOS-M内核对外API的差异](faqs-kernel.md#section447571122918) ### 轻量和小型系统
- [如何分析线程栈溢出](faqs-kernel.md#section8623141711293)
### 文件系统<a name="section14523145918136"></a> - [编译构建过程中,提示“usr/sbin/ninja: invalid option -- w”](../faqs/faqs-building.md#编译构建过程中提示usrsbinninja-invalid-option----w)
- [Hi3516开源板以写的模式打开同一个文件失败(LiteOS-A)](faqs-kernel.md#section517972255311) - [编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses”](../faqs/faqs-building.md#编译构建过程中提示usrbinld-cannot-find--lncurses)
### 芯片适配<a name="section141541939159"></a> - [编译构建过程中,提示“line 77: mcopy: command not found”](../faqs/faqs-building.md#编译构建过程中提示line-77-mcopy-command-not-found)
- [LiteOS内核已支持哪些硬件平台](faqs-kernel.md#section868413518533) - [编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”](../faqs/faqs-building.md#编译构建过程中提示riscv32-unknown-elf-gcc-error-trying-to-exec-cc1-execvp-no-such-file-or-directory)
- [LiteOS内核已支持哪几款芯片架构](faqs-kernel.md#section1131661465417)
### 三方组件<a name="section4988163321816"></a> - [编译构建过程中,提示“No module named 'Crypto'”](../faqs/faqs-building.md#编译构建过程中提示no-module-named-crypto)
- [OpenHarmony已支持哪些三方组件](faqs-kernel.md#section74138185411) - [编译构建过程中,提示“xx.sh : xx unexpected operator”](../faqs/faqs-building.md#编译构建过程中提示xxsh--xx-unexpected-operator)
- [在OpenHarmony上使用OpenSSL,出现秘钥长度校验不正确](faqs-kernel.md#section10564614135516)
- [setsockopt是否支持SO\_RCVBUF和SO\_SNDBUF选项](faqs-kernel.md#section2093373215556)
### 编译链接<a name="section080219574225"></a> - [编译构建过程中,提示“Could not find a version that satisfies the requirement six>=1.9.0”](../faqs/faqs-building.md#编译构建过程中提示could-not-find-a-version-that-satisfies-the-requirement-six190)
- [Arm Linux开发的应用程序,如何在LiteOS-A上运行](faqs-kernel.md#section1164175713557) - [编译构建过程中,提示找不到“-lgcc”](../faqs/faqs-building.md#编译构建过程中提示找不到-lgcc)
- [OpenHarmony在什么系统下编译,使用什么编译器](faqs-kernel.md#section132287223567)
- [LiteOS-M上使用单独编译成静态库的三方组件,出现三方组件中的全局变量值不正确,或调用三方组件的函数后系统卡死](faqs-kernel.md#section15189154225619)
- [LiteOS-A生成目标可执行文件,提示 use VFP register arguments,xxx.o does not](faqs-kernel.md#section193571012578)
- [clock\_gettime接口获取的时间打印不对](faqs-kernel.md#section8973152015717)
## 移植<a name="section129331824154313"></a> - [编译构建过程中,提示找不到“python”](../faqs/faqs-building.md#编译构建过程中提示找不到python)
- [如何将用户的堆内存挂载进内核](faqs-porting.md#section21471536184914) - [编译构建过程中,提示找不到“python3”](../faqs/faqs-building.md#编译构建过程中提示找不到python3)
## 启动恢复<a name="section83501764443"></a>
- [系统启动过程中打印“parse failed!”错误后停止启动](faqs-startup.md#section835662214302) ## 烧录
- [系统启动过程未结束就自动重启,如此反复持续](faqs-startup.md#section3857921143117)
- [参数正确的情况下调用SetParameter/GetParameter返回失败](faqs-startup.md#section548818116328)
## 系统服务<a name="section19567132114455"></a>
### 公共基础库<a name="section3214181711465"></a> ### 轻量和小型系统
- [LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储路径设置错误,导致KV存储运行失败](faqs-system-applications.md#section16520347131511) - [烧写选择串口后提示“Error: Opening COMxx: Access denied”](../faqs/faqs-burning.md#烧写选择串口后提示error-opening-comxx-access-denied)
### 视觉应用常见问题<a name="section295651815466"></a> - [烧写失败](../faqs/faqs-burning.md#烧写失败)
- [是否存在一个全局变量,所有的页面都可以访问?](faqs-system-applications.md#section187297991718) - [串口无回显](../faqs/faqs-burning.md#串口无回显)
- [如何获取dom中的元素](faqs-system-applications.md#section1833493719175)
- [如何在页面间传值?](faqs-system-applications.md#section184283812183)
- [list如何滚动到某个item?](faqs-system-applications.md#section11897734131811)
- [text支持多行吗?](faqs-system-applications.md#section5872656121814)
- [为什么控件不显示?](faqs-system-applications.md#section7397125317107)
- [如何实现页面滑动?](faqs-system-applications.md#section338794422010)
- [Left、Top为什么不生效?](faqs-system-applications.md#section2597193611217)
- [动态绑定为什么不生效?](faqs-system-applications.md#section6939050172115)
- [如何实现相对定位和绝对定位?](faqs-system-applications.md#section5547311192215)
- [如何控制控件的显示与隐藏?](faqs-system-applications.md#section16107113352213)
- [使用Margin时,有什么注意事项?](faqs-system-applications.md#section1524910142314)
- [使用事件订阅时,有什么注意事项?](faqs-system-applications.md#section1537132012231)
- [使用动态绑定时,有什么注意事项?](faqs-system-applications.md#section96561452236)
- [swiper loop属性如何生效?](faqs-system-applications.md#section690166112414)
- [使用数组时,有什么注意事项?](faqs-system-applications.md#section1554552822414)
### hdc<a name="section178081876506"></a> - [Windows电脑与单板网络连接失败](../faqs/faqs-burning.md#windows电脑与单板网络连接失败)
- [hdc\_std连接不到设备](faqs-system-applications.md#section1965012223257)
- [hdc\_std运行不了](faqs-system-applications.md#section1157575212515)
## 内核
### 基础内核
- [LiteOS-A和LiteOS-M内核对外API的差异](../faqs/faqs-kernel.md#liteos-a和liteos-m内核对外api的差异)
- [如何分析线程栈溢出](../faqs/faqs-kernel.md#如何分析线程栈溢出)
### 文件系统
- [Hi3516开源板以写的模式打开同一个文件失败(LiteOS-A)](../faqs/faqs-kernel.md#hi3516开源板以写的模式打开同一个文件失败liteos-a)
### 芯片适配
- [LiteOS内核已支持哪些硬件平台](../faqs/faqs-kernel.md#liteos内核已支持哪些硬件平台)
- [LiteOS内核已支持哪几款芯片架构](../faqs/faqs-kernel.md#liteos内核已支持哪几款芯片架构)
### 三方组件
- [HarmonyOSOpenHarmony已支持哪些三方组件](../faqs/faqs-kernel.md#harmonyosopenharmony已支持哪些三方组件)
- [在HarmonyOSOpenHarmony上使用OpenSSL,出现秘钥长度校验不正确](../faqs/faqs-kernel.md#在harmonyosopenharmony上使用openssl出现秘钥长度校验不正确)
- [setsockopt是否支持SO_RCVBUF和SO_SNDBUF选项](../faqs/faqs-kernel.md#setsockopt是否支持sorcvbuf和sosndbuf选项)
### 编译链接
- [Arm Linux开发的应用程序,HarmonyOSOpenHarmony如何在LiteOS-A上运行](../faqs/faqs-kernel.md#arm-linux开发的应用程序harmonyosopenharmony如何在liteos-a上运行)
- [HarmonyOSOpenHarmony在什么系统下编译,使用什么编译器](../faqs/faqs-kernel.md#harmonyosopenharmony在什么系统下编译使用什么编译器)[HarmonyOSOpenHarmony在什么系统下编译,使用什么编译器](../faqs/faqs-kernel.md#harmonyosopenharmony在什么系统下编译使用什么编译器)
- [LiteOS-M上使用单独编译成静态库的三方组件,出现三方组件中的全局变量值不正确,或调用三方组件的函数后系统卡死](../faqs/faqs-kernel.md#liteos-m上使用单独编译成静态库的三方组件出现三方组件中的全局变量值不正确或调用三方组件的函数后系统卡死)
- [LiteOS-A生成目标可执行文件时,提示 use VFP register arguments,xxx.o does not](../faqs/faqs-kernel.md#liteos-a生成目标可执行文件时提示-use--vfp-register-argumentsxxxo-does-not)
- [clock_gettime接口获取的时间打印不对](../faqs/faqs-kernel.md#clockgettime接口获取的时间打印不对)
## 移植
- [如何将用户的堆内存挂载进内核](../faqs/faqs-transplant.md#如何将用户的堆内存挂载进内核)
## 启动恢复
- [系统启动过程中打印“parse failed!”错误后停止启动](../faqs/faqs-init.md#系统启动过程中打印parse-failed错误后停止启动)
- [系统启动过程未结束就自动重启,如此反复持续](../faqs/faqs-init.md#系统启动过程未结束就自动重启如此反复持续)
- [参数正确的情况下调用SetParameter/GetParameter返回失败](../faqs/faqs-init.md#参数正确的情况下调用setparametergetparameter返回失败)
## 系统服务
### 公共基础库
- [1.LiteOS-A内核(Hi3516、Hi3518平台)KV存储路径设置错误,导致KV存储运行失败](../faqs/faqs-system-using.md#1liteos-a内核hi3516hi3518平台kv存储路径设置错误导致kv存储运行失败)
### 视觉应用常见问题
- [是否存在一个全局变量,所有的页面都可以访问?](../faqs/faqs-system-using.md#是否存在一个全局变量所有的页面都可以访问)
- [如何获取dom中的元素](../faqs/faqs-system-using.md#如何获取dom中的元素)
- [如何在页面间传值?](../faqs/faqs-system-using.md#如何在页面间传值)
- [list如何滚动到某个item?](../faqs/faqs-system-using.md#list如何滚动到某个item)
- [text支持多行吗?](../faqs/faqs-system-using.md#text支持多行吗)
- [为什么控件不显示?](../faqs/faqs-system-using.md#为什么控件不显示)
- [如何实现页面滑动?](../faqs/faqs-system-using.md#如何实现页面滑动)
- [Left、Top为什么不生效?](../faqs/faqs-system-using.md#lefttop为什么不生效)
- [动态绑定为什么不生效?](../faqs/faqs-system-using.md#动态绑定为什么不生效)
- [如何实现相对定位和绝对定位?](../faqs/faqs-system-using.md#如何实现相对定位和绝对定位)
- [如何控制控件的显示与隐藏?](../faqs/faqs-system-using.md#如何控制控件的显示与隐藏)
- [使用Margin时,有什么注意事项?](../faqs/faqs-system-using.md#使用margin时有什么注意事项)
- [使用事件订阅时,有什么注意事项?](../faqs/faqs-system-using.md#使用事件订阅时有什么注意事项)
- [使用动态绑定时,有什么注意事项?](../faqs/faqs-system-using.md#使用动态绑定时有什么注意事项)
- [swiper loop属性如何生效?](../faqs/faqs-system-using.md#swiper-loop属性如何生效)
- [使用数组时,有什么注意事项?](../faqs/faqs-system-using.md#使用数组时有什么注意事项)
### hdc
- [hdc_std连接不到设备](../faqs/faqs-system-using.md#hdcstd连接不到设备)
- [hdc_std运行不了](../faqs/faqs-system-using.md#hdcstd运行不了)
# 系统应用常见问题
## 公共基础库常见问题
### 1.LiteOS-A内核(Hi3516、Hi3518平台)KV存储路径设置错误,导致KV存储运行失败
**现象描述**
LiteOS-A内核(Hi3516、Hi3518平台)直接调用KV存储提供的接口,各参数正常的情况下,编译可执行程序运行失败。
**可能原因**
直接运行编译出的可执行文件,没有将程序基于AbilityKit转换成应用,不能由BMS在应用安装时正确设置应用数据存储路径,导致KV存储运行失败。
**解决办法**
显示调用KV存储的UtilsSetEnv接口,设置数据存储路径。
```
UtilsSetEnv("/storage/com.example.kv");
```
## 视觉应用常见问题
### 是否存在一个全局变量,所有的页面都可以访问?
当前框架中不存在所有Page都可以访问的全局变量。
### 如何获取dom中的元素
通过ref属性获取dom中的元素,详细示例如下图所示;获取的元素只能使用它的方法,不能改变属性。
```
<!--index.hml-->
<div class="container">
<!--指定组件的ref属性为animator-->
<image-animator class="image-player" ref="animator" images="{{images}}" duration="1s" onclick="handleClick"></image-animator>
</div>
/* index.js */
export default {
data: {
images:[
{src:"common/frame1.png"},
{src:"common/frame2.png"},
{src:"common/frame3.png"}
]
},
handleClick(){
//通过$refs属性获取对应的组件,在hml中,组件的ref属性要设置为animator
const animator = this.$refs.animator;
const state = animator.getState();
if(state == "paused"){
animator.resume();
}else if(state == "stopped"){
animator.start();
}else{
animator.pause();
}
}
}
```
### 如何在页面间传值?
通过router.replace方法中的params参数来传递,参考代码如下:
第一个页面传递数据:
```
router.replace({
uri:'pages/detail/detail', //要跳转的页面uri
params:{transferData:this.data} //传递的数据,数据个数和名称开发者自己定义,
});
```
第二个界面接受数据:
```
onInit(){
const data = this.transferData; //在onInit函数中接受传递的数据
}
```
### list如何滚动到某个item?
通过list的scrollTo方法滚动到指定的item,参数是目标item的index。Index参数可以通过scrollend事件获取或者开发者指定。
### text支持多行吗?
text支持多行。通过回车键换行或者是不设置text的高度属性,由控件自动根据内容换行。
### 为什么控件不显示?
**现象描述**
开发者在hml文件中添加的控件无法显示
**可能原因**
- 未设置width和height值;
- 样式设置错误。
**处理步骤**
(1)检查是否设置width和height值,组件必须显式设置width和height值;
(2)检查组件的样式设置是否正确。
### 如何实现页面滑动?
实现页面滑动目前有三种方式:scroll(根组件大小超过屏幕的大小即自动实现scroll效果)、list、swiper。开发者可以参考开发文档查看三者的区别,并加以使用。
### Left、Top为什么不生效?
除根节点外,Left、Top配合Stack组件使用才有效果。
### 动态绑定为什么不生效?
在进行绑定时,必须先将要绑定的对象或者对象的属性进行定义,不能先绑定后定义
### 如何实现相对定位和绝对定位?
使用div、stack(top left属性)来实现相对和绝对定位。
### 如何控制控件的显示与隐藏?
通过display、show和if来控制控件的显示与隐藏。区别在于:if为false时,组件会从VDOM中移除,而show仅是渲染时不可见,组件依然存在于VDOM中。
### 使用Margin时,有什么注意事项?
Stack组件不支持其子组件设置margin属性。
### 使用事件订阅时,有什么注意事项?
在应用运行期间只存在一个page,所以router.replace跳转是先销毁前一个页面,然后在新创建一个界面。因此,如果涉及到事件订阅的页面,每次页面创建时要进行事件订阅,跳转离开界面前取消事件订阅。
### 使用动态绑定时,有什么注意事项?
过多的动态绑定会消耗较多的内存,若非业务需要,尽量不要使用太多的动态绑定。
### swiper loop属性如何生效?
去掉第一个组件或者去掉最后一个组件,剩余的长度大于swiper长度,loop生效。
### 使用数组时,有什么注意事项?
数组元素不宜过多,尽量避免对大数组进行频繁操作。
## hdc类问题
### hdc_std连接不到设备
- **现象描述**
执行 "hdc_std list targets"命令后结果为:[Empty]
- **解决方法**
1. 设备没有被识别:
在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要断开并重联PC和OpenHarmony设备之间的USB连接,或者烧写最新的镜像。
2. hdc_std工作异常:
可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。
3. hdc_std与设备不匹配:
如果设备烧写的是最新镜像,hdc_std也需要使用最新版本。
### hdc_std运行不了
- **现象描述**
点击hdc_std.exe文件无法运行。
- **解决方法**
hdc_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc_std命令直接使用。
# 移植常见问题
## 如何将用户的堆内存挂载进内核
- 内核堆内存配置的相关宏如下,用户可根据实际情况,在target_config.h中配置:
**表1** 内核堆内存配置相关宏
| 宏名称 | 描述 |
| -------- | -------- |
| LOSCFG_SYS_EXTERNAL_HEAP | 这个宏决定系统是使用内核的内部堆内存还是用户的堆内存,默认为0(即使用内部的堆内存),大小为0x10000;如果用户需要基于外部的堆内存,那么可以将该宏设置为1。 |
| LOSCFG_SYS_HEAP_ADDR | 内核堆内存的起始地址。 |
| LOSCFG_SYS_HEAP_SIZE | 内核堆内存的大小,即LOSCFG_SYS_HEAP_ADDR指定的内存块大小。 |
- 注意事项:
指定的堆内存范围务必保证没有其他模块使用,避免踩内存,破坏堆内存功能。
# FAQ
- **[常见问题概述](faqs-overview.md)**
- **[环境搭建常见问题](faqs-environment-building.md)**
- **[编译构建子系统常见问题](faqs-building.md)**
- **[烧录常见问题](faqs-burning.md)**
- **[内核常见问题](faqs-kernel.md)**
- **[移植常见问题](faqs-transplant.md)**
- **[启动恢复常见问题](faqs-init.md)**
- **[系统应用常见问题](faqs-system-using.md)**
\ No newline at end of file
# Docker编译环境<a name="ZH-CN_TOPIC_0000001055701144"></a> # Docker编译环境
## Docker环境介绍<a name="section107932281315"></a>
## Docker环境介绍
OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完成复杂的开发环境准备工作。两种Docker环境及适用场景如下: OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完成复杂的开发环境准备工作。两种Docker环境及适用场景如下:
- 独立Docker环境:适用于直接基于Ubuntu、Windows操作系统平台进行版本编译的场景。 - 独立Docker环境:适用于直接基于Ubuntu、Windows操作系统平台进行版本编译的场景。
- 基于HPM的Docker环境:适用于使用HPM工具进行发行版编译的场景。 - 基于HPM的Docker环境:适用于使用HPM工具进行发行版编译的场景。
**表 1** Docker镜像介绍 **表1** Docker镜像介绍
<a name="table11986917191214"></a> | 系统类型 | 运行平台 | Docker镜像仓库 | 标签 |
<table><thead align="left"><tr id="row149861417121215"><th class="cellrowborder" valign="top" width="15.831583158315832%" id="mcps1.2.6.1.1"><p id="p798611714124"><a name="p798611714124"></a><a name="p798611714124"></a>Docker环境</p> | -------- | -------- | -------- | -------- |
</th> | 轻量和小型系统(独立Docker环境) | Ubuntu/Windows | swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker | 1.0.0 |
<th class="cellrowborder" valign="top" width="13.97139713971397%" id="mcps1.2.6.1.2"><p id="p1698661751219"><a name="p1698661751219"></a><a name="p1698661751219"></a>系统类型</p> | 标准系统(独立Docker环境) | Ubuntu | swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard | 1.0.0 |
</th> | 轻量和小型系统(HPM Docker环境) | Ubuntu/Windows | swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker | 0.0.3 |
<th class="cellrowborder" valign="top" width="18.61186118611861%" id="mcps1.2.6.1.3"><p id="p1798671761217"><a name="p1798671761217"></a><a name="p1798671761217"></a>运行平台</p>
</th>
<th class="cellrowborder" valign="top" width="35.8935893589359%" id="mcps1.2.6.1.4"><p id="p20526205414295"><a name="p20526205414295"></a><a name="p20526205414295"></a>Docker镜像仓库</p> ## 环境准备
</th>
<th class="cellrowborder" valign="top" width="15.69156915691569%" id="mcps1.2.6.1.5"><p id="p1833001309"><a name="p1833001309"></a><a name="p1833001309"></a>标签</p>
</th>
</tr>
</thead>
<tbody><tr id="row1798661751216"><td class="cellrowborder" valign="top" width="15.831583158315832%" headers="mcps1.2.6.1.1 "><p id="p1898631791213"><a name="p1898631791213"></a><a name="p1898631791213"></a>独立 Docker环境</p>
</td>
<td class="cellrowborder" valign="top" width="13.97139713971397%" headers="mcps1.2.6.1.2 "><p id="p1598617177128"><a name="p1598617177128"></a><a name="p1598617177128"></a>轻量和小型系统</p>
</td>
<td class="cellrowborder" valign="top" width="18.61186118611861%" headers="mcps1.2.6.1.3 "><p id="p898614178122"><a name="p898614178122"></a><a name="p898614178122"></a>Ubuntu/Windows</p>
</td>
<td class="cellrowborder" valign="top" width="35.8935893589359%" headers="mcps1.2.6.1.4 "><p id="p12667431305"><a name="p12667431305"></a><a name="p12667431305"></a>swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker</p>
</td>
<td class="cellrowborder" valign="top" width="15.69156915691569%" headers="mcps1.2.6.1.5 "><p id="p143320173017"><a name="p143320173017"></a><a name="p143320173017"></a>1.0.0</p>
</td>
<tr id="row5986201731214"><td class="cellrowborder" align="center" valign="top" width="15.831583158315832%" headers="mcps1.2.6.1.1 "><p id="p136981216143"><a name="p136981216143"></a><a name="p136981216143"></a>HPM Docker环境</p>
</td>
<td class="cellrowborder" valign="top" width="13.97139713971397%" headers="mcps1.2.6.1.2 "><p id="p969831161416"><a name="p969831161416"></a><a name="p969831161416"></a>轻量和小型系统</p>
</td>
<td class="cellrowborder" valign="top" width="18.61186118611861%" headers="mcps1.2.6.1.3 "><p id="p18821161052214"><a name="p18821161052214"></a><a name="p18821161052214"></a>Ubuntu/Windows</p>
</td>
<td class="cellrowborder" valign="top" width="35.8935893589359%" headers="mcps1.2.6.1.4 "><p id="p1652616548294"><a name="p1652616548294"></a><a name="p1652616548294"></a>swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker</p>
</td>
<td class="cellrowborder" valign="top" width="15.69156915691569%" headers="mcps1.2.6.1.5 "><p id="p1433130173010"><a name="p1433130173010"></a><a name="p1433130173010"></a>0.0.3</p>
</td>
</tr>
</tbody>
</table>
## 环境准备<a name="section7337134183512"></a>
在使用docker环境前需要先完成以下操作: 在使用docker环境前需要先完成以下操作:
1. 安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/) 1. 安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/)
2. 获取OpenHarmony源码,请参考[获取源码](sourcecode-acquire.md)
>![](../public_sys-resources/icon-note.gif) **说明:** 2. 获取OpenHarmony源码,请参考[获取源码](https://device.harmonyos.com/cn/docs/documentation/guide/sourcecode-acquire-0000001050769927)
>HPM Docker环境无需单独获取源码。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> HPM Docker环境无需单独获取源码。
## 独立Docker环境<a name="section2858536103611"></a> ## 独立Docker环境
OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud.com/swr/?region=cn-south-1#/app/warehouse/warehouseMangeDetail/goldensir/openharmony-docker/openharmony-docker?type=ownImage)上。开发者可以通过该镜像在很大程度上简化编译前的环境配置。下文将介绍具体使用步骤。 OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud.com/swr/?region=cn-south-1#/app/warehouse/warehouseMangeDetail/goldensir/openharmony-docker/openharmony-docker?type=ownImage)上。开发者可以通过该镜像在很大程度上简化编译前的环境配置。下文将介绍具体使用步骤。
### 搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)<a name="section319412277287"></a> ### 搭建Docker环境(轻量系统和小型系统)
1. 获取Docker镜像。 1. 获取Docker镜像。
...@@ -76,41 +41,46 @@ OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud ...@@ -76,41 +41,46 @@ OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0 docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0
``` ```
2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 2. 进入源码根目录执行如下命令,从而进入Docker构建环境。
ubuntu下执行: ubuntu下执行:
``` ```
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0 docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0
``` ```
windows下执行(假设源码目录为D:\\OpenHarmony): windows下执行(假设源码目录为D:\OpenHarmony):
``` ```
docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0 docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0
``` ```
### 编译源码(轻量系统和小型系统)
### 编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)<a name="section631485163615"></a> 通过如下编译脚本启动轻量系统类设备(参考内存≥128KiB)和小型系统类设备(参考内存≥1MiB)的编译。下文以Hi3516平台为例说明具体编译步骤。
通过如下编译脚本启动轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)的编译。下文以Hi3516平台为例说明具体编译步骤。 设置编译路径,选择当前路径。
设置编译路径,选择当前路径。
``` ```
hb set hb set
.
``` ```
**图 1** 设置编译界面<a name="fig7947145854013"></a> **图1** 设置编译界面
![](figure/设置编译界面.png "设置编译界面")
![zh-cn_image_0000001153508656](figures/zh-cn_image_0000001153508656.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 当前开发板平台和编译界面的对应关系如下:
>
> - Hi3861:wifiiot_hispark_pegasus\@hisilicon
>
> - Hi3516:ipcamera_hispark_taurus\@hisilicon
>
> - Hi3518:ipcamera_hispark_aries\@hisilicon
>![](../public_sys-resources/icon-note.gif) **说明:** 1. 选择ipcamera_hispark_taurus\@hisilicon并回车。
>当前开发板平台和编译界面的对应关系如下:
>- Hi3861:wifiiot\_hispark\_pegasus@hisilicon
>- Hi3516:ipcamera\_hispark\_taurus@hisilicon
>- Hi3518:ipcamera\_hispark\_aries@hisilicon
1. 选择ipcamera\_hispark\_taurus@hisilicon并回车。
2. 执行编译。 2. 执行编译。
``` ```
...@@ -118,46 +88,45 @@ hb set ...@@ -118,46 +88,45 @@ hb set
``` ```
3. 查看编译结果。 3. 查看编译结果。
编译结果文件生成在out/hispark_taurus/ipcamera_hispark_taurus目录下。
编译结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 ### 搭建Docker环境(标准系统)
### 搭建Docker环境-标准系统类设备(参考内存≥128MB)<a name="section13585262391"></a>
1. 获取Docker镜像。 1. 获取Docker镜像。
``` ```
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0 docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:1.0.0
``` ```
2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 2. 进入源码根目录执行如下命令,从而进入Docker构建环境。
``` ```
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0 docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:1.0.0
``` ```
### 编译源码(标准系统)
### 编译源码-标准系统类设备(参考内存≥128MB)<a name="section193711513406"></a> 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。
通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。
``` ```
./build.sh --product-name {product_name} --ccache ./build.sh --product-name {product_name} --ccache
``` ```
\{product\_name\}为当前版本支持的平台。比如:Hi3516DV300和rk3568等。 {product_name}为当前版本支持的平台。比如:Hi3516DV300和rk3568等。
编译所生成的文件都归档在out/{device_name}/目录下,结果镜像输出在 out/{device_name}/packages/phone/images/ 目录下。 编译所生成的文件都归档在out/{device_name}/目录下,结果镜像输出在 out/{device_name}/packages/phone/images/ 目录下。
>![](../public_sys-resources/icon-note.gif) **说明:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>退出Docker执行exit命令即可。 > 退出Docker执行exit命令即可。
## 基于HPM的Docker环境<a name="section485713518337"></a> ## 基于HPM的Docker环境
docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件,能够帮助用户快速初始化HPM工程,利用docker镜像来快速编译OpenHarmony发行版,在很大程度上简化了编译前的环境配置。开发者在配置好Ubuntu和[hpm-cli](../hpm-part/hpm-part-development.md)开发环境后,可以通过以下步骤来使用我们提供的Docker环境。 docker_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件,能够帮助用户快速初始化HPM工程,利用docker镜像来快速编译OpenHarmony发行版,在很大程度上简化了编译前的环境配置。开发者在配置好Ubuntu和[hpm-cli](https://device.harmonyos.com/cn/docs/documentation/guide/hpm-part-development-install-0000001178291102)开发环境后,可以通过以下步骤来使用我们提供的Docker环境。
### 搭建Docker环境<a name="section3295842510"></a>
### 搭建Docker环境
1. 初始化安装模板。在任意工作目录中执行以下命令。 1. 初始化安装模板。在任意工作目录中执行以下命令。
...@@ -166,27 +135,26 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件 ...@@ -166,27 +135,26 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件
``` ```
2. 修改publishAs。 2. 修改publishAs。
因为获取到的是模板类型的包,要把包的类型改为需要的类型。 在当前目录下打开bundle.json文件,把"publishAs"字段的值由"template"改为"distribution"。 因为获取到的是模板类型的包,要把包的类型改为需要的类型。 在当前目录下打开bundle.json文件,把"publishAs"字段的值由"template"改为"distribution"。
### 获取及编译源码<a name="section69141039143518"></a> ### 获取及编译源码
执行编译。自动安装docker只能在Ubuntu环境下执行,如果其他环境,需要用户自行安装docker,然后拉取镜像,执行编译。 执行编译。自动安装docker只能在Ubuntu环境下执行,如果其他环境,需要用户自行安装docker,然后拉取镜像,执行编译。
- **自动安装docker(Ubuntu环境)** - **自动安装docker(Ubuntu环境)**
以下命令可以帮助用户自动安装docker, 拉取镜像,并且在容器中开始运行对应解决方案的拉取和编译。 以下命令可以帮助用户自动安装docker, 拉取镜像,并且在容器中开始运行对应解决方案的拉取和编译。
**方式一:** **方式一:**
命令后接参数指定解决方案,格式如下: 命令后接参数指定解决方案,格式如下:
``` ```
hpm run docker solution={product} hpm run docker solution={product}
``` ```
\{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 {product}为需编译的解决方案,如:\@ohos/hispark_taurus、\@ohos/hispark_aries、\@ohos/hispark_pegasus。
**方式二:** **方式二:**
...@@ -198,15 +166,14 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件 ...@@ -198,15 +166,14 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件
export solution={product} export solution={product}
``` ```
\{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 {product}为需编译的解决方案,如:\@ohos/hispark_taurus、\@ohos/hispark_aries、\@ohos/hispark_pegasus。
2. 获取源码及执行编译。 2. 获取源码及执行编译。
``` ```
hpm run docker hpm run docker
``` ```
以上两种方式以@ohos/hispark\_taurus为例,执行成功结果如下: 以上两种方式以\@ohos/hispark_taurus为例,执行成功结果如下:
``` ```
...... ......
...@@ -214,11 +181,10 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件 ...@@ -214,11 +181,10 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件
@ohos/hispark_taurus: distribution building completed. @ohos/hispark_taurus: distribution building completed.
``` ```
- **自行安装docker(非Ubuntu环境)** - **自行安装docker(非Ubuntu环境)**
自行安装docker相关操作如下: 自行安装docker相关操作如下:
``` ```
# 拉取镜像 # 拉取镜像
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3# linux环境下的编译 docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3# linux环境下的编译
...@@ -227,4 +193,3 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件 ...@@ -227,4 +193,3 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件
hpm config set shellPath "gitbash路径" hpm config set shellPath "gitbash路径"
hpm run distWithDocker solution={product} hpm run distWithDocker solution={product}
``` ```
# IDE # IDE
## 获取设备开发工具(HUAWEI DevEco Device Tool) ## 获取设备开发工具(HUAWEI DevEco Device Tool)
HUAWEI DevEco Device Tool是OpenHarmony面向智能设备开发者提供的一站式集成开发环境,支持OpenHarmony的组件按需定制,支持代码编辑、编译、烧录、调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。具体可参见[获取工具](https://device.harmonyos.com/cn/ide)[工具使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905) HUAWEI DevEco Device Tool是OpenHarmony面向智能设备开发者提供的一站式集成开发环境,支持OpenHarmony的组件按需定制,支持代码编辑、编译、烧录、调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。具体可参见[获取工具](https://device.harmonyos.com/cn/ide)[工具使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905)**。**
## 获取应用开发工具(HUAWEI DevEco Studio) ## 获取应用开发工具(HUAWEI DevEco Studio)
......
# 获取源码<a name="ZH-CN_TOPIC_0000001150448437"></a> # 获取源码
## OpenHarmony介绍<a name="section6370143622110"></a>
## OpenHarmony介绍
OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展。 OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展。
开源代码仓库地址:[https://openharmony.gitee.com](https://openharmony.gitee.com) 开源代码仓库地址:[https://openharmony.gitee.com](https://openharmony.gitee.com)
## 获取源码概述<a name="section12763342204"></a>
OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发者可根据业务诉求选用合适的方式获取源码: ## 获取源码概述
本文档将介绍如何获取OpenHarmony源码并说明OpenHarmony的源码目录结构。OpenHarmony的代码以[组件](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/hpm-part/Readme-CN.md)的形式开放,开发者可以通过如下其中一种方式获取:
- **获取方式1**:从码云代码仓库获取。通过repo或git工具从代码仓库中下载,此方式可获取最新代码。 - **获取方式1**:从码云代码仓库获取。通过repo或git工具从代码仓库中下载,此方式可获取最新代码。
- **获取方式2**:通过[DevEco Marketplace](https://repo.harmonyos.com/#/cn/home)网站获取。访问[DevEco Marketplace](https://repo.harmonyos.com/#/cn/home)网站,查找满足需求的开源发行版,直接下载(或者定制后下载),再通过hpm-cli命令工具将所需的组件及工具链下载、安装到本地。 - **获取方式2**:通过[DevEco Marketplace](https://repo.harmonyos.com/#/cn/home)网站获取。访问[DevEco Marketplace](https://repo.harmonyos.com/#/cn/home)网站,查找满足需求的开源发行版,直接下载(或者定制后下载),再通过hpm-cli命令工具将所需的组件及工具链下载、安装到本地。
- **获取方式3**:从镜像站点下载归档后的发行版压缩文件。如果要获取旧版本的源码,也可通过此方式获取,此方式下载速度较快。 - **获取方式3**:从镜像站点下载归档后的发行版压缩文件。如果要获取旧版本的源码,也可通过此方式获取,此方式下载速度较快。
- **获取方式4**:从github代码仓库获取。通过repo或git工具从代码仓库中下载,此方式可获取最新代码。 - **获取方式4**:从github代码仓库获取。通过repo或git工具从代码仓库中下载,此方式可获取最新代码。
## 获取方式1:从码云仓库获取<a name="section537312010229"></a>
### 适用场景<a name="section10881513459"></a> ## 获取方式1:从码云仓库获取
### 适用场景
- 基于OpenHarmony的稳定分支建立自己的基线,分发下游客户。 - 基于OpenHarmony的稳定分支建立自己的基线,分发下游客户。
...@@ -30,10 +39,12 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发 ...@@ -30,10 +39,12 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发
- 学习OpenHarmony的源码。 - 学习OpenHarmony的源码。
### 前提条件<a name="section102871547153314"></a> ### 前提条件
1. 注册码云gitee帐号。 1. 注册码云gitee帐号。
2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191) 2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)
3. 安装[git客户端](https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading)并配置用户信息。 3. 安装[git客户端](https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading)并配置用户信息。
``` ```
...@@ -45,17 +56,17 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发 ...@@ -45,17 +56,17 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发
4. 安装码云repo工具,可以执行如下命令。 4. 安装码云repo工具,可以执行如下命令。
``` ```
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中
chmod a+x /usr/local/bin/repo chmod a+x /usr/local/bin/repo
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
``` ```
### 操作步骤<a name="section429012478331"></a> ### 操作步骤
>![](../public_sys-resources/icon-note.gif) **说明:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
>Master主干为开发分支,开发者可通过Master主干获取最新特性。发布版本代码相对比较稳定,开发者可基于发布版本代码进行商用功能开发。 > Master主干为开发分支,开发者可通过Master主干获取最新特性。发布版本代码相对比较稳定,开发者可基于发布版本代码进行商用功能开发。
- **OpenHarmony主干代码获取** - **OpenHarmony主干代码获取**
...@@ -69,6 +80,7 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发 ...@@ -69,6 +80,7 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发
方式二:通过repo + https下载。 方式二:通过repo + https下载。
``` ```
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
repo sync -c repo sync -c
...@@ -77,27 +89,27 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发 ...@@ -77,27 +89,27 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发
- **OpenHarmony发布版本代码获取** - **OpenHarmony发布版本代码获取**
OpenHarmony发布版本获取源码方式请参考[Release-Notes](../../release-notes/Readme.md)。 OpenHarmony发布版本获取源码方式请参考[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/Readme.md)
## 获取方式2:从DevEco Marketplace获取<a name="section463013147412"></a> ## 获取方式2:从DevEco Marketplace获取
### 适用场景<a name="section26661067443"></a>
### 适用场景
对于刚接触OpenHarmony的新用户,希望能够参考一些示例解决方案从而进行快速开发。可以在[DevEco Marketplace](https://repo.harmonyos.com/#/cn/home)网站获取下载开源发行版,也可以在开源发行版的基础上定制(添加或删除组件)。然后通过包管理器命令行工具(hpm-cli)将需要的组件及相关的编译工具链全部下载、安装到本地。 对于刚接触OpenHarmony的新用户,希望能够参考一些示例解决方案从而进行快速开发。可以在[DevEco Marketplace](https://repo.harmonyos.com/#/cn/home)网站获取下载开源发行版,也可以在开源发行版的基础上定制(添加或删除组件)。然后通过包管理器命令行工具(hpm-cli)将需要的组件及相关的编译工具链全部下载、安装到本地。
### 前提条件<a name="section17544943123315"></a>
### 前提条件
先要在本地安装Node.js和hpm命令行工具,安装步骤如下: 先要在本地安装Node.js和hpm命令行工具,安装步骤如下:
1. 安装Node.js。 1. 安装Node.js。
官网下载并在本地安装Node.js. 官网下载并在本地安装Node.js.
[Node.js](https://nodejs.org/) 版本需不低于12.x \(包含npm 6.14.4\),推荐安装LTS版本。 [Node.js](https://nodejs.org/)版本需不低于12.x (包含npm 6.14.4),推荐安装LTS版本。
2. 通过Node.js自带的npm安装hpm命令行工具。 2. 通过Node.js自带的npm安装hpm命令行工具。
打开CMD,执行以下命令: 打开CMD,执行以下命令:
``` ```
...@@ -117,223 +129,80 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发 ...@@ -117,223 +129,80 @@ OpenHarmony当前为开发者提供了以下4种获取源码的方式,开发
``` ```
### 操作步骤<a name="section954619433333"></a> ### 操作步骤
1. 查找发行版。 1. 查找发行版。
1. 访问[DevEco Marketplace](https://repo.harmonyos.com/#/cn/home),设定搜索的对象为“设备组件“,并在左侧边栏选择“开源发行版“,如下图所示。 1. 访问[DevEco Marketplace](https://repo.harmonyos.com/#/cn/home),设定搜索的对象为设备组件,并在左侧边栏选择开源发行版,如下图所示。
2. 在搜索框输入关键字搜索,如“摄像头”。 2. 在搜索框输入关键字搜索,如“摄像头”。
3. 结果中显示与关键字匹配的发行版,可以进一步根据组件类别等过滤条件(如:适配的开发板,内核)精确筛选。 3. 结果中显示与关键字匹配的发行版,可以进一步根据组件类别等过滤条件(如:适配的开发板,内核)精确筛选。
4. 查找合适的发行版,点击查看发行版的详情介绍。 4. 查找合适的发行版,点击查看发行版的详情介绍。
**图 1** 包管理<a name="fig349416264520"></a> **图1** 包管理
![](figure/包管理.png "包管理")
2. 了解发行版详情。 ![zh-cn_image_0000001168212170](figures/zh-cn_image_0000001168212170.png)
2. 了解发行版详情。
1. 仔细阅读发行版的说明信息,以了解使用场景、特性、组件构成、使用方法以及如何进行定制化,如下图所示。 1. 仔细阅读发行版的说明信息,以了解使用场景、特性、组件构成、使用方法以及如何进行定制化,如下图所示。
2. 点击「直接下载」,将发行版下载到本地。 2. 点击「直接下载」,将发行版下载到本地。
3. 点击「定制组件」,将对发行版包含的组件进行定制(添加/删除)。 3. 点击「定制组件」,将对发行版包含的组件进行定制(添加/删除)。
**图 2** 发行版示例<a name="fig142484411121"></a> **图2** 发行版示例
![](figure/发行版示例.png "发行版示例")
![zh-cn_image_0000001167734854](figures/zh-cn_image_0000001167734854.png)
3. 定制组件。 3. 定制组件。
1. 进入发行版的定制页面,如下图所示。 1. 进入发行版的定制页面,如下图所示。
2. 通过关闭开关移除可选组件,或者通过“添加组件”增加新的组件。 2. 通过关闭开关移除可选组件,或者通过“添加组件”增加新的组件。
3. 在右边填写您的项目基本信息,包括名称、版本、描述等信息。 3. 在右边填写您的项目基本信息,包括名称、版本、描述等信息。
4. 点击“下载“,系统会根据您的选择,生成相应的OpenHarmony代码结构文件\(如my\_cust\_dist.zip\),保存至本地文件。 4. 点击下载,系统会根据您的选择,生成相应的OpenHarmony代码结构文件(如my_cust_dist.zip),保存至本地文件。
**图3** 组件定制
**图 3** 组件定制<a name="fig1256020372197"></a> ![zh-cn_image_0000001167743458](figures/zh-cn_image_0000001167743458.png)
![](figure/组件定制.png "组件定制")
4. 安装组件。 4. 安装组件。
1. 解压下载的压缩文件,用命令行工具CMD(Linux下的Shell终端)。 1. 解压下载的压缩文件,用命令行工具CMD(Linux下的Shell终端)。
2. 在解压后的文件目录下执行hpm install指令,系统会自动下载并安装组件。安装窗口显示“Install sucessful”表示组件下载及安装成功。 2. 在解压后的文件目录下执行hpm install指令,系统会自动下载并安装组件。安装窗口显示“Install successful”表示组件下载及安装成功。
3. 下载的组件将保存在工程目录下的ohos\_bundles文件夹中(部分组件安装后会将源码复制到指定目录下)。 3. 下载的组件将保存在工程目录下的ohos_bundles文件夹中(部分组件安装后会将源码复制到指定目录下)。
## 获取方式3:从镜像站点获取<a name="section1186691118430"></a> ## 获取方式3:从镜像站点获取
为了获得更好的下载性能,您可以选择从以下站点的镜像库获取源码或者对应的解决方案。 为了获得更好的下载性能,您可以选择从以下站点的镜像库获取源码或者对应的解决方案。
本部分只提供OpenHarmony LTS最新版本和最新发布版本的源码获取方式, 其他版本获取源码方式以及具体版本信息请参考[Release-Notes](../../release-notes/Readme.md) 本部分只提供OpenHarmony LTS最新版本和最新发布版本的源码获取方式, 其他版本获取源码方式以及具体版本信息请参考[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/Readme.md)
**表 1** 获取源码路径 **表1** 获取源码路径
<a name="table17735923173912"></a> | **LTS版本源码** | **版本信息** | **下载站点** | **SHA256校验码** |
<table><thead align="left"><tr id="row1073515237392"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p5109183611392"><a name="p5109183611392"></a><a name="p5109183611392"></a><strong id="b31091936183918"><a name="b31091936183918"></a><a name="b31091936183918"></a>LTS版本源码</strong></p> | -------- | -------- | -------- | -------- |
</th> | 全量代码(标准、轻量和小型系统) | 3.0 | [站点](https://repo.huaweicloud.com/harmonyos/os/3.0/code-v3.0-LTS.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.0/code-v3.0-LTS.tar.gz.sha256) |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p13109436103916"><a name="p13109436103916"></a><a name="p13109436103916"></a><strong id="b191091936153912"><a name="b191091936153912"></a><a name="b191091936153912"></a>版本信息</strong></p> | 标准系统解决方案(二进制) | 3.0 | [站点](https://repo.huaweicloud.com/harmonyos/os/3.0/standard.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.0/standard.tar.gz.sha256) |
</th> | Hi3861解决方案(二进制) | 3.0 | [站点](https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_pegasus.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_pegasus.tar.gz.sha256) |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p610923616398"><a name="p610923616398"></a><a name="p610923616398"></a><strong id="b1210920365393"><a name="b1210920365393"></a><a name="b1210920365393"></a>下载站点</strong></p> | Hi3518解决方案(二进制) | 3.0 | [站点](https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_aries.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_aries.tar.gz.sha256) |
</th> | Hi3516解决方案-LiteOS(二进制) | 3.0 | [站点](https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_taurus.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_taurus.tar.gz.sha256) |
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p2109736133914"><a name="p2109736133914"></a><a name="p2109736133914"></a><strong id="b18109113613397"><a name="b18109113613397"></a><a name="b18109113613397"></a>SHA256校验码</strong></p> | Hi3516解决方案-Linux(二进制) | 3.0 | [站点](https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_taurus_linux.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_taurus_linux.tar.gz.sha256) |
</th> | RELEASE-NOTES | 3.0 | [站点](https://gitee.com/openharmony/docs/blob/OpenHarmony-3.0-LTS/zh-cn/release-notes/OpenHarmony-v3.0-LTS.md) | - |
</tr> | **最新发布版本源码** | **版本信息** | **下载站点** | **SHA256校验码** |
</thead> | 全量代码Release版本(标准、轻量和小型系统) | 3.1 Release | [站点](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/code-v3.1-Release.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/code-v3.1-Release.tar.gz.sha256) |
<tbody><tr id="row17736152318398"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1110983610395"><a name="p1110983610395"></a><a name="p1110983610395"></a>全量代码(标准、轻量和小型系统)</p> | Hi3516标准系统解决方案(二进制) | 3.1 Release | [站点](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_hi3516.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_hi3516.tar.gz.sha256) |
</td> | RK3568标准系统解决方案(二进制) | 3.1 Release | [站点](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_rk3568.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_rk3568.tar.gz.sha256) |
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p151091536143915"><a name="p151091536143915"></a><a name="p151091536143915"></a>3.0</p> | Hi3861解决方案(二进制) | 3.1 Release | [站点](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_pegasus.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_pegasus.tar.gz.sha256) |
</td> | Hi3516解决方案-LiteOS(二进制) | 3.1 Release | [站点](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus.tar.gz.sha256) |
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p15931114016546"><a name="p15931114016546"></a><a name="p15931114016546"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/code-v3.0-LTS.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p> | Hi3516解决方案-Linux(二进制) | 3.1 Release | [站点](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus_linux.tar.gz) | [SHA256校验码](https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus_linux.tar.gz.sha256) |
</td> | RELEASE-NOTES | 3.1 Release | [站点](https://gitee.com/openharmony/docs/tree/OpenHarmony-3.1-Release/zh-cn/release-notes/OpenHarmony-v3.1-Release.md) | - |
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p3770144281415"><a name="p3770144281415"></a><a name="p3770144281415"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/code-v3.0-LTS.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p> | **编译工具链** | **版本信息** | **下载站点** | **SHA256校验码** |
</td> | 编译工具链获取清单 | - | [站点](https://repo.huaweicloud.com/harmonyos/os/2.0/tool_chain/) | - |
</tr>
<tr id="row14814218214"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p2481132228"><a name="p2481132228"></a><a name="p2481132228"></a>标准系统解决方案(二进制)</p>
</td> ## 获取方式4:从github镜像仓库获取
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p94811121629"><a name="p94811121629"></a><a name="p94811121629"></a>3.0</p>
</td> > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1358555631"><a name="p1358555631"></a><a name="p1358555631"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/standard.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p10581551639"><a name="p10581551639"></a><a name="p10581551639"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/standard.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row473612318396"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p511014369394"><a name="p511014369394"></a><a name="p511014369394"></a>Hi3861解决方案(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p0110036193911"><a name="p0110036193911"></a><a name="p0110036193911"></a>3.0</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p29291940175415"><a name="p29291940175415"></a><a name="p29291940175415"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_pegasus.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p134864584147"><a name="p134864584147"></a><a name="p134864584147"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_pegasus.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row873614239395"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p11110113633913"><a name="p11110113633913"></a><a name="p11110113633913"></a>Hi3518解决方案(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p18110193613391"><a name="p18110193613391"></a><a name="p18110193613391"></a>3.0</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p125681045181518"><a name="p125681045181518"></a><a name="p125681045181518"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_aries.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p4607175915149"><a name="p4607175915149"></a><a name="p4607175915149"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_aries.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row1273682343914"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p15110123693919"><a name="p15110123693919"></a><a name="p15110123693919"></a>Hi3516解决方案-LiteOS(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1211012362396"><a name="p1211012362396"></a><a name="p1211012362396"></a>3.0</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p10455184661518"><a name="p10455184661518"></a><a name="p10455184661518"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_taurus.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p84951102150"><a name="p84951102150"></a><a name="p84951102150"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_taurus.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row18945941460"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p12945204118618"><a name="p12945204118618"></a><a name="p12945204118618"></a>Hi3516解决方案-Linux(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p7686415384"><a name="p7686415384"></a><a name="p7686415384"></a>3.0</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p156861155812"><a name="p156861155812"></a><a name="p156861155812"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_taurus_linux.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p16686201510815"><a name="p16686201510815"></a><a name="p16686201510815"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.0/hispark_taurus_linux.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row167371123163914"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p10110143610393"><a name="p10110143610393"></a><a name="p10110143610393"></a>RELEASE-NOTES</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p141101436193911"><a name="p141101436193911"></a><a name="p141101436193911"></a>3.0</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p88931840195416"><a name="p88931840195416"></a><a name="p88931840195416"></a><a href="https://gitee.com/openharmony/docs/blob/OpenHarmony-3.0-LTS/zh-cn/release-notes/OpenHarmony-v3.0-LTS.md" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p039662242117"><a name="p039662242117"></a><a name="p039662242117"></a>-</p>
</td>
</tr>
<tr id="row573719239393"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p104146493390"><a name="p104146493390"></a><a name="p104146493390"></a><strong id="b12414104919398"><a name="b12414104919398"></a><a name="b12414104919398"></a>最新发布版本源码</strong></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p194141849163919"><a name="p194141849163919"></a><a name="p194141849163919"></a><strong id="b441494913918"><a name="b441494913918"></a><a name="b441494913918"></a>版本信息</strong></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p8414649193919"><a name="p8414649193919"></a><a name="p8414649193919"></a><strong id="b341584914393"><a name="b341584914393"></a><a name="b341584914393"></a>下载站点</strong></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p13415149133914"><a name="p13415149133914"></a><a name="p13415149133914"></a><strong id="b8415114953915"><a name="b8415114953915"></a><a name="b8415114953915"></a>SHA256校验码</strong></p>
</td>
</tr>
<tr id="row18518114121312"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p4437184283419"><a name="p4437184283419"></a><a name="p4437184283419"></a>全量代码Release版本(标准、轻量和小型系统)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p15437144213345"><a name="p15437144213345"></a><a name="p15437144213345"></a>3.1 Release</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p64379420343"><a name="p64379420343"></a><a name="p64379420343"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/code-v3.1-Release.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p13437842103414"><a name="p13437842103414"></a><a name="p13437842103414"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/code-v3.1-Release.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row461814235717"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p0618124216579"><a name="p0618124216579"></a><a name="p0618124216579"></a>Hi3516标准系统解决方案(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p156181142145714"><a name="p156181142145714"></a><a name="p156181142145714"></a>3.1 Release</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p16619174275717"><a name="p16619174275717"></a><a name="p16619174275717"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_hi3516.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p79771324121813"><a name="p79771324121813"></a><a name="p79771324121813"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_hi3516.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row162201392319"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p2220191315"><a name="p2220191315"></a><a name="p2220191315"></a>RK3568标准系统解决方案(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p6220191312"><a name="p6220191312"></a><a name="p6220191312"></a>3.1 Release</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p522019916317"><a name="p522019916317"></a><a name="p522019916317"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_rk3568.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p18742268187"><a name="p18742268187"></a><a name="p18742268187"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_rk3568.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row148666201519"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p18867820165113"><a name="p18867820165113"></a><a name="p18867820165113"></a>Hi3861解决方案(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p108671520115118"><a name="p108671520115118"></a><a name="p108671520115118"></a>3.1 Release</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p19867202085113"><a name="p19867202085113"></a><a name="p19867202085113"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_pegasus.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p193613276183"><a name="p193613276183"></a><a name="p193613276183"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_pegasus.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row6114461545"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p630312351557"><a name="p630312351557"></a><a name="p630312351557"></a>Hi3516解决方案-LiteOS(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1612646125413"><a name="p1612646125413"></a><a name="p1612646125413"></a>3.1 Release</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p8123467546"><a name="p8123467546"></a><a name="p8123467546"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p197721270187"><a name="p197721270187"></a><a name="p197721270187"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row152143765612"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p530833917567"><a name="p530833917567"></a><a name="p530833917567"></a>Hi3516解决方案-Linux(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p19213372563"><a name="p19213372563"></a><a name="p19213372563"></a>3.1 Release</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1921337205612"><a name="p1921337205612"></a><a name="p1921337205612"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus_linux.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p14441122810188"><a name="p14441122810188"></a><a name="p14441122810188"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus_linux.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256校验码</a></p>
</td>
</tr>
<tr id="row1663285502319"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1961810962416"><a name="p1961810962416"></a><a name="p1961810962416"></a>RELEASE-NOTES</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p146331255172318"><a name="p146331255172318"></a><a name="p146331255172318"></a>3.1 Release</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p18800131862419"><a name="p18800131862419"></a><a name="p18800131862419"></a><a href="https://gitee.com/openharmony/docs/tree/OpenHarmony-3.1-Release/zh-cn/release-notes/OpenHarmony-v3.1-Release.md" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p8633855132314"><a name="p8633855132314"></a><a name="p8633855132314"></a>-</p>
</td>
</tr>
<tr id="row19937626418"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1938221842"><a name="p1938221842"></a><a name="p1938221842"></a><strong id="b1393619251243"><a name="b1393619251243"></a><a name="b1393619251243"></a>编译工具链</strong></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1093810218417"><a name="p1093810218417"></a><a name="p1093810218417"></a><strong id="b1416114641015"><a name="b1416114641015"></a><a name="b1416114641015"></a>版本信息</strong></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p9938132648"><a name="p9938132648"></a><a name="p9938132648"></a><strong id="b14842143351015"><a name="b14842143351015"></a><a name="b14842143351015"></a>下载站点</strong></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p12520113711011"><a name="p12520113711011"></a><a name="p12520113711011"></a><strong id="b17520237181015"><a name="b17520237181015"></a><a name="b17520237181015"></a>SHA256校验码</strong></p>
</td>
</tr>
<tr id="row204197817410"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p8419118242"><a name="p8419118242"></a><a name="p8419118242"></a>编译工具链获取清单</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p10876124517162"><a name="p10876124517162"></a><a name="p10876124517162"></a>-</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1542078742"><a name="p1542078742"></a><a name="p1542078742"></a><a href="https://repo.huaweicloud.com/harmonyos/os/2.0/tool_chain/" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p134201881147"><a name="p134201881147"></a><a name="p134201881147"></a>-</p>
</td>
</tr>
</tbody>
</table>
## 获取方式4:从github镜像仓库获取<a name="section23448418360"></a>
>![](../public_sys-resources/icon-note.gif) **说明:**
> 镜像仓库每日23:00(UTC +8:00)同步。 > 镜像仓库每日23:00(UTC +8:00)同步。
方式一(推荐):通过repo + ssh下载(需注册公钥,请参考[GitHub帮助中心](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account))。 方式一(推荐):通过repo + ssh下载(需注册公钥,请参考[GitHub帮助中心](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account))。
``` ```
repo init -u git@github.com:openharmony/manifest.git -b master --no-repo-verify repo init -u git@github.com:openharmony/manifest.git -b master --no-repo-verify
repo sync -c repo sync -c
...@@ -342,94 +211,33 @@ repo forall -c 'git lfs pull' ...@@ -342,94 +211,33 @@ repo forall -c 'git lfs pull'
方式二:通过repo + https下载。 方式二:通过repo + https下载。
``` ```
repo init -u https://github.com/openharmony/manifest.git -b master --no-repo-verify repo init -u https://github.com/openharmony/manifest.git -b master --no-repo-verify
repo sync -c repo sync -c
repo forall -c 'git lfs pull' repo forall -c 'git lfs pull'
``` ```
## 源码目录简介<a name="section1072115612811"></a>
## 源码目录简介
下表是OpenHarmony源码目录: 下表是OpenHarmony源码目录:
**表 2** 源码目录 **表2** 源码目录
<a name="table3815144702820"></a> | 目录名 | 描述 |
<table><thead align="left"><tr id="row198162047192810"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p690319291299"><a name="p690319291299"></a><a name="p690319291299"></a>目录名</p> | -------- | -------- |
</th> | applications | 应用程序样例,包括camera等 |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p5903122962918"><a name="p5903122962918"></a><a name="p5903122962918"></a>描述</p> | base | 基础软件服务子系统集&amp;硬件服务子系统集 |
</th> | build | 组件化编译、构建和配置脚本 |
</tr> | docs | 说明文档 |
</thead> | domains | 增强软件服务子系统集 |
<tbody><tr id="row1981674719280"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p69031429162912"><a name="p69031429162912"></a><a name="p69031429162912"></a>applications</p> | drivers | 驱动子系统 |
</td> | foundation | 系统基础能力子系统集 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p090352912914"><a name="p090352912914"></a><a name="p090352912914"></a>应用程序样例,包括camera等</p> | kernel | 内核子系统 |
</td> | prebuilts | 编译器及工具链子系统 |
</tr> | test | 测试子系统 |
<tr id="row5816747132817"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p99031129112918"><a name="p99031129112918"></a><a name="p99031129112918"></a>base</p> | third_party | 开源第三方组件 |
</td> | utils | 常用的工具集 |
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p790472962914"><a name="p790472962914"></a><a name="p790472962914"></a>基础软件服务子系统集&amp;硬件服务子系统集</p> | vendor | 厂商提供的软件 |
</td> | build.py | 编译脚本文件 |
</tr>
<tr id="row1134218692910"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p4904112910295"><a name="p4904112910295"></a><a name="p4904112910295"></a>build</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1090482942911"><a name="p1090482942911"></a><a name="p1090482942911"></a>组件化编译、构建和配置脚本</p>
</td>
</tr>
<tr id="row8166154261316"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1216719425130"><a name="p1216719425130"></a><a name="p1216719425130"></a>docs</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17167134217134"><a name="p17167134217134"></a><a name="p17167134217134"></a>说明文档</p>
</td>
</tr>
<tr id="row1841618902919"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1390462902910"><a name="p1390462902910"></a><a name="p1390462902910"></a>domains</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1390432914296"><a name="p1390432914296"></a><a name="p1390432914296"></a>增强软件服务子系统集</p>
</td>
</tr>
<tr id="row841620912298"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p119041629182919"><a name="p119041629182919"></a><a name="p119041629182919"></a>drivers</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p9904629132911"><a name="p9904629132911"></a><a name="p9904629132911"></a>驱动子系统</p>
</td>
</tr>
<tr id="row164164992915"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p79042298298"><a name="p79042298298"></a><a name="p79042298298"></a>foundation</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p18904132922915"><a name="p18904132922915"></a><a name="p18904132922915"></a>系统基础能力子系统集</p>
</td>
</tr>
<tr id="row1441610922915"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p490402916299"><a name="p490402916299"></a><a name="p490402916299"></a>kernel</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1904112932912"><a name="p1904112932912"></a><a name="p1904112932912"></a>内核子系统</p>
</td>
</tr>
<tr id="row194175972917"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1904132912910"><a name="p1904132912910"></a><a name="p1904132912910"></a>prebuilts</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p390492919296"><a name="p390492919296"></a><a name="p390492919296"></a>编译器及工具链子系统</p>
</td>
</tr>
<tr id="row841718942913"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p12904929202919"><a name="p12904929202919"></a><a name="p12904929202919"></a>test</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p4904152912297"><a name="p4904152912297"></a><a name="p4904152912297"></a>测试子系统</p>
</td>
</tr>
<tr id="row24175915294"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p13904162992916"><a name="p13904162992916"></a><a name="p13904162992916"></a>third_party</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p6904829112917"><a name="p6904829112917"></a><a name="p6904829112917"></a>开源第三方组件</p>
</td>
</tr>
<tr id="row334210652914"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1390442918299"><a name="p1390442918299"></a><a name="p1390442918299"></a>utils</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p690412296297"><a name="p690412296297"></a><a name="p690412296297"></a>常用的工具集</p>
</td>
</tr>
<tr id="row73421664298"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7905172920292"><a name="p7905172920292"></a><a name="p7905172920292"></a>vendor</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p290510290293"><a name="p290510290293"></a><a name="p290510290293"></a>厂商提供的软件</p>
</td>
</tr>
<tr id="row734319617292"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p09056291290"><a name="p09056291290"></a><a name="p09056291290"></a>build.py</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1790542912290"><a name="p1790542912290"></a><a name="p1790542912290"></a>编译脚本文件</p>
</td>
</tr>
</tbody>
</table>
Signed-off-by: duangavin123 <duanxichao@huawei.com>
Merge branch 'master' of https://gitee.com/duangavin123_admin/docs_1
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册