diff --git a/zh-cn/device-dev/driver/Readme-CN.md b/zh-cn/device-dev/driver/Readme-CN.md index 2b3b1d2cb6c12ffe684140c74a0b2d006edfdde7..effd8fab53a77ed313b0a3f15edcd4688e974a48 100755 --- a/zh-cn/device-dev/driver/Readme-CN.md +++ b/zh-cn/device-dev/driver/Readme-CN.md @@ -10,7 +10,10 @@ - [平台驱动开发](driver-develop.md) - [ADC](driver-platform-adc-develop.md) - [GPIO](driver-platform-gpio-develop.md) + - [HDMI](driver-platform-hdmi-develop.md) - [I2C](driver-platform-i2c-develop.md) + - [I3C](driver-platform-i3c-develop.md) + - [MIPI-CSI](driver-platform-mipicsi-develop.md) - [MIPI-DSI](driver-platform-mipidsi-develop.md) - [MMC](driver-platform-mmc-develop.md) - [PWM](driver-platform-pwm-develop.md) @@ -19,22 +22,24 @@ - [SPI](driver-platform-spi-develop.md) - [UART](driver-platform-uart-develop.md) - [WatchDog](driver-platform-watchdog-develop.md) - - [MIPI_CSI](driver-platform-mipicsi-develop.md) - [平台驱动使用](driver-platform.md) + - [ADC](driver-platform-adc-des.md) - [GPIO](driver-platform-gpio-des.md) + - [HDMI](driver-platform-hdmi-des.md) - [I2C](driver-platform-i2c-des.md) + - [I3C](driver-platform-i3c-des.md) + - [MIPI-CSI](driver-platform-mipicsi-des.md) + - [MIPI-DSI](driver-platform-mipidsi-des.md) + - [PWM](driver-platform-pwm-des.md) - [RTC](driver-platform-rtc-des.md) - [SDIO](driver-platform-sdio-des.md) - [SPI](driver-platform-spi-des.md) - [UART](driver-platform-uart-des.md) - [WATCHDOG](driver-platform-watchdog-des.md) - - [MIPI DSI](driver-platform-mipidsi-des.md) - - [PWM](driver-platform-pwm-des.md) - - [MIPI_CSI](driver-platform-mipicsi-des.md) - [外设驱动使用](driver-peripherals.md) - [LCD](driver-peripherals-lcd-des.md) - [TOUCHSCREEN](driver-peripherals-touch-des.md) - [SENSOR](driver-peripherals-sensor-des.md) - [WLAN](driver-peripherals-external-des.md) - [AUDIO](driver-peripherals-audio-des.md) - - [USB](driver-peripherals-usb-des.md) \ No newline at end of file + - [USB](driver-peripherals-usb-des.md) diff --git a/zh-cn/device-dev/driver/driver-develop.md b/zh-cn/device-dev/driver/driver-develop.md index b4bf84d947fb1fdb94ff7280896871f25a806faa..e4cee0c88383f41bd46628a0b0dfd079876f805c 100644 --- a/zh-cn/device-dev/driver/driver-develop.md +++ b/zh-cn/device-dev/driver/driver-develop.md @@ -4,8 +4,14 @@ - **[GPIO](driver-platform-gpio-develop.md)** +- **[HDMI](driver-platform-hdmi-develop.md)** + - **[I2C](driver-platform-i2c-develop.md)** +- **[I3C](driver-platform-i3c-develop.md)** + +- **[MIPI-CSI](driver-platform-mipicsi-develop.md)** + - **[MIPI-DSI](driver-platform-mipidsi-develop.md)** - **[MMC](driver-platform-mmc-develop.md)** @@ -21,5 +27,3 @@ - **[UART](driver-platform-uart-develop.md)** - **[WatchDog](driver-platform-watchdog-develop.md)** - - diff --git a/zh-cn/device-dev/driver/driver-platform-adc-des.md b/zh-cn/device-dev/driver/driver-platform-adc-des.md new file mode 100755 index 0000000000000000000000000000000000000000..bb9ed39d4ae1e4762e6504943e84cdb2f9d60591 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-adc-des.md @@ -0,0 +1,265 @@ +# ADC + +- [概述](#section1) +- [接口说明](#section2) +- [使用指导](#section3) + - [使用流程](#section4) + - [打开ADC设备](#section5) + - [读取AD转换结果](#section6) + - [关闭ADC设备](#section7) + +- [使用实例](#section8) + +## 概述 + +- ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备。 + +- ADC接口定义了完成ADC传输的通用方法集合,包括: + - ADC设备管理:打开或关闭ADC设备。 + - ADC读取转换结果:读取AD转换结果。 + + **图 1** ADC物理连线示意图 + ![](figures/ADC物理连线示意图.png "ADC物理连线示意图") + +## 接口说明 + +**表 1** ADC驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

ADC设备管理接口

+

AdcOpen

+
打开ADC设备

+

AdcClose

+

关闭ADC设备

+

ADC读取转换结果接口

+

AdcRead

+

读取AD转换结果值

+
+ +## 使用指导 + +### 使用流程 + +使用ADC设备的一般流程如[图2](#fig2)所示。 + + **图 2** ADC使用流程图 +![](figures/ADC使用流程图.png "ADC使用流程图") + +### 打开ADC设备 + +在进行AD转换之前,首先要调用AdcOpen打开ADC设备。 + +```c +DevHandle AdcOpen(int16_t number); +``` + +**表 2** AdcOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

number

+

ADC设备号

+

返回值

+

返回值描述

+

NULL

+

打开ADC设备失败

+

设备句柄

+

打开的ADC设备句柄

+
+ +假设系统中存在2个ADC设备,编号从0到1,那么我们现在打开1号设备。 + +```c +DevHandle adcHandle = NULL; /* ADC设备句柄 / + +/* 打开ADC设备 */ +adcHandle = AdcOpen(1); +if (adcHandle == NULL) { + HDF_LOGE("AdcOpen: failed\n"); + return; +} +``` + +### 读取AD转换结果 + +```c +int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t *val); +``` + +**表 3** AdcRead参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

ADC设备句柄

+

channel

+

ADC设备通道号

+

val

+

AD转换结果

+

返回值

+

返回值描述

+

0

+

读取成功

+

负数

+

读取失败

+
+ +### 关闭ADC设备 + +ADC通信完成之后,需要关闭ADC设备。 +```c +void AdcClose(DevHandle handle); +``` +**表 4** AdcClose参数和返回值描述 + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

ADC设备句柄

+

返回值

+

返回值描述

+

+

+
+ +关闭ADC设备示例: + +```c +AdcClose(adcHandle); /* 关闭ADC设备 */ +``` + +## 使用实例 + +本例程以操作开发板上的ADC设备为例,详细展示ADC接口的完整使用流程。 + +本例拟对Hi3516DV300某开发板上ADC设备进行简单的读取操作,基本硬件信息如下: + +- SOC:hi3516dv300。 + +- 原理图信息:电位器挂接在0号ADC设备1通道下。 + +本例程对测试ADC进行连续读取操作,测试ADC功能是否正常。 + +示例如下: + +```c +#include "adc_if.h" /* ADC标准接口头文件 */ +#include "hdf_log.h" /* 标准日志打印头文件 */ + +/* 设备号0,通道号1 */ +#define ADC_DEVICE_NUM 0 +#define ADC_CHANNEL_NUM 1 + +/* ADC例程总入口 */ +static int32_t TestCaseAdc(void) +{ + int32_t i; + int32_t ret; + DevHandle adcHandle; + uint32_t Readbuf[30] = {0}; + + /* 打开ADC设备 */ + adcHandle = AdcOpen(ADC_DEVICE_NUM); + if (adcHandle == NULL) { + HDF_LOGE("%s: Open ADC%u fail!", __func__, ADC_DEVICE_NUM); + return -1; + } + + /* 连续进行30次AD转换并读取转换结果 */ + for (i = 0; i < 30; i++) { + ret = AdcRead(adcHandle, ADC_CHANNEL_NUM, &Readbuf[i]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: tp ADC write reg fail!:%d", __func__, ret); + AdcClose(adcHandle); + return -1; + } + } + HDF_LOGI("%s: ADC read successful!", __func__); + + /* 访问完毕关闭ADC设备 */ + AdcClose(adcHandle); + + return 0; +} +``` + diff --git a/zh-cn/device-dev/driver/driver-platform-adc-develop.md b/zh-cn/device-dev/driver/driver-platform-adc-develop.md index c82f0ed7ced87fb97f94629ccb3eace00811ffb6..c4df774eeec3aeee3722baf645db8c5ecb3a545f 100755 --- a/zh-cn/device-dev/driver/driver-platform-adc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-adc-develop.md @@ -9,8 +9,8 @@ ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备,在HDF框架中,ADC模块接口适配模式采用统一服务模式,这需要一个设备服务来作为ADC模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如ADC可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 -**图 1** ADC统一服务 -![](figures/ADC统一服务.png "ADC统一服务") +**图 1** ADC统一服务模式 +![](figures/统一服务模式结构图.png "ADC统一服务模式") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-gpio-develop.md b/zh-cn/device-dev/driver/driver-platform-gpio-develop.md index 5d4d63ac1f17b61d2fbec88f74129c8b4aac61d4..d489e9aceb8bd5fe7218e3573427382742416dcf 100755 --- a/zh-cn/device-dev/driver/driver-platform-gpio-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-gpio-develop.md @@ -7,12 +7,10 @@ ## 概述 -GPIO(General-purpose input/output)即通用型输入输出,在HDF框架中, - -GPIO的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 +GPIO(General-purpose input/output)即通用型输入输出,在HDF框架中,GPIO的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 **图 1** GPIO无服务模式结构图 -![](figures/GPIO无服务模式结构图.png "GPIO无服务模式结构图") +![](figures/无服务模式结构图.png "GPIO无服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-hdmi-des.md b/zh-cn/device-dev/driver/driver-platform-hdmi-des.md new file mode 100755 index 0000000000000000000000000000000000000000..1ad42787db839705a319f6432f537cb19f86ba5d --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-hdmi-des.md @@ -0,0 +1,1003 @@ +# HDMI + +- [概述](#section1) +- [接口说明](#section2) +- [使用指导](#section3) + - [使用流程](#section4) + - [打开HDMI控制器](#section5) + - [注册热插拔回调函数](#section6) + - [读取EDID](#section7) + - [设置属性](#section8) + - [启动HDMI传输](#section10) + - [停止HDMI传输](#section11) + - [注销热插拔回调函数](#section12) + - [关闭HDMI控制器](#section13) + +- [使用实例](#section14) + +## 概述 + +- HDMI(High-Definition Multiface Interface)是Hitachi, Panasonic, Philips, SiliconImage, Sony, Thomson, Toshiba共同发布的一款音视频传输协议。 +- HDMI以主从方式工作,通常有一个Source端和一个Sink端。 +- HDMI接口定义了完成HDMI传输的通用方法集合,包括: + + - HDMI控制器管理:打开或关闭HDMI控制器 + - HDMI启动/停止传输:启动或停止HDMI传输 + - HDMI控制器设置:设置音频、视频及HDR属性,设置色彩深度、声音图像消隐等 + - HDMI读取EDID:读取Sink端原始的EDID数据 + - HDMI热插拔:注册/注销热插拔回调函数 +- HDMI物理连接如[图1](#fig1)所示: + **图 1** HDMI物理连线示意图 + ![](figures/HDMI物理连线示意图.png "HDMI物理连线示意图") + +## 接口说明 + +**表 1** HDMI驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

HDMI控制器管理接口

+

HdmiOpen

+
打开HDMI控制器

+

HdmiClose

+

关闭HDMI控制器

+

启动/停止HDMI传输接口

+

HdmiStart

+
启动HDMI传输

+

HdmiStop

+

停止HDMI传输

+

HDMI控制器设置接口

+

HdmiAvmuteSet

+
HDMI声音图像消隐设置

+

HdmiDeepColorSet

+

设置色彩深度

+

HdmiDeepColorGet

+

获取色彩深度

+

HdmiSetVideoAttribute

+

设置视频属性

+

HdmiSetAudioAttribute

+

设置音频属性

+

HdmiSetHdrAttribute

+

设置HDR属性

+

EDID获取接口

+

HdmiReadSinkEdid

+
HDMI读取Sink端原始EDID数据

+

HDMI热插拔相关接口

+

HdmiRegisterHpdCallbackFunc

+
注册HDMI热插拔检测回调函数

+

HdmiUnregisterHpdCallbackFunc

+

注销HDMI热插拔检测回调函数

+
+ +## 使用指导 + +### 使用流程 + +使用HDMI设备的一般流程如[图2](#fig2)所示。 + +**图 2** HDMI设备使用流程图 +![](figures/HDMI使用流程图.png "HDMI使用流程图") + +### 打开HDMI控制器 + +在进行HDMI通信前,首先要调用HdmiOpen打开HDMI控制器。 + +```c +DevHandle HdmiOpen(int16_t number); +``` + +**表 2** HdmiOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

number

+

HDMI控制器号

+

返回值

+

返回值描述

+

NULL

+

打开HDMI控制器失败

+

控制器句柄

+

打开的HDMI控制器句柄

+
+ +假设系统中存在2个HDMI控制器,编号从0到1,那么我们现在获取0号控制器: + +```c +DevHandle hdmiHandle = NULL; /* HDMI控制器句柄 / + +/* 打开HDMI控制器 */ +hdmiHandle = HdmiOpen(0); +if (hdmiHandle == NULL) { + HDF_LOGE("HdmiOpen: failed\n"); + return; +} +``` + +### 注册热插拔检测回调函数 + +```c +int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback); +``` + +**表 3** HdmiRegisterHpdCallbackFunc参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

callback

+

热插拔回调函数信息

+

返回值

+

返回值描述

+

0

+

注册成功

+

负数

+

注册失败

+
+ +注册热插拔检测回调函数示例: + +```c +/* 热插拔检测回调函数定义 */ +static void HdmiHpdHandle(void *data, bool hpd) +{ + if (data == NULL) { + HDF_LOGE("priv data is NULL"); + return; +} + + if (hpd == true) { + HDF_LOGD("HdmiHpdHandle: hot plug"); + /* 调用者添加相关处理 */ + } else { + HDF_LOGD("HdmiHpdHandle: hot unplog"); + /* 调用者添加相关处理 */ + } +} + + /* 热插拔检测回调函数注册示例 */ + struct HdmiHpdCallbackInfo info = {0}; + info.data = handle; + info.callbackFunc = HdmiHpdHandle; + ret = HdmiRegisterHpdCallbackFunc(hdmiHandle, info); + if (ret != 0) { + HDF_LOGE("HdmiRegisterHpdCallbackFunc: Register failed."); + } +``` + +### 读取EDID + +```c +int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len); +``` + +**表 4** HdmiReadSinkEdid参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

buffer

+

数据缓冲区

+

len

+

数据长度

+

返回值

+

返回值描述

+

正整数

+

成功读取的原始EDID数据

+

负数或0

+

读取失败

+
+ +读取Sink端的原始EDID数据示例: + +```c +int32_t len; +uint8_t edid[HDMI_EDID_MAX_LEN] = {0}; + +len = HdmiReadSinkEdid(hdmiHandle, edid, HDMI_EDID_MAX_LEN); +if (len <= 0) { + HDF_LOGE("%s: HdmiReadSinkEdid failed len = %d.", __func__, len); +} +``` + +### 设置音频、视频及HDR属性 + +#### 设置音频属性 + +```c +int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr); +``` + +**表 5** HdmiSetAudioAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

attr

+

音频属性

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置音频属性示例: + +```c +struct HdmiAudioAttr audioAttr = {0}; +int32_t ret; + +audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3; +audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S; +audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16; +audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K; +audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3; +ret = HdmiSetAudioAttribute(handle, &audioAttr); +if (ret != 0) { + HDF_LOGE("HdmiSetAudioAttribute failed."); +} +``` + +#### 设置视频属性 + +```c +int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr); +``` + +**表 6** HdmiSetVideoAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

attr

+

视频属性

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置视频属性示例: + +```c +struct HdmiVideoAttr videoAttr = {0}; +int32_t ret; + +videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444; +videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED; +videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM; +videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL; +ret = HdmiSetVideoAttribute(handle, &videoAttr); +if (ret != 0) { + HDF_LOGE("HdmiSetVideoAttribute failed."); +} +``` + +#### 设置HDR属性 + +```c +int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr); +``` + +**表 7** HdmiSetHdrAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

attr

+

HDR属性

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置HDR属性示例: + +```c +struct HdmiHdrAttr hdrAttr = {0}; +int32_t ret; + +hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3; +hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY; +hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048; +hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1; +hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709; +ret = HdmiSetHdrAttribute(handle, &hdrAttr); +if (ret != 0) { + HDF_LOGE("HdmiSetHdrAttribute failed."); +} +``` + +### 其他可选设置 + +#### 设置HDMI声音图像消隐 + +```c +int32_t HdmiAvmuteSet(DevHandle handle, bool enable); +``` + +**表 8** HdmiAvmuteSet参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

enable

+

使能/去使能avmute

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置声音图像消隐示例: + +```c +int32_t ret; + +ret = HdmiAvmuteSet(hdmiHandle, true); +if (ret != 0) { + HDF_LOGE("HdmiAvmuteSet failed."); +} +``` + +#### 设置色彩深度 + +```c +int32_t HdmiDeepColorSet(DevHandle handle, enum HdmiDeepColor color); +``` + +**表 9** HdmiDeepColorSet参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

color

+

色彩深度

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +设置色彩深度示例: + +```c +int32_t ret; + +ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS); +if (ret != 0) { + HDF_LOGE("HdmiDeepColorSet failed."); +} +``` + +#### 获取色彩深度 + +```c +int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color); +``` + +**表 10** HdmiDeepColorGet参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

color

+

色彩深度

+

返回值

+

返回值描述

+

0

+

获取成功

+

负数

+

获取失败

+
+ +获取色彩深度示例: + +```c +enum HdmiDeepColor color; +int32_t ret; + +ret = HdmiDeepColorGet(handle, &color); +if (ret != 0) { + HDF_LOGE("HdmiDeepColorGet failed."); +} +``` + +### 启动HDMI传输 + +```c +int32_t HdmiStart(DevHandle handle); +``` + +**表 11** HdmiStart参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

返回值

+

返回值描述

+

0

+

启动成功

+

负数

+

启动失败

+
+ +启动HDMI传输示例: + +```c +int32_t ret; + +ret = HdmiStart(hdmiHandle); +if (ret != 0) { + HDF_LOGE("start transmission failed."); +} +``` + +### 停止HDMI传输 + +```c +int32_t HdmiStop(DevHandle handle); +``` + +**表 12** HdmiStop参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

返回值

+

返回值描述

+

0

+

停止成功

+

负数

+

停止失败

+
+ +停止HDMI传输示例: + +```c +int32_t ret; + +ret = HdmiStop(hdmiHandle); +if (ret != 0) { + HDF_LOGE("stop transmission failed."); +} +``` + +### 注销热插拔检测回调函数 + +```c +int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle); +``` + +**表 13** HdmiUnregisterHpdCallbackFunc参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+

返回值

+

返回值描述

+

0

+

注销成功

+

负数

+

注销失败

+
+ +注销热插拔检测回调函数示例: + +```c +int32_t ret; + +ret = HdmiUnregisterHpdCallbackFunc(hdmiHandle); +if (ret != 0) { + HDF_LOGE("unregister failed."); +} +``` + +### 关闭HDMI控制器 + +```c +void HdmiClose(DevHandle handle); +``` + +**表 14** HdmiClose参数和返回值描述 + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

HDMI控制器句柄

+
+ +关闭HDMI控制器示例: + +```c +HdmiClose(hdmiHandle); +``` + +## 使用实例 + +本例程以操作开发板上的HDMI设备为例,详细展示HDMI接口的完整使用流程。 + +本例拟在Hi3516DV300开发板上对虚拟驱动进行简单的传输操作: + +- SOC:hi3516dv300。 + +- HDMI控制器:使用0号HDMI控制器。 + + +示例如下: + +```c +#include "hdmi_if.h" /* HDMI标准接口头文件 */ +#include "hdf_log.h" /* 标准日志打印头文件 */ +#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */ + +/* 热插拔回调函数 */ +static void HdmiHpdHandle(void *data, bool hpd) +{ + if (data == NULL) { + HDF_LOGE("priv data is NULL"); + return; + } + + if (hpd == true) { + HDF_LOGD("HdmiHpdHandle: hot plug"); + /* 调用者添加相关处理 */ + } else { + HDF_LOGD("HdmiHpdHandle: hot unplog"); + /* 调用者添加相关处理 */ + } +} + +/* 设置HDMI相关属性 */ +static int32_t TestHdmiSetAttr(DevHandle handle) +{ + enum HdmiDeepColor color; + struct HdmiVideoAttr videoAttr = {0}; + struct HdmiAudioAttr audioAttr = {0}; + struct HdmiHdrAttr hdrAttr = {0}; + int32_t ret; + + ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS); + + if (ret != 0) { + HDF_LOGE("HdmiDeepColorSet failed."); + return ret; + } + ret = HdmiDeepColorGet(handle, &color); + if (ret != 0) { + HDF_LOGE("HdmiDeepColorGet failed."); + return ret; + } + HDF_LOGE("HdmiDeepColorGet successful, color = %d.", color); + videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444; + videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED; + videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM; + videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL; + ret = HdmiSetVideoAttribute(handle, &videoAttr); + if (ret != 0) { + HDF_LOGE("HdmiSetVideoAttribute failed."); + return ret; + } + audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3; + audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S; + audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16; + audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K; + audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3; + ret = HdmiSetAudioAttribute(handle, &audioAttr); + if (ret != 0) { + HDF_LOGE("HdmiSetAudioAttribute failed."); + return ret; + } + hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3; + hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY; + hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048; + hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1; + hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709; + ret = HdmiSetHdrAttribute(handle, &hdrAttr); + if (ret != 0) { + HDF_LOGE("HdmiSetHdrAttribute failed."); + return ret; + } + + return 0; +} + +/* HDMI例程总入口 */ +static int32_t TestCaseHdmi(void) +{ + DevHandle handle = NULL; + int32_t ret; + + struct HdmiHpdCallbackInfo info = {0}; + uint8_t data[128] = {0}; + + HDF_LOGD("HdmiAdapterInit: successful."); + handle = HdmiOpen(0); + if (handle == NULL) { + HDF_LOGE("HdmiOpen failed."); + return ret; + } + info.data = handle; + info.callbackFunc = HdmiHpdHandle; + ret = HdmiRegisterHpdCallbackFunc(handle, &info); + if (ret != 0) { + HDF_LOGE("HdmiRegisterHpdCallbackFunc failed."); + return ret; + } + + ret = HdmiReadSinkEdid(handle, data, 128); + if (ret <= 0) { + HDF_LOGE("HdmiReadSinkEdid failed."); + return ret; + } + HDF_LOGE("HdmiReadSinkEdid successful, data[6] = %d, data[8] = %d.", data[6], data[8]); + + ret = TestHdmiSetAttr(handle); + if (ret != 0) { + HDF_LOGE("TestHdmiSetAttr failed."); + return ret; + } + + ret = HdmiStart(handle); + if (ret != 0) { + HDF_LOGE("HdmiStart failed."); + return ret; + } + + OsalMSleep(1000); + + ret = HdmiStop(handle); + if (ret != 0) { + HDF_LOGE("HdmiStop failed."); + return ret; + } + + ret = HdmiUnregisterHpdCallbackFunc(handle); + if (ret != 0) { + HDF_LOGE("HdmiUnregisterHpdCallbackFunc failed."); + return ret; + } + HdmiClose(handle); + return 0; +} + +``` \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md b/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md new file mode 100755 index 0000000000000000000000000000000000000000..408a31c4229be396fec6afe707d2e4a124d63309 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-hdmi-develop.md @@ -0,0 +1,383 @@ +# HDMI + +- [概述](#1) +- [开发步骤](#2) +- [开发实例](#3) + +## 概述 + +HDMI(High-Definition Multiface Interface)是Hitachi、Panasonic、Philips、SiliconImage、Sony、Thomson、Toshiba共同发布的一款音视频传输协议,主要用于DVD、机顶盒等音视频source到TV、显示器等sink设备的传输。传输过程遵循TMDS(Transition Minimized Differential Signaling)协议。 + +在HDF框架中,HDMI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用率。 + + **图 1** HDMI统一服务模式 + +![image1](figures/独立服务模式结构图.png) + +## 开发步骤 + +HDMI模块适配的三个环节是配置属性文件,实例化驱动入口以及实例化HDMI控制器对象。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device_info.hcs文件中添加deviceNode描述。 + - 【可选】添加hdmi_config.hcs器件属性文件。 + +3. **实例化HDMI控制器对象:** + - 初始化HdmiCntlr成员。 + - 实例化HdmiCntlr成员HdmiCntlrOps方法集合,其定义和成员函数说明见下文。 + + HdmiCntlrOps定义: + ```c + struct HdmiCntlrOps { + void (*hardWareInit)(struct HdmiCntlr *cntlr); + void (*hardWareStatusGet)(struct HdmiCntlr *cntlr, struct HdmiHardwareStatus *status); + void (*controllerReset)(struct HdmiCntlr *cntlr); + bool (*hotPlugStateGet)(struct HdmiCntlr *cntlr); + bool (*hotPlugInterruptStateGet)(struct HdmiCntlr *cntlr); + void (*lowPowerSet)(struct HdmiCntlr *cntlr, bool enable); + void (*tmdsModeSet)(struct HdmiCntlr *cntlr, enum HdmiTmdsModeType mode); + int32_t (*tmdsConfigSet)(struct HdmiCntlr *cntlr, struct HdmiTmdsConfig mode); + void (*infoFrameEnable)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, bool enable); + int32_t (*infoFrameSend)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, uint8_t *data, uint32_t len); + int32_t (*infoFrameDataSet)(struct HdmiCntlr *cntlr, uint32_t type, uint8_t *data, uint32_t len); + int32_t (*cecMsgSend)(struct HdmiCntlr *cntlr, struct HdmiCecMsg *msg); + void (*audioPathEnable)(struct HdmiCntlr *cntlr, bool enable); + void (*audioPathSet)(struct HdmiCntlr *cntlr, struct HdmiAudioConfigInfo *config); + void (*phyOutputEnable)(struct HdmiCntlr *cntlr, bool enable); + void (*phyOutputSet)(struct HdmiCntlr *cntlr, struct HdmiPhyCfg *cfg); + void (*blackDataSet)(struct HdmiCntlr *cntlr, bool enable); + void (*videoMuteEnable)(struct HdmiCntlr *cntlr, bool enable); + void (*videoPathSet)(struct HdmiCntlr *cntlr, struct HdmiVideoAttr *attr); + void (*audioMuteEnable)(struct HdmiCntlr *cntlr, bool enable); + void (*avmuteSet)(struct HdmiCntlr *cntlr, bool enable); + int32_t (*ddcTransfer)(struct HdmiCntlr *cntlr, struct HdmiDdcCfg *ddcCfg); + bool (*scdcSourceScrambleGet)(struct HdmiCntlr *cntlr); + int32_t (*scdcSourceScrambleSet)(struct HdmiCntlr *cntlr, bool enable); + void (*frlSet)(struct HdmiCntlr *cntlr); + int32_t (*frlEnable)(struct HdmiCntlr *cntlr, bool enable); + int32_t (*audioNctsSet)(struct HdmiCntlr *cntlr, struct HdmiFrlAudioNctsConfig *cfg); + void (*frlTrainingConfigSet)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainConfig *cfg); + void (*frlTrainingStart)(struct HdmiCntlr *cntlr); + void (*frlGetTriningRslt)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainRslt *rslt); + void (*hdcpRegInit)(struct HdmiCntlr *cntlr); + int32_t (*hdcpGenerateAksvAndAn)(struct HdmiCntlr *cntlr); + int32_t (*hdcpOptReg)(struct HdmiCntlr *cntlr, enum HdmiHdcpRegOptType type, uint8_t *data, uint32_t len); + void (*hdrTimerSet)(struct HdmiCntlr *cntlr, struct HdmiHdrTimerConfig *config); + }; + ``` + + 表1 HdmiCntlrOps结构体成员的回调函数功能说明 + + | 函数成员 | 入参 | 出参 | 返回值 | 功能 | + | ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------ | -------------------------------------------------- | + | hardWareInit | **cntlr**: 结构体指针,核心层HDMI控制器; | 无 | 无 | HDMI硬件初始化 | + | hardWareStatusGet | **cntlr**: 结构体指针,核心层HDMI控制器;
| **status**:HDMI硬件状态 ; | 无 | 获取HDMI当前硬件状态 | + | controllerReset | **cntlr**: 结构体指针,核心层HDMI控制器; | 无 | 无 | HDMI控制器复位 | + | hotPlugStateGet | **cntlr**: 结构体指针,核心层HDMI控制器; | 无 | bool: HDMI热插拔状态 | 获取HDMI热插拔状态 | + | hotPlugInterruptStateGet | **cntlr**: 结构体指针,核心层HDMI控制器; | 无 | bool: HDMI热插拔中断状态 | 获取HDMI热插拔中断状态 | + | lowPowerSet | **cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能 | 无 | 无 | 使能/去使能低功耗 | + | tmdsModeSet | **cntlr**: 结构体指针,核心层HDMI控制器;
**mode**:TMDS模式 | 无 | 无 | 设置TMDS模式 | + |tmdsConfigSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**mode**: TMDS参数|无|HDF_STATUS相关状态|配置TMDS参数| + |infoFrameEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**infoFrameType**: packet类型
**enable**: bool,使能/去使能|无|无|使能/去使能infoFrame| + |infoFrameSend|**cntlr**: 结构体指针,核心层HDMI控制器;
**infoFrameType**: packet类型
**data**: infoFrame数据
**len**:数据长度|无|HDF_STATUS相关状态|发送inforFrame| + |cecMsgSend|**cntlr**: 结构体指针,核心层HDMI控制器;
**msg**: CEC消息|无|HDF_STATUS相关状态|发送CEC消息| + |audioPathEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能audio通路| + |audioPathSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**config**: 配置信息|无|无|设置audio通路配置信息| + |phyOutputEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能物理层输出状态| + |phyOutputSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**cfg**: 配置信息|无|无|设置物理层配置信息| + |blackDataSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|黑屏设置| + |videoMuteEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能video静音| + |videoPathSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**attr**: 配置信息|无|无|设置viedo通路配置信息| + |audioMuteEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能audio静音| + |avmuteSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|无|使能/去使能声音图像消隐| + |ddcTransfer|**cntlr**: 结构体指针,核心层HDMI控制器;
**ddcCfg**:DDC配置参数|**ddcCfg**:DDC配置参数|HDF_STATUS相关状态|DDC读写数据| + |scdcSourceScrambleGet|**cntlr**: 结构体指针,核心层HDMI控制器;|无|bool,加扰状态|获取source端的加扰状态| + |scdcSourceScrambleSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|HDF_STATUS相关状态|使能/去使能source端的加扰| + |frlEnable|**cntlr**: 结构体指针,核心层HDMI控制器;
**enable**: bool,使能/去使能|无|HDF_STATUS相关状态|使能/去使能FRL| + |audioNctsSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**cfg**:N/CTS配 置参数|无|HDF_STATUS相关状态|设置audio的N/CTS信息| + |frlTrainingConfigSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**cfg**:FRL Traning配置参数|无|无|设置FRL Traning配置信息| + |frlTrainingStart|**cntlr**: 结构体指针,核心层HDMI控制器;|无|无|开始FRL Traning流程| + |frlGetTriningRslt|**cntlr**: 结构体指针,核心层HDMI控制器;|**rslt**:FRL Traning结果|无|获取FRL Traning结果| + |hdcpRegInit|**cntlr**: 结构体指针,核心层HDMI控制器;|无|无|初始化HDCP流程相关的寄存器| + |hdcpGenerateAksvAndAn|**cntlr**: 结构体指针,核心层HDMI控制器;|无|HDF_STATUS相关状态|HDCP流程中生成aksv和an| + |hdcpOptReg|**cntlr**: 结构体指针,核心层HDMI控制器;
**type**: 操作类型
**data**: 寄存器数据
**len**: 数据长度|**data**: 寄存器数据|HDF_STATUS相关状态|HDCP流程中的相关寄存器读写操作| + |hdrTimerSet|**cntlr**: 结构体指针,核心层HDMI控制器;
**config**: timer配置信息|无|无|设置HDR相关的timer配置信息| + +## 开发实例 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + HDMI驱动入口参考: + + ```c + struct HdfDriverEntry g_hdmiDriverEntry = { + .moduleVersion = 1, + .Bind = HdmiAdapterBind, + .Init = HdmiAdapterInit, + .Release = HdmiAdapterRelease, + .moduleName = "adapter_hdmi_driver",//【必要】与HCS里面的名字匹配 + }; + HDF_INIT(g_hdmiDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + ``` + +2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在hdmi_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层HdmiCntlr相关成员的默认值或限制范围有密切关系。 + + 从第一个节点开始配置具体HDMI控制器信息,此节点并不表示某一路HDMI控制器,而是代表一个资源性质设备,用于描述一类HDMI控制器的信息。本例只有一个HDMI控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在hdmi_config文件中增加对应的器件属性。 + + - device_info.hcs 配置参考 + + ```c + root { + platform :: host { + device_hdmi :: device { + device0 :: deviceNode { + policy = 2; // 等于2,需要发布服务 + priority = 20; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + serviceName = "HDF_PLATFORM_HDMI_0"; //【必要】驱动对外发布服务的名称,必须唯一 + moduleName = "hdmi_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + deviceMatchAttr = "adapter_hdmi_driver"; //【必要】用于配置控制器私有数据,要与hdmi_config.hcs中对应控制器保持一致 + } // 具体的控制器信息在 hdmi_config.hcs 中 + } + } + } + ``` + + - hdmi_config.hcs 配置参考 + + ```c + root { + platform { + hdmi_config { + template hdmi_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + match_attr = ""; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + index = 0; //【必要】hdmi控制器编号 + regBasePhy = 0x10100000; //【必要】寄存器物理基地址 + regSize = 0xd1; //【必要】寄存器位宽 + irqNum = 100; //【必要】中断号 + maxTmdsClock = 300; + videoTiming = 10; + quantization = 1; + colorSpace = 0; + colorimetry = 0; + audioIfType = 0; + audioBitDepth = 1; + audioSampleRate = 2; + audioChannels = 1; + hdrColorimetry = 4; + hdrUserMode = 1; + cap = 0xd001e045; + } + controller_0x10100000 :: hdmi_controller { + match_attr = "adapter_hdmi_driver"; + index = 0; + regBasePhy = 0x10100000; + irqNum = 100; + maxTmdsClock = 400; + defTmdsClock = 300; + maxFrlRate = 600; + videoTiming = 10; + quantization = 1; + colorSpace = 0; + colorimetry = 0; + audioIfType = 0; + audioSampleRate = 2; + audioChannels = 1; + hdrColorimetry = 4; + hdrUserMode = 1; + cap = 0xd001e045; + } + } + } + } + ``` + +3. 最后一步,完成驱动入口注册之后,要以核心层HdmiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化HdmiCntlr成员HdmiCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + + - 自定义结构体参考 + + > ![](../public_sys-resources/icon-note.gif) **说明:** + > 从驱动角度看,自定义结构体是参数和数据的载体。HDF会读取hdmi_config.hcs文件中的数值并通过DeviceResourceIface来初始化结构体成员,且其中一些重要数值(例如设备号、总线号等)也会被传递给核心层HdmiCntlr对象。 + + ```c + struct HdmiAdapterHost { + struct HdmiCntlr *cntlr; //【必要】是核心层控制对象,具体描述如下 + volatile unsigned char *regBase;//【必要】寄存器基地址 + uint32_t regBasePhy; //【必要】寄存器物理基地址 + uint32_t regSize; //【必要】寄存器位宽 + uint32_t irqNum; //【必要】中断号 + }; + + /* HdmiCntlr是核心层控制器结构体,其中的成员在Init函数中被赋值 */ + struct HdmiCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *hdfDevObj; + struct PlatformDevice device; + struct OsalMutex mutex; + struct PlatformQueue *msgQueue; + struct HdmiCntlrCap cap; + struct HdmiAttr attr; + struct HdmiCntlrOps *ops; + uint32_t deviceIndex; + uint32_t state; // 控制器状态 + enum HdmiTmdsModeType tmdsMode; + struct HdmiDevice *hdmi; + struct HdmiInfoframe infoframe; + struct HdmiScdc *scdc; + struct HdmiDdc ddc; + struct HdmiFrl *frl; + struct HdmiHdcp *hdcp; + struct HdmiCec *cec; + struct HdmiEvent event; + struct HdmiHdr *hdr; + void *priv; + }; + ``` + + - **【重要】** HdmiCntlr成员回调函数结构体HdmiCntlrOps的实例化 + + ```c + static struct HdmiCntlrOps g_hdmiAdapterHostOps = { + .hardWareInit = HdmiAdapterHardWareInit, + .hardWareStatusGet = HdmiAdapterHardWareStatusGet, + .controllerReset = HdmiAdapterControllerReset, + .hotPlugStateGet = HdmiAdapterHotPlugStateGet, + .hotPlugInterruptStateGet = HdmiAdapterHotPlugInterruptStateGet, + .lowPowerSet = HdmiAdapterLowPowerSet, + .tmdsModeSet = HdmiAdapterTmdsModeSet, + .tmdsConfigSet = HdmiAdapterTmdsConfigSet, + .infoframeEnable = HdmiAdapterInfoframeEnable, + .infoframeSend = HdmiAdapterInfoframeSend, + .infoframeDataSet = HdmiAdapterInfoframeDataSet, + .cecMsgSend = HdmiAdapterCecMsgSend, + .audioPathEnable = HdmiAdapterAudioPathEnable, + .audioPathSet = HdmiAdapterAudioPathSet, + .phyOutputEnable = HdmiAdapterPhyOutputEnable, + .phyOutputSet = HdmiAdapterPhyOutputSet, + .blackDataSet = HdmiAdapterBlackDataSet, + .videoMuteEnable = HdmiAdapterVideoMuteEnable, + .videoPathSet = HdmiAdapterVideoPathSet, + .audioMuteEnable = HdmiAdapterAudioMuteEnable, + .avmuteSet = HdmiAdapterAvmuteSet, + .ddcTransfer = HdmiAdapterDdcTransfer, + .scdcSourceScrambleGet = HdmiAdapterScdcSourceScrambleGet, + .scdcSourceScrambleSet = HdmiAdapterScdcSourceScrambleSet, + .frlSet = HdmiAdapterFrlSet, + .frlEnable = HdmiAdapterFrlEnable, + .audioNctsSet = HdmiAdapterAudioNctsSet, + .frlTrainingConfigSet = HdmiAdapterFrlTrainingConfigSet, + .frlTrainingStart = HdmiAdapterFrlTrainingStart, + .frlGetTriningRslt = HdmiAdapterFrlGetTriningRslt, + .hdcpRegInit = HdmiAdapterHdcpRegInit, + .hdcpGenerateAksvAndAn = HdmiAdapterHdcpGenerateAksvAndAn, + .hdcpOptReg = HdmiAdapterHdcpOptReg, + .hdrTimerSet = HdmiAdapterHdrTimerSet, + }; + ``` + + - **Bind函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外呈现的接口参数,具备 HCS 配置文件的信息 + > + > **返回值:** + > HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) + + |状态(值)|状态描述| + |:-|:-| + |HDF_ERR_INVALID_OBJECT|控制器对象非法| + |HDF_ERR_INVALID_PARAM |参数非法| + |HDF_ERR_MALLOC_FAIL |内存分配失败| + |HDF_ERR_IO |I/O 错误| + |HDF_SUCCESS |传输成功| + |HDF_FAILURE |传输失败| + + > **函数说明:** + > 初始化自定义结构体对象HdmiAdapterHost,初始化HdmiCntlr成员,调用核心层HdmiCntlrAdd函数。 + > + > HdmiCntlr,HdmiAdapterHost,HdfDeviceObject之间互相赋值,方便其他函数可以相互转化。 + + ```c + static int32_t HdmiAdapterBind(struct HdfDeviceObject *obj) + { + struct HdmiCntlr *cntlr = NULL; + struct HimciAdapterHost *host = NULL; + int32_t ret; + cntlr = (struct HdmiCntlr *)OsalMemCalloc(sizeof(struct HdmiCntlr)); + if (cntlr == NULL) { + HDF_LOGE("%s: malloc cntlr failed!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + host = (struct HimciAdapterHost *)OsalMemCalloc(sizeof(struct HimciAdapterHost)); + if (host == NULL) { + HDF_LOGE("%s: malloc host failed!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + cntlr->priv = (void *)host; //【必要】将host存放至cntlr的私有数据 + cntlr->ops = &g_hdmiHostOps; //【必要】HdmiCntlrOps的实例化对象的挂载 + cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 + obj->service = &cntlr->service; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 + ret = HdmiAdapterCntlrParse(cntlr, obj); //【必要】 初始化 cntlr. 失败则 goto __ERR; + ... + ret = HdmiAdapterHostParse(host, obj); //【必要】 初始化 host对象的相关属性,失败则 goto __ERR; + ... + ret = HdmiAdapterHostInit(host, cntlr); //厂商自定义的初始化,失败则 goto __ERR; + ... + ret = HdmiCntlrAdd(cntlr); //调用核心层函数 失败则 goto __ERR; + ... + HDF_LOGD("HdmiAdapterBind: success."); + return HDF_SUCCESS; + __ERR: + HdmiAdapterDeleteHost(host); + HDF_LOGD("HdmiAdapterBind: fail, err = %d.", ret); + return ret; + } + ``` + + - **init函数参考** + + >**入参:** + >HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + > + >**返回值:** + >HDF_STATUS相关状态 + > + >函数说明: + > + >实现HdmiAdapterInit函数。 + + ```c + static int32_t HdmiAdapterInit(struct HdfDeviceObject *obj) + { + return HDF_SUCCESS; + } + ``` + + - **Release 函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + > + > **返回值:** + > 无 + > + > **函数说明:** + > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 + + ```c + static void HdmiAdapterRelease(struct HdfDeviceObject *obj) + { + struct HdmiCntlr *cntlr = NULL; + ... + cntlr = (struct HdmiCntlr *)obj->service;//这里有HdfDeviceObject到HdmiCntlr的强制转化,通过service成员,赋值见Bind函数 + ... + HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);//厂商自定义的内存释放函数,这里有HdmiCntlr到HimciAdapterHost的强制转化 + } + ``` + > 所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 diff --git a/zh-cn/device-dev/driver/driver-platform-i2c-develop.md b/zh-cn/device-dev/driver/driver-platform-i2c-develop.md index a056cf3e1b7dd380288879309cf7ac5621676a3c..3fd15170cc7e61ea8e3bcc047cf82967bd716562 100755 --- a/zh-cn/device-dev/driver/driver-platform-i2c-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-i2c-develop.md @@ -7,10 +7,10 @@ ## 概述 -I2C\(Inter Integrated Circuit\)总线是由Philips公司开发的一种简单、双向二线制同步串行总线,在HDF框架中,I2C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I2C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I2C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 +I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线,在HDF框架中,I2C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I2C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I2C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 **图 1** I2C统一服务模式结构图 -![](figures/I2C统一服务模式结构图.png "I2C统一服务模式结构图") +![](figures/统一服务模式结构图.png "I2C统一服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-i3c-des.md b/zh-cn/device-dev/driver/driver-platform-i3c-des.md new file mode 100755 index 0000000000000000000000000000000000000000..b2000091489dfa80a596c360fcdd776dab8a92c4 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-i3c-des.md @@ -0,0 +1,620 @@ +# I3C + +- [概述](#section1) +- [接口说明](#section2) +- [使用指导](#section3) + - [使用流程](#section4) + - [打开I3C控制器](#section5) + - [进行I3C通信](#section6) + - [获取I3C控制器配置](#section7) + - [配置I3C控制器](#section8) + - [请求IBI(带内中断)](#section9) + - [释放IBI(带内中断)](#section10) + - [关闭I3C控制器](#section11) + +- [使用实例](#section12) + +## 概述 + +- I3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一种简单、低成本的双向二线制同步串行总线。 +- I3C总线向下兼容传统的I2C设备,同时增加了带内中断(In-Bind Interrupt)功能,支持I3C设备进行热接入操作,弥补了I2C总线需要额外增加中断线来完成中断的不足。 +- I3C总线上允许同时存在I2C设备、I3C从设备和I3C次级主设备。 +- I3C接口定义了完成I3C传输的通用方法集合,包括: + + - I3C控制器管理:打开或关闭I3C控制器。 + - I3C控制器配置:获取或配置I3C控制器参数。 + - I3C消息传输:通过消息传输结构体数组进行自定义传输。 + - I3C带内中断:请求或释放带内中断。 + - I3C的物理连接如[图1](#fig1)所示: + **图 1** I3C物理连线示意图 + ![](figures/I3C物理连线示意图.png "I3C物理连线示意图") + +## 接口说明 + +**表 1** I3C驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

I3C控制器管理接口

+

I3cOpen

+
打开I3C控制器

+

I3cClose

+

关闭I3C控制器

+

I3c消息传输接口

+

I3cTransfer

+

自定义传输

+

I3C控制器配置接口

+

I3cSetConfig

+
配置I3C控制器

+

I3cGetConfig

+

获取I3C控制器配置

+

I3C带内中断接口

+

I3cRequestIbi

+
请求带内中断

+

I3cFreeIbi

+

释放带内中断

+
+ + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +I3C的使用流程如[图2](#fig2)所示。 + +**图 2** I3C使用流程图 +![](figures/I3C使用流程图.png "I3C使用流程图") + +### 打开I3C控制器 + +在进行I3C通信前,首先要调用I3cOpen打开I3C控制器。 +```c +DevHandle I3cOpen(int16_t number); +``` + +**表 2** I3cOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

number

+

I3C控制器号

+

返回值

+

返回值描述

+

NULL

+

打开I3C控制器失败

+

控制器句柄

+

打开的I3C控制器句柄

+
+ +假设系统中存在8个I3C控制器,编号从0到7,那么我们现在打开1号控制器: + +```c +DevHandle i3cHandle = NULL; /* I3C控制器句柄 / + +/* 打开I3C控制器 */ +i3cHandle = I3cOpen(1); +if (i3cHandle == NULL) { + HDF_LOGE("I3cOpen: failed\n"); + return; +} +``` + +### 进行I3C通信 + +消息传输 +```c +int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum TransMode mode); +``` + +**表 3** I3cTransfer参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器句柄

+

msgs

+

待传输数据的消息结构体数组

+

count

+

消息数组长度

+

mode

+

传输模式,0:I2C模式;1:I3C模式;2:发送CCC(Common Command Code)

+

返回值

+

返回值描述

+

正整数

+

成功传输的消息结构体数目

+

负数

+

执行失败

+
+ +I3C传输消息类型为I3cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。 + +```c +int32_t ret; +uint8_t wbuff[2] = { 0x12, 0x13 }; +uint8_t rbuff[2] = { 0 }; +struct I3cMsg msgs[2]; /* 自定义传输的消息结构体数组 */ +msgs[0].buf = wbuff; /* 写入的数据 */ +msgs[0].len = 2; /* 写入数据长度为2 */ +msgs[0].addr = 0x3F; /* 写入设备地址为0x3F */ +msgs[0].flags = 0; /* 传输标记为0,默认为写 */ +msgs[1].buf = rbuff; /* 要读取的数据 */ +msgs[1].len = 2; /* 读取数据长度为2 */ +msgs[1].addr = 0x3F; /* 读取设备地址为0x3F */ +msgs[1].flags = I3C_FLAG_READ /* I3C_FLAG_READ置位 */ +/* 进行一次I2C模式自定义传输,传输的消息个数为2 */ +ret = I3cTransfer(i3cHandle, msgs, 2, I2C_MODE); +if (ret != 2) { + HDF_LOGE("I3cTransfer: failed, ret %d\n", ret); + return; +} +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>- I3cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。 +>- 本函数不对消息结构体个数做限制,其最大个数度由具体I3C控制器决定。 +>- 本函数不对每个消息结构体中的数据长度做限制,同样由具体I3C控制器决定。 +>- 本函数可能会引起系统休眠,禁止在中断上下文调用。 + +### 获取I3C控制器配置 + +```c +int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config); +``` + +**表 4** I3cGetConfig参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器句柄

+

config

+

I3C控制器配置

+

返回值

+

返回值描述

+

0

+

获取成功

+

负数

+

获取失败

+
+ +### 配置I3C控制器 + +```c +int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config); +``` + +**表 5** I3cSetConfig参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器句柄

+

config

+

I3C控制器配置

+

返回值

+

返回值描述

+

0

+

配置成功

+

负数

+

配置失败

+
+ +### 请求IBI(带内中断) + +```c +int32_t I3cRequestIbi(DevHandle handle, uint16_t addr, I3cIbiFunc func, uint32_t payload); +``` + +**表 6** I3cRequestIbi参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器设备句柄

+

addr

+

I3C设备地址

+

func

+

IBI回调函数

+

payload

+

IBI有效载荷

+

返回值

+

返回值描述

+

0

+

请求成功

+

负数

+

请求失败

+
+ +```c +static int32_t TestI3cIbiFunc(DevHandle handle, uint16_t addr, struct I3cIbiData data) +{ + (void)handle; + (void)addr; + HDF_LOGD("%s: %.16s", __func__, (char *)data.buf); + + return 0; +} + +int32_t I3cTestRequestIbi(void) +{ + DevHandle i3cHandle = NULL; + int32_t ret; + + /* 打开I3C控制器 */ + i3cHandle = I3cOpen(1); + if (i3cHandle == NULL) { + HDF_LOGE("I3cOpen: failed\n"); + return; +} + ret = I3cRequestIbi(i3cHandle, 0x3F, TestI3cIbiFunc, 16); + if (ret != 0) { + HDF_LOGE("%s: Requset IBI failed!", __func__); + return -1; + } + + I3cClose(i3cHandle); + HDF_LOGD("%s: Done", __func__); + + return 0; +} +``` + +### 释放IBI(带内中断) + +```c +int32_t I3cFreeIbi(DevHandle handle, uint16_t addr); +``` + +**表 7** I3cFreeIbi参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器设备句柄

+

addr

+

I3C设备地址

+

返回值

+

返回值描述

+

0

+

释放成功

+

负数

+

释放失败

+
+ +```c +I3cFreeIbi(i3cHandle, 0x3F); /* 释放带内中断 */ +``` + +### 关闭I3C控制器 + +I3C通信完成之后,需要关闭I3C控制器,关闭函数如下所示: +```c +void I3cClose(DevHandle handle); +``` + +**表 4** I3cClose参数和返回值描述 + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I3C控制器设备句柄

+
+ + +```c +I3cClose(i3cHandle); /* 关闭I3C控制器 */ +``` + +## 使用实例 + +本例程以操作开发板上的I3C设备为例,详细展示I3C接口的完整使用流程。 + +由于Hi3516DV300系列SOC没有I3C控制器,本例拟在Hi3516DV300某开发板上对虚拟驱动进行简单的传输操作,基本硬件信息如下: + +- SOC:hi3516dv300。 + +- 虚拟:I3C地址为0x3f, 寄存器位宽为1字节。 + +- 原理图信息:虚拟I3C设备挂接在18号和19号I3C控制器下。 + +本例程进行简单的I3C传输,测试I3C通路是否正常。 + +示例如下: + +```c +#include "i3c_if.h" /* I3C标准接口头文件 */ +#include "i3c_ccc.h" /* I3C通用命令代码头文件 */ +#include "hdf_log.h" /* 标准日志打印头文件 */ +#include "osal_io.h" /* 标准IO读写接口头文件 */ +#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */ + +/* 定义一个表示设备的结构体,存储信息 */ +struct TestI3cDevice { + uint16_t busNum; /* I3C总线号 */ + uint16_t addr; /* I3C设备地址 */ + uint16_t regLen; /* 寄存器字节宽度 */ + DevHandle i3cHandle; /* I3C控制器句柄 */ +}; + +/* 基于I3cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */ +static int TestI3cReadWrite(struct TestI3cDevice *testDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen, uint8_t flag) +{ + int index = 0; + unsigned char regBuf[4] = {0}; + struct I3cMsg msgs[2] = {0}; + + /* 单双字节寄存器长度适配 */ + if (testDevice->regLen == 1) { + regBuf[index++] = regAddr & 0xFF; + } else { + regBuf[index++] = (regAddr >> 8) & 0xFF; + regBuf[index++] = regAddr & 0xFF; + } + + /* 填充I3cMsg消息结构 */ + msgs[0].addr = testDevice->addr; + msgs[0].flags = 0; /* 标记为0,表示写入 */ + msgs[0].len = testDevice->regLen; + msgs[0].buf = regBuf; + + msgs[1].addr = testDevice->addr; + msgs[1].flags = (flag == 1) ? I3C_FLAG_READ : 0; /* 添加读标记位,表示读取 */ + msgs[1].len = dataLen; + msgs[1].buf = regData; + + if (I3cTransfer(testDevice->i3cHandle, msgs, 2, I2C_MODE) != 2) { + HDF_LOGE("%s: i3c read err", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +/* 寄存器读函数 */ +static inline int TestI3cReadReg(struct TestI3cDevice *testDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen) +{ + return TestI3cReadWrite(testDevice, regAddr, regData, dataLen, 1); +} + +/* 寄存器写函数 */ +static inline int TestI3cWriteReg(struct TestI3cDevice *testDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen) +{ + return TestI3cReadWrite(testDevice, regAddr, regData, dataLen, 0); +} + +/* I3C例程总入口 */ +static int32_t TestCaseI3c(void) +{ + int32_t i; + int32_t ret; + unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC }; + unsigned char bufRead[7] = {0}; + static struct TestI3cDevice testDevice; + + /* 设备信息初始化 */ + testDevice.busNum = 18; + testDevice.addr = 0x3F; + testDevice.regLen = 1; + testDevice.i3cHandle = NULL; + + /* 打开I3C控制器 */ + testDevice.i3cHandle = I3cOpen(testDevice.busNum); + if (testDevice.i3cHandle == NULL) { + HDF_LOGE("%s: Open I3c:%u fail!", __func__, testDevice.busNum); + return -1; + } + + /* 向地址为0x3F的设备连续写7字节数据 */ + ret = TestI3cWriteReg(&testDevice, 0x3F, bufWrite, 7); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: test i3c write reg fail!:%d", __func__, ret); + I3cClose(testDevice.i3cHandle); + return -1; + } + OsalMSleep(10); + + /* 从地址为0x3F的设备连续读7字节数据 */ + ret = TestI3cReadReg(&testDevice, 0x3F, bufRead, 7); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: test i3c read reg fail!:%d", __func__, ret); + I3cClose(testDevice.i3cHandle); + return -1; + } + HDF_LOGI("%s: test i3c write&read reg success!", __func__); + + /* 访问完毕关闭I3C控制器 */ + I3cClose(testDevice.i3cHandle); + + return 0; +} +``` \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-i3c-develop.md b/zh-cn/device-dev/driver/driver-platform-i3c-develop.md new file mode 100755 index 0000000000000000000000000000000000000000..3f882b3b3dfd1a733da5feef13239c429ea2a41b --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-i3c-develop.md @@ -0,0 +1,410 @@ +# I3C + +- [概述](#1) +- [开发步骤](#2) +- [开发实例](#3) + +## 概述 + +I3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一种简单、低成本的双向二线制同步串行总线。在HDF框架中,I3C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I3C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I3C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 + +![image1](figures/统一服务模式结构图.png) + +## 开发步骤 + +I3C模块适配的四个环节是实例化驱动入口、配置属性文件、实例化I3C控制器对象以及注册中断处理子程序。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + + - 在device_info.hcs文件中添加deviceNode描述。 + - 【可选】添加i3c_config.hcs器件属性文件。 + +3. **实例化I3C控制器对象:** + + - 初始化I3cCntlr成员。 + - 实例化I3cCntlr成员I3cMethod方法集合,其定义和成员函数说明见下文。 + +4. **注册中断处理子程序:** + 为控制器注册中断处理程序,实现设备热接入和IBI(带内中断)功能。 + + I3cMethod定义: + ```c + struct I3cMethod { + int32_t (*sendCccCmd)(struct I3cCntlr *cntlr, struct I3cCccCmd *ccc); + int32_t (*transfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count); + int32_t (*i2cTransfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count); + int32_t (*setConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config); + int32_t (*getConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config); + int32_t (*requestIbi)(struct I3cDevice *dev); + void (*freeIbi)(struct I3cDevice *dev); + }; + ``` + + 表1 I3cMethod结构体成员的回调函数功能说明 + + |函数成员|入参|出参|返回值|功能| + |-|-|-|-|-| + |sendCccCmd|**cntlr**: 结构体指针,核心层I3C控制器;
**ccc**:传入的通用命令代码结构体指针;|**ccc**:传出的通用命令代码结构体指针;|HDF_STATUS相关状态|发送CCC(Common command Code,即通用命令代码)| + |Transfer |**cntlr**: 结构体指针,核心层I3C控制器;
**msgs**:结构体指针,用户消息 ;
**count**:int16_t,消息数量|**msgs**:结构体指针,用户消息 ;|HDF_STATUS相关状态|使用I3C模式传递用户消息| + |i2cTransfer |**cntlr**: 结构体指针,核心层I3C控制器;
**msgs**:结构体指针,用户消息 ;
**count**:int16_t,消息数量|**msgs**:结构体指针,用户消息 ;|HDF_STATUS相关状态|使用I2C模式传递用户消息| + |setConfig|**cntlr**: 结构体指针,核心层I3C控制器;
**config**: 控制器配置参数|无|HDF_STATUS相关状态|设置I3C控制器配置参数| + |getConfig|**cntlr**: 结构体指针,核心层I3C控制器;|**config**: 控制器配置参数|HDF_STATUS相关状态|获取I3C控制器配置参数| + |requestIbi|**device**: 结构体指针,核心层I3C设备;|无|HDF_STATUS相关状态|为I3C设备请求IBI(In-Bind Interrupt,即带内中断)| + |freeIbi|**device**: 结构体指针,核心层I3C设备;|无|HDF_STATUS相关状态|释放IBI| + +## 开发实例 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + I3C驱动入口参考: + + > I3C模块这种类型的控制器会出现很多个控制器挂接的情况,因而在HDF框架中首先会为这类型的控制器创建一个管理器对象,并同时对外发布一个管理器服务来统一处理外部访问。这样,用户需要打开某个控制器时,会先获取到管理器服务,然后管理器服务根据用户指定参数查找到指定控制器。 + > + > I3C管理器服务的驱动由核心层实现,**厂商不需要关注这部分内容的实现,但在实现Init函数的时候需要调用核心层的I3cCntlrAdd函数,它会实现相应功能。** + + ```c + static struct HdfDriverEntry g_virtualI3cDriverEntry = { + .moduleVersion = 1, + .Init = VirtualI3cInit, + .Release = VirtualI3cRelease, + .moduleName = "virtual_i3c_driver",//【必要且与 HCS 里面的名字匹配】 + }; + HDF_INIT(g_virtualI3cDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + + /* 核心层i3c_core.c管理器服务的驱动入口 */ + struct HdfDriverEntry g_i3cManagerEntry = { + .moduleVersion = 1, + .Init = I3cManagerInit, + .Release = I3cManagerRelease, + .moduleName = "HDF_PLATFORM_I3C_MANAGER",//这与device_info文件中device0对应 + }; + HDF_INIT(g_i3cManagerEntry); + ``` + +2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在i3c_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层I3cCntlr相关成员的默认值或限制范围有密切关系。 + + **统一服务模式**的特点是device_info文件中第一个设备节点必须为I3C管理器,其各项参数必须如下设置: + + |成员名|值| + |-|-| + |moduleName |HDF_PLATFORM_I3C_MANAGER| + |serviceName|无(预留)| + |policy|0| + |cntlrMatchAttr| 无(预留)| + + 从第二个节点开始配置具体I3C控制器信息,此节点并不表示某一路I3C控制器,而是代表一个资源性质设备,用于描述一类I3C控制器的信息。本例只有一个I3C控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在i3c_config文件中增加对应的器件属性。 + + - device_info.hcs 配置参考 + + ```c + root { + device_i3c :: device { + device0 :: deviceNode { + policy = 0; + priority = 52; + permission = 0644; + serviceName = "HDF_PLATFORM_I3C_MANAGER"; + moduleName = "HDF_PLATFORM_I3C_MANAGER"; + } + } + i3c_virtual :: deviceNode { + policy = 0; // 等于0,不需要发布服务 + priority = 56; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + moduleName = "virtual_i3c_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + serviceName = "VIRTUAL_I3C_DRIVER"; //【必要】驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "virtual_i3c"; //【必要】用于配置控制器私有数据,要与i3c_config.hcs中对应控制器保持一致 + } // 具体的控制器信息在 i3c_config.hcs 中 + } + ``` + + - i3c_config.hcs 配置参考 + + ```c + root { + platform { + i3c_config { + match_attr = "virtual_i3c"; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + template i3c_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + busId = 0; //【必要】i3c总线号 + busMode = 0x0; // 总线模式,0x0:纯净; 0x1:混合高速; 0x2:混合受限; 0x3: 混合低速; + regBasePhy = 0x120b0000; //【必要】物理基地址 + regSize = 0xd1; //【必要】寄存器位宽 + IrqNum = 20; //【必要】中断号 + i3cMaxRate = 12900000; //【可选】i3c模式最大时钟速率 + i3cRate = 12500000; //【可选】i3c模式时钟速率 + i2cFmRate = 1000000; //【可选】i2c FM模式时钟速率 + i2cFmPlusRate = 400000; //【可选】i2c FM+模式时钟速率 + } + controller_0 :: i3c_controller { + busId = 18; + IrqNum = 20; + } + } + } + } + ``` + +3. 配置属性文件完成后,要以核心层I3cCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化I3cCntlr成员I3cMethod(让用户可以通过接口来调用驱动底层函数)。 + + 此步骤需要通过实现HdfDriverEntry成员函数(Bind,Init,Release)来完成。 + + - 自定义结构体参考 + + > 从驱动的角度看,自定义结构体是参数和数据的载体,而且i3c_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层I3cCntlr对象,例如设备号、总线号等。 + + ```c + struct VirtualI3cCntlr { + struct I3cCntlr cntlr; //【必要】是核心层控制对象,具体描述见下面 + volatile unsigned char *regBase;//【必要】寄存器基地址 + uint32_t regBasePhy; //【必要】寄存器物理基地址 + uint32_t regSize; //【必要】寄存器位宽 + uint16_t busId; //【必要】设备号 + uint16_t busMode; + uint16_t IrqNum; + uint32_t i3cMaxRate; + uint32_t i3cRate; + uint32_t i2cFmRate; + uint32_t i2cFmPlusRate; + }; + + /* I3cCntlr是核心层控制器结构体,其中的成员在Init函数中被赋值 */ + struct I3cCntlr { + OsalSpinlock lock; + void *owner; + int16_t busId; + struct I3cConfig config; + uint16_t addrSlot[(I3C_ADDR_MAX + 1) / ADDRS_PER_UINT16]; + struct I3cIbiInfo *ibiSlot[I3C_IBI_MAX]; + const struct I3cMethod *ops; + const struct I3cLockMethod *lockOps; + void *priv; + }; + ``` + + > **【重要】** I3cCntlr成员回调函数结构体I3cMethod的实例化,I3cLockMethod回调函数结构体本例未实现,若要实例化,可参考I2C驱动开发,其他成员在Init函数中初始化 + + + - **init函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + > + > **返回值:** + > HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) + + |状态(值)|问题描述| + |:-|:-:| + |HDF_ERR_INVALID_OBJECT|控制器对象非法| + |HDF_ERR_INVALID_PARAM |参数非法| + |HDF_ERR_MALLOC_FAIL |内存分配失败| + |HDF_ERR_IO |I/O 错误| + |HDF_SUCCESS |传输成功| + |HDF_FAILURE |传输失败| + + > **函数说明:** + > 初始化自定义结构体对象,初始化I3cCntlr成员,调用核心层I3cCntlrAdd函数。 + + ```c + static int32_t VirtualI3cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) + { + int32_t ret; + struct VirtualI3cCntlr *virtual = NULL; //【必要】自定义结构体对象 + (void)device; + + virtual = (struct VirtualI3cCntlr *)OsalMemCalloc(sizeof(*virtual)); //【必要】内存分配 + if (virtual == NULL) { + HDF_LOGE("%s: Malloc virtual fail!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = VirtualI3cReadDrs(virtual, node); //【必要】将i3c_config文件的默认值填充到结构体中 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); + goto __ERR__; + } + ... + virtual->regBase = OsalIoRemap(virtual->regBasePhy, virtual->regSize);//【必要】地址映射 + ret = OsalRegisterIrq(hi35xx->softIrqNum, OSAL_IRQF_TRIGGER_NONE, I3cIbiHandle, "I3C", virtual); //【必要】注册中断程序 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: register irq failed!", __func__); + return ret; + } + ... + VirtualI3cCntlrInit(virtual); //【必要】I3C设备的初始化 + virtual->cntlr.priv = (void *)node; //【必要】存储设备属性 + virtual->cntlr.busId = virtual->busId; //【必要】初始化I3cCntlr成员 + virtual->cntlr.ops = &g_method; //【必要】I3cMethod的实例化对象的挂载 + (void)OsalSpinInit(&virtual->spin); + ret = I3cCntlrAdd(&virtual->cntlr); //【必要且重要】调用此函数将控制器添加至核心,返回成功信号后驱动才完全接入平台核心层 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: add i3c controller failed! ret = %d", __func__, ret); + (void)OsalSpinDestroy(&virtual->spin); + goto __ERR__; + } + + return HDF_SUCCESS; + __ERR__: //若控制器添加失败,需要执行去初始化相关函数 + if (virtual != NULL) { + OsalMemFree(virtual); + virtual = NULL; + } + + return ret; + } + + static int32_t VirtualI3cInit(struct HdfDeviceObject *device) + { + int32_t ret; + const struct DeviceResourceNode *childNode = NULL; + + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = VirtualI3cParseAndInit(device, childNode); + if (ret != HDF_SUCCESS) { + break; + } + } + + return ret; + } + ``` + + - **Release 函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 。 + > + > **返回值:** + > 无。 + > + > **函数说明:** + > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ```c + static void VirtualI3cRemoveByNode(const struct DeviceResourceNode *node) + { + int32_t ret; + int16_t busId; + struct I3cCntlr *cntlr = NULL; + struct VirtualI3cCntlr *virtual = NULL; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return; + } + + ret = drsOps->GetUint16(node, "busId", (uint16_t *)&busId, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read busId fail!", __func__); + return; + } + ... + /* 可以调用I3cCntlrGet函数通过设备的cntlrNum获取I3cCntlr对象, 以及调用I3cCntlrRemove函数来释放I3cCntlr对象的内容 */ + cntlr = I3cCntlrGet(busId); + if (cntlr != NULL && cntlr->priv == node) { + I3cCntlrPut(cntlr); + I3cCntlrRemove(cntlr); //【必要】主要是从管理器驱动那边移除I3cCntlr对象 + virtual = (struct VirtualI3cCntlr *)cntlr;//【必要】通过强制转换获取自定义的对象并进行release操作 + (void)OsalSpinDestroy(&virtual->spin); + OsalMemFree(virtual); + } + return; + } + + static void VirtualI3cRelease(struct HdfDeviceObject *device) + { + const struct DeviceResourceNode *childNode = NULL; + + HDF_LOGI("%s: enter", __func__); + + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return; + } + ... + //遍历、解析i3c_config.hcs中的所有配置节点,并分别进行release操作 + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + VirtualI3cRemoveByNode(childNode); //函数定义如上 + } + } + ``` + +4. 最后一步,实现中断处理程序,在中断处理程序中通过判断中断产生的地址,实现热接入、IBI等操作。 + + ```c + static int32_t VirtualI3cReservedAddrWorker(struct VirtualI3cCntlr *virtual, uint16_t addr) + { + (void)virtual; + switch (addr) { + case I3C_HOT_JOIN_ADDR: + VirtualI3cHotJoin(virtual); + break; + case I3C_RESERVED_ADDR_7H3E: + case I3C_RESERVED_ADDR_7H5E: + case I3C_RESERVED_ADDR_7H6E: + case I3C_RESERVED_ADDR_7H76: + case I3C_RESERVED_ADDR_7H7A: + case I3C_RESERVED_ADDR_7H7C: + case I3C_RESERVED_ADDR_7H7F: + /* 广播地址单比特错误的所有情形 */ + HDF_LOGW("%s: broadcast Address single bit error!", __func__); + break; + default: + HDF_LOGD("%s: Reserved address which is not supported!", __func__); + break; + } + + return HDF_SUCCESS; + } + ``` + + ```c + static int32_t I3cIbiHandle(uint32_t irq, void *data) + { + struct VirtualI3cCntlr *virtual = NULL; + struct I3cDevice *device = NULL; + uint16_t ibiAddr; + char *testStr = "Hello I3C!"; + + (void)irq; + if (data == NULL) { + HDF_LOGW("%s: data is NULL!", __func__); + return HDF_ERR_INVALID_PARAM; + } + virtual = (struct VirtualI3cCntlr *)data; + /* 【必要】获取产生中断的地址,使用CHECK_RESERVED_ADDR宏判断该地址是否为I3C保留地址 */ + ibiAddr = VirtualI3cGetIbiAddr(); + if (CHECK_RESERVED_ADDR(ibiAddr) == I3C_ADDR_RESERVED) { + HDF_LOGD("%s: Calling VirtualI3cResAddrWorker...", __func__); + return VirtualI3cReservedAddrWorker(virtual, ibiAddr); + } else { + HDF_LOGD("%s: Calling I3cCntlrIbiCallback...", __func__); + device = GetDeviceByAddr(&virtual->cntlr, ibiAddr); + if (device == NULL) { + HDF_LOGE("func:%s device is NULL!",__func__); + return HDF_ERR_MALLOC_FAIL; + } + if (device->ibi->payload > VIRTUAL_I3C_TEST_STR_LEN) { + /* 将字符串"Hello I3C!"放入IBI缓冲区内 */ + *device->ibi->data = *testStr; + } + /* 根据产生IBI的I3C设备调用IBI回调函数 */ + return I3cCntlrIbiCallback(device); + } + + return HDF_SUCCESS; + } + ``` \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md b/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md index 2ce904f2f90c1c3944117b23a5fb3c18e0ade00d..00a64732b8580be625ace6e71cc08fbcf3b3f198 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md @@ -6,10 +6,10 @@ ## 概述 -CSI(Camera Serial Interface)是由MIPI联盟下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 无服务模式结构图 -![image1](figures/CSI无服务模式结构图.png) +![image1](figures/无服务模式结构图.png) ## 开发步骤 diff --git a/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md b/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md index 8bf3895f465ff6d2da893f246b11b140fc5d4f49..49d492ba8b5ff283573d7446abe0eaaea88e9f20 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md @@ -10,7 +10,7 @@ DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范。在HDF框架中,MIPI-DSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 **图 1** DSI无服务模式结构图 -![](figures/DSI无服务模式结构图.png "DSI无服务模式结构图") +![](figures/无服务模式结构图.png "DSI无服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-mmc-develop.md b/zh-cn/device-dev/driver/driver-platform-mmc-develop.md index b8e0219717ffd428bad3623de5cafc7b17b5b95a..80dea26f8728f8ed7bad062451d1b2aa3c88fdff 100755 --- a/zh-cn/device-dev/driver/driver-platform-mmc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mmc-develop.md @@ -10,7 +10,7 @@ MMC(MultiMedia Card),即多媒体卡,在HDF框架中,MMC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图 1** MMC独立服务模式结构图 -![](figures/MMC独立服务模式结构图.png "MMC独立服务模式结构图") +![](figures/独立服务模式结构图.png "MMC独立服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-pwm-develop.md b/zh-cn/device-dev/driver/driver-platform-pwm-develop.md index 123d12aee05a96359f76da4a2cd2f0691ae9b8df..9d927033fa4f97c645c552bd7306a7542a0571f0 100755 --- a/zh-cn/device-dev/driver/driver-platform-pwm-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-pwm-develop.md @@ -10,7 +10,7 @@ PWM(Pulse Width Modulator)即脉冲宽度调节器,在HDF框架中,PWM的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图 1** PWM独立服务模式结构图 -![](figures/PWM独立服务模式结构图.png "PWM独立服务模式结构图") +![](figures/独立服务模式结构图.png "PWM独立服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-rtc-develop.md b/zh-cn/device-dev/driver/driver-platform-rtc-develop.md index 6a72063974617e607f0f69dd8fdf7888e434bf4c..8b5023bf9f92bcf28d5ae4ae84d7d6bad572c2b9 100755 --- a/zh-cn/device-dev/driver/driver-platform-rtc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-rtc-develop.md @@ -10,7 +10,7 @@ RTC\(real-time clock\)为操作系统中的实时时钟设备,在HDF框架中,RTC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图 1** RTC独立服务模式结构图 -![](figures/RTC独立服务模式结构图.png "RTC独立服务模式结构图") +![](figures/独立服务模式结构图.png "RTC独立服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-sdio-develop.md b/zh-cn/device-dev/driver/driver-platform-sdio-develop.md index 1c59197f4862db914d4f55c82cbee223f47783eb..bfc2d147b1baf29aada5dc6c359a942587726ddc 100755 --- a/zh-cn/device-dev/driver/driver-platform-sdio-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-sdio-develop.md @@ -7,10 +7,10 @@ ## 概述 -SDIO由SD卡发展而来,被统称为mmc(MultiMediaCard),相关技术差别不大,在HDF框架中,SDIO的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 +SDIO由SD卡发展而来,被统称为MMC(MultiMediaCard),相关技术差别不大,在HDF框架中,SDIO的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图 1** SDIO独立服务模式结构图 -![](figures/SDIO独立服务模式结构图.png "SDIO独立服务模式结构图") +![](figures/独立服务模式结构图.png "SDIO独立服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-spi-develop.md b/zh-cn/device-dev/driver/driver-platform-spi-develop.md index 30865e6ae085c5825530053318f69bde8ab8cab4..7445a2c54e14fd5fbf144996fc9c89d4fc955b79 100755 --- a/zh-cn/device-dev/driver/driver-platform-spi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-spi-develop.md @@ -7,10 +7,10 @@ ## 概述 -SPI是串行外设接口(Serial Peripheral Interface)的缩写,在HDF框架中,SPI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 +SPI即串行外设接口(Serial Peripheral Interface),在HDF框架中,SPI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图 1** SPI独立服务模式结构图 -![](figures/SPI独立服务模式结构图.png "SPI独立服务模式结构图") +![](figures/独立服务模式结构图.png "SPI独立服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-uart-develop.md b/zh-cn/device-dev/driver/driver-platform-uart-develop.md index 03aca8344b3dfa0be34f75bfc1242c713687d23c..b0c410be520e08c8f7551afbb25d54de9c1b229a 100755 --- a/zh-cn/device-dev/driver/driver-platform-uart-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-uart-develop.md @@ -10,7 +10,7 @@ UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,在HDF框架中,UART的接口适配模式采用独立服务模式。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图 1** UART独立服务模式结构图 -![](figures/UART独立服务模式结构图.png "UART独立服务模式结构图") +![](figures/独立服务模式结构图.png "UART独立服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform-watchdog-develop.md b/zh-cn/device-dev/driver/driver-platform-watchdog-develop.md index dbfcba6136a653dfa85e047b05555d4f75601793..eda28043c4ffac4aedf14ba132895ca9bee13b90 100755 --- a/zh-cn/device-dev/driver/driver-platform-watchdog-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-watchdog-develop.md @@ -10,7 +10,7 @@ 看门狗(Watchdog),又叫看门狗计时器(Watchdog timer),是一种硬件的计时设备,在HDF框架中,Watchdog接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 **图 1** Watchdog独立服务模式结构图 -![](figures/Watchdog独立服务模式结构图.png "Watchdog独立服务模式结构图") +![](figures/独立服务模式结构图.png "Watchdog独立服务模式结构图") ## 接口说明 diff --git a/zh-cn/device-dev/driver/driver-platform.md b/zh-cn/device-dev/driver/driver-platform.md index 017b58ac18c54d64ed5cf536984ce2dd5ae10dc5..01fc51f6cd1717787c769e2c1f1f79bc7b67d2d3 100644 --- a/zh-cn/device-dev/driver/driver-platform.md +++ b/zh-cn/device-dev/driver/driver-platform.md @@ -1,9 +1,21 @@ # 平台驱动使用 +- **[ADC](driver-platform-adc-des.md)** + - **[GPIO](driver-platform-gpio-des.md)** +- **[HDMI](driver-platform-hdmi-des.md)** + - **[I2C](driver-platform-i2c-des.md)** +- **[I3C](driver-platform-i3c-des.md)** + +- **[MIPI-CSI](driver-platform-mipicsi-des.md)** + +- **[MIPI-DSI](driver-platform-mipidsi-des.md)** + +- **[PWM](driver-platform-pwm-des.md)** + - **[RTC](driver-platform-rtc-des.md)** - **[SDIO](driver-platform-sdio-des.md)** @@ -13,9 +25,3 @@ - **[UART](driver-platform-uart-des.md)** - **[WATCHDOG](driver-platform-watchdog-des.md)** - -- **[MIPI DSI](driver-platform-mipidsi-des.md)** - -- **[PWM](driver-platform-pwm-des.md)** - - diff --git "a/zh-cn/device-dev/driver/figures/ADC\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/ADC\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..9b140042ffdfff77a76cc69814a0217af2ddc5df Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/ADC\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/ADC\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/driver/figures/ADC\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..da94f3b486edb6b269ef341b12b1816f23036c32 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/ADC\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/DSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/DSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100755 index 833ff6cc89e49ed4210dd68a502e4b304ac1c273..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/DSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/GPIO\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/GPIO\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 833ff6cc89e49ed4210dd68a502e4b304ac1c273..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/GPIO\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/HDMI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/HDMI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..fa578f83d99f47e868312dad99d6b38fa960e794 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/HDMI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/HDMI\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/driver/figures/HDMI\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..9c1618562e33dd6fd08d2ec7f48454a43c1e1541 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/HDMI\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/I2C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I2C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 838f9a4416d901eb29b5d203b559b3dcfe29fed9..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/I2C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..40c7088de596e771921861c727d4813f686eda40 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/I3C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I3C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..08942f92cdc1c9fa6c0442537525cfcba90254a7 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/I3C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/PWM\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/PWM\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 23324872566e5affac8baa186a30b64b3257f673..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/PWM\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/RTC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/RTC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 23324872566e5affac8baa186a30b64b3257f673..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/RTC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/SDIO\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/SDIO\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 23324872566e5affac8baa186a30b64b3257f673..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/SDIO\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/SPI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/SPI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 23324872566e5affac8baa186a30b64b3257f673..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/SPI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/UART\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/UART\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 23324872566e5affac8baa186a30b64b3257f673..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/UART\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/Watchdog\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/Watchdog\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 23324872566e5affac8baa186a30b64b3257f673..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figures/Watchdog\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figures/CSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/driver/figures/CSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/driver/figures/\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/MMC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/driver/figures/MMC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/driver/figures/\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/ADC\347\273\237\344\270\200\346\234\215\345\212\241.png" "b/zh-cn/device-dev/driver/figures/\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/driver/figures/ADC\347\273\237\344\270\200\346\234\215\345\212\241.png" rename to "zh-cn/device-dev/driver/figures/\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png"