提交 eeb2ff76 编写于 作者: Y yafeng_wang

docs: Document rectification

Signed-off-by: Nyafeng_wang <wangyafeng15@huawei.com>
上级 91832e5b
......@@ -4,65 +4,61 @@
### 功能简介<a name="section2"></a>
ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备。
ADC(Analog to Digital Converter),即模拟-数字转换器,可将模拟信号转换成对应的数字信号,便于存储与计算等操作。除电源线和地线之外,ADC只需要1根线与被测量的设备进行连接,其物理连线如图1:
**图 1** ADC物理连线示意图<a name="fig1"></a>
![](figures/ADC物理连线示意图.png "ADC物理连线示意图")
ADC接口定义了完成AD转换的通用方法集合,包括:
ADC接口定义了完成ADC传输的通用方法集合,包括:
- ADC设备管理:打开或关闭ADC设备。
- ADC读取转换结果:读取AD转换结果。
### 基本概念<a name="section3"></a>
ADC主要用于将模拟量转换成数字量,从而便于存储与计算等。
ADC的主要技术参数有:
- 分辨率
分辨率指的是ADC模块能够转换的二进制位数,位数越多分辨率越高。
- 转换误差
转换误差通常是以输出误差的最大值形式给出。它表示A/D转换器实际输出的数字量和理论上的输出数字量之间的差别。常用最低有效位的倍数表示。
- 转换时间
转换时间是指A/D转换器从转换控制信号到来开始,到输出端得到稳定的数字信号所经过的时间。
### 运作机制<a name="section4"></a>
在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),如果采用独立服务模式则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。ADC模块接口适配模式采用统一服务模式。
ADC模块各分层的作用为:接口层提供打开设备,写入数据,关闭设备的接口。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其他具体的功能。
除电源线和地线之外,ADC只需要1根线与被测量的设备进行连接,其物理连线如[图1](#fig1)所示:
**图 1** ADC物理连线示意图<a name="fig1"></a>
![](figures/ADC物理连线示意图.png "ADC物理连线示意图")
### 约束与限制<a name="section5"></a>
ADC模块当前仅支持轻量和小型系统内核(LiteOS)
ADC模块仅支持轮询方式读取数据
## 使用指导<a name="section6"></a>
### 场景介绍<a name="section7"></a>
ADC设备通常用于将模拟电压转换为数字量,如与咪头搭配进行声音采集、与NTC电阻搭配进行温度测量,或者将其他模拟传感器的输出量转换为数字量的场景。
ADC设备通常用于将模拟电压或电流转换为数字量,例如与NTC电阻搭配进行温度测量,或者将其他模拟传感器的输出量转换为数字量的场景。
### 接口说明<a name="section8"></a>
ADC模块提供的主要接口如[表1](#table1)所示,更多关于接口的介绍请参考对应的API接口文档
ADC模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/adc_if.h
**表 1** ADC驱动API接口功能介绍
<a name="table1"></a>
| 接口名 | 描述 |
| 接口名 | 接口描述 |
| -------- | ---------------- |
| AdcOpen | 打开ADC设备 |
| AdcClose | 关闭ADC设备 |
| AdcRead | 读取AD转换结果值 |
| DevHandle AdcOpen(uint32_t number) | 打开ADC设备 |
| void AdcClose(DevHandle handle) | 关闭ADC设备 |
| int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t \*val) | 读取AD转换结果值 |
### 开发步骤<a name="section9"></a>
使用ADC设备的一般流程如[图2](#fig2)所示。
使用ADC设备的一般流程如图2所示。
**图 2** ADC使用流程图<a name="fig2"></a>
![](figures/ADC使用流程图.png "ADC使用流程图")
......@@ -156,13 +152,11 @@ AdcClose(adcHandle); /* 关闭ADC设备 */
### 使用实例<a name="section10"></a>
本例程以操作开发板上的ADC设备为例,详细展示ADC接口的完整使用流程。
本例拟对Hi3516DV300某开发板上ADC设备进行简单的读取操作,基本硬件信息如下:
本例拟对Hi3516DV300开发板上ADC设备进行简单的读取操作,基本硬件信息如下:
- SOC:hi3516dv300。
- 原理图信息:电位器挂接在0号ADC设备1通道下。
- 硬件连接:电位器挂接在0号ADC设备1通道下。
本例程对测试ADC进行连续读取操作,测试ADC功能是否正常。
......@@ -173,16 +167,17 @@ AdcClose(adcHandle); /* 关闭ADC设备 */
#include "hdf_log.h" /* 标准日志打印头文件 */
/* 设备号0,通道号1 */
#define ADC_DEVICE_NUM 0
#define ADC_DEVICE_NUM 0
#define ADC_CHANNEL_NUM 1
#define ADC_TEST_NUM 30
/* ADC例程总入口 */
static int32_t TestCaseAdc(void)
{
int32_t i;
int32_t ret;
DevHandle adcHandle;
uint32_t readBuf[30] = {0};
DevHandle adcHandle = NULL;
uint32_t readBuf[ADC_TEST_NUM] = {0};
/* 打开ADC设备 */
adcHandle = AdcOpen(ADC_DEVICE_NUM);
......@@ -192,7 +187,7 @@ static int32_t TestCaseAdc(void)
}
/* 连续进行30次AD转换并读取转换结果 */
for (i = 0; i < 30; i++) {
for (i = 0; i < ADC_TEST_NUM; i++) {
ret = AdcRead(adcHandle, ADC_CHANNEL_NUM, &readBuf[i]);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: ADC read fail!:%d", __func__, ret);
......
......@@ -4,7 +4,10 @@
### 功能简介
DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备。
DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备,主要用于:
- 作为过程控制计算机系统的输出通道,与执行器相连,实现对生产过程的自动控制。
- 在利用反馈技术的模数转换器设计中,作为重要的功能模块呈现。
DAC接口定义了完成DAC传输的通用方法集合,包括:
- DAC设备管理:打开或关闭DAC设备。
......@@ -12,11 +15,6 @@ DAC接口定义了完成DAC传输的通用方法集合,包括:
### 基本概念
DAC模块支持数模转换的开发,它主要用于:
1. 作为过程控制计算机系统的输出通道,与执行器相连,实现对生产过程的自动控制。
2. 在利用反馈技术的模数转换器设计中,作为重要的功能模块呈现。
- 分辨率
分辨率指的是DAC模块能够转换的二进制位数,位数越多分辨率越高。
......@@ -35,7 +33,7 @@ DAC模块支持数模转换的开发,它主要用于:
### 运作机制
在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),如果采用独立服务模式,则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。DAC模块接口适配模式采用统一服务模式,如图1所示。
在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),如果采用独立服务模式,则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。DAC模块接口适配模式采用统一服务模式(如图1)。
DAC模块各分层的作用为:接口层提供打开设备、写入数据和关闭设备的接口。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其它具体的功能。
......@@ -47,7 +45,7 @@ DAC模块各分层的作用为:接口层提供打开设备、写入数据和
### 约束与限制
DAC模块当前仅支持轻量和小型系统内核(LiteOS)。
DAC模块当前仅支持轻量和小型系统内核(LiteOS-A)。
## 使用指导
......@@ -57,11 +55,11 @@ DAC模块的主要工作是以电流、电压或电荷的形式将数字信号
### 接口说明
DAC模块提供的主要接口如下所示,更多关于接口的介绍请参考对应的API接口文档
DAC模块提供的主要接口如下所示,具体API详见//drivers/hdf_core/framework/include/platform/dac_if.h
**表 1** DAC驱动API接口功能介绍
| 接口名 | 描述 |
| 接口名 | 接口描述 |
| ------------------------------------------------------------------ | ------------ |
| DevHandle DacOpen(uint32_t number) | 打开DAC设备。 |
| void DacClose(DevHandle handle) | 关闭DAC设备。 |
......@@ -94,7 +92,7 @@ DevHandle DacOpen(uint32_t number);
假设系统中存在2个DAC设备,编号从0到1,现在打开1号设备。
```c++
DevHandle dacHandle = NULL; /* DAC设备句柄 /
DevHandle dacHandle = NULL; // DAC设备句柄
/* 打开DAC设备 */
dacHandle = DacOpen(1);
......@@ -123,12 +121,12 @@ int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val);
```c++
/* 通过DAC_CHANNEL_NUM设备通道写入目标val值 */
ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret);
DacClose(dacHandle);
return -1;
}
ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret);
DacClose(dacHandle);
return -1;
}
```
#### 关闭DAC设备
......
......@@ -3,9 +3,13 @@
## 概述
I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。
### 功能简介
I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA(SerialData)串行数据线以及SCL(SerialClock)串行时钟线两根线相连,如图1所示。
I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。由于其硬件连接简单、成本低廉,因此被广泛应用于各种短距离通信的场景。
### 运作机制
I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA(SerialData)串行数据线以及SCL(SerialClock)串行时钟线两根线相连(如图1)。
I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。
......@@ -19,37 +23,40 @@ I2C接口定义了完成I2C传输的通用方法集合,包括:
![image](figures/I2C物理连线示意图.png "I2C物理连线示意图")
## 使用指导
## 接口说明
### 场景介绍
**表1** I2C驱动API接口功能介绍
I2C通常用于与各类支持I2C协议的传感器、执行器或输入输出设备进行通信。
| 功能分类 | 接口描述 |
| -------- | -------- |
| I2C控制器管理接口 | -&nbsp;I2cOpen:打开I2C控制器<br/>-&nbsp;I2cClose:关闭I2C控制器 |
| I2C消息传输接口 | I2cTransfer:自定义传输 |
### 接口说明
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**<br>
> 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
I2C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/i2c_if.h。
**表1** I2C驱动API接口功能介绍
## 使用指导
| 接口名 | 接口描述 |
| -------- | -------- |
| DevHandle I2cOpen(int16_t number) | 打开I2C控制器 |
| void I2cClose(DevHandle handle) | 关闭I2C控制器 |
| int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count) | 自定义传输 |
### 使用流程
使用I2C设备的一般流程如下图所示。
**图2** I2C设备使用流程图
**图2** I2C设备使用流程图
![image](figures/I2C设备使用流程图.png "I2C设备使用流程图")
![image](figures/I2C设备使用流程图.png "I2C设备使用流程图")
### 打开I2C控制器
#### 打开I2C控制器
在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。
```c
DevHandle I2cOpen(int16_t number);
```
**表2** I2cOpen参数和返回值描述
......@@ -62,8 +69,7 @@ DevHandle I2cOpen(int16_t number);
假设系统中存在8个I2C控制器,编号从0到7,以下代码示例为获取3号控制器:
```
```c
DevHandle i2cHandle = NULL; /* I2C控制器句柄 /
/* 打开I2C控制器 */
......@@ -75,11 +81,13 @@ if (i2cHandle == NULL) {
```
### 进行I2C通信
#### 进行I2C通信
消息传输
```c
int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count);
```
**表3** I2cTransfer参数和返回值描述
......@@ -92,10 +100,10 @@ int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count);
| 正整数 | 成功传输的消息结构体数目 |
| 负数 | 执行失败 |
I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。
I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。组合读写示例:
```
```c
int32_t ret;
uint8_t wbuff[2] = { 0x12, 0x13 };
uint8_t rbuff[2] = { 0 };
......@@ -126,11 +134,13 @@ if (ret != 2) {
> - 本函数可能会引起系统休眠,不允许在中断上下文调用
### 关闭I2C控制器
#### 关闭I2C控制器
I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所述:
```c
void I2cClose(DevHandle handle);
```
**表4** I2cClose参数和返回值描述
......@@ -138,23 +148,24 @@ void I2cClose(DevHandle handle);
| -------- | -------- |
| handle | I2C控制器设备句柄 |
关闭I2C控制器示例:
```
```c
I2cClose(i2cHandle); /* 关闭I2C控制器 */
```
## 使用示例
### 使用示例
本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。
本例拟对Hi3516DV300开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下:
本例拟对Hi3516DV300开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下:
- SOC:hi3516dv300。
- Touch IC:I2C地址为0x38, IC内部寄存器位宽为1字节。
- Touch IC:I2C地址为0x38IC内部寄存器位宽为1字节。
- 原理图信息:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO。
- 硬件连接:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO。
本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。
......@@ -163,8 +174,7 @@ I2cClose(i2cHandle); /* 关闭I2C控制器 */
示例如下:
```
```c
#include "i2c_if.h" /* I2C标准接口头文件 */
#include "gpio_if.h" /* GPIO标准接口头文件 */
#include "hdf_log.h" /* 标准日志打印头文件 */
......
......@@ -35,7 +35,7 @@ I3C接口定义了完成I3C传输的通用方法集合,包括:
### 运作机制<a name="section4"></a>
在HDF框架中,I3C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I3C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I3C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。
在HDF框架中,I3C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I3C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I3C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。
相比于I2C,I3C总线拥有更高的速度、更低的功耗,支持带内中断、从设备热接入以及切换当前主设备,同时向后兼容I2C从设备。一路I3C总线上,可以连接多个设备,这些设备可以是I2C从设备、I3C从设备和I3C次级主设备,但只能同时存在一个主设备,一般为控制器本身。
......@@ -44,38 +44,41 @@ I3C接口定义了完成I3C传输的通用方法集合,包括:
### 约束与限制<a name="section5"></a>
I3C模块当前仅支持轻量和小型系统内核(LiteOS
I3C模块当前仅支持轻量和小型系统内核(LiteOS-A),不支持在用户态使用
## 使用指导<a name="section6"></a>
### 场景介绍<a name="section7"></a>
I3C可连接单个或多个I3C、I2C从器件,它主要用于:
1. 与传感器通信,如陀螺仪、气压计或支持I3C协议的图像传感器等;
2. 通过软件或硬件协议转换,与其他接口(如 UART 串口等)的设备进行通信。
- 与传感器通信,如陀螺仪、气压计或支持I3C协议的图像传感器等;
- 通过软件或硬件协议转换,与其他接口(如 UART 串口等)的设备进行通信。
### 接口说明<a name="section8"></a>
I3C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/i3c_if.h。
**表 1** I3C驱动API接口功能介绍
<a name="table1"></a>
| 接口名 | 描述 |
| 接口名 | 接口描述 |
| ------------- | ----------------- |
| I3cOpen | 打开I3C控制器 |
| I3cClose | 关闭I3C控制器 |
| I3cTransfer | 自定义传输 |
| I3cSetConfig | 配置I3C控制器 |
| I3cGetConfig | 获取I3C控制器配置 |
| I3cRequestIbi | 请求带内中断 |
| I3cFreeIbi | 释放带内中断 |
| DevHandle I3cOpen(int16_t number) | 打开I3C控制器 |
| void I3cClose(DevHandle handle) | 关闭I3C控制器 |
| int32_t I3cTransfer(DevHandle handle, struct I3cMsg \*msg, int16_t count, enum TransMode mode) | 自定义传输 |
| int32_t I3cSetConfig(DevHandle handle, struct I3cConfig \*config) | 配置I3C控制器 |
| int32_t I3cGetConfig(DevHandle handle, struct I3cConfig \*config) | 获取I3C控制器配置 |
| int32_t I3cRequestIbi(DevHandle handle, uint16_t addr, I3cIbiFunc func, uint32_t payload) | 请求带内中断 |
| int32_t I3cFreeIbi(DevHandle handle, uint16_t addr) | 释放带内中断 |
>![](../public_sys-resources/icon-note.gif) **说明:**<br>
>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
### 开发步骤<a name="section9"></a>
I3C的使用流程如[图2](#fig2)所示。
I3C的使用流程如图2所示。
**图 2** I3C使用流程图<a name="fig2"></a>
![](figures/I3C使用流程图.png "I3C使用流程图")
......@@ -111,65 +114,15 @@ if (i3cHandle == NULL) {
}
```
#### 进行I3C通信<a name="section6"></a>
消息传输
```c
int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum TransMode mode);
```
**表 3** I3cTransfer参数和返回值描述
<a name="table3"></a>
| 参数 | 参数描述 |
| ---------- | -------------------------------------------- |
| handle | I3C控制器句柄 |
| msgs | 待传输数据的消息结构体数组 |
| count | 消息数组长度 |
| mode | 传输模式,0:I2C模式;1:I3C模式;2:发送CCC |
| **返回值** | **返回值描述** |
| 正整数 | 成功传输的消息结构体数目 |
| 负数 | 执行失败 |
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控制器配置<a name="section7"></a>
```c
int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config);
```
**表 4** I3cGetConfig参数和返回值描述
**表 3** I3cGetConfig参数和返回值描述
<a name="table4"></a>
<a name="table3"></a>
| 参数 | 参数描述 |
| ---------- | -------------- |
......@@ -197,9 +150,9 @@ if (ret != HDF_SUCCESS) {
int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config);
```
**表 5** I3cSetConfig参数和返回值描述
**表 4** I3cSetConfig参数和返回值描述
<a name="table5"></a>
<a name="table4"></a>
| 参数 | 参数描述 |
| ---------- | -------------- |
......@@ -223,6 +176,56 @@ if (ret != HDF_SUCCESS) {
}
```
#### 进行I3C通信<a name="section6"></a>
消息传输
```c
int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum TransMode mode);
```
**表 5** I3cTransfer参数和返回值描述
<a name="table5"></a>
| 参数 | 参数描述 |
| ---------- | -------------------------------------------- |
| handle | I3C控制器句柄 |
| msgs | 待传输数据的消息结构体数组 |
| count | 消息数组长度 |
| mode | 传输模式,0:I2C模式;1:I3C模式;2:发送CCC |
| **返回值** | **返回值描述** |
| 正整数 | 成功传输的消息结构体数目 |
| 负数 | 执行失败 |
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控制器决定。
>- 本函数可能会引起系统休眠,禁止在中断上下文调用。
#### 请求IBI(带内中断)<a name="section9"></a>
```c
......@@ -310,9 +313,9 @@ I3C通信完成之后,需要关闭I3C控制器,关闭函数如下所示:
void I3cClose(DevHandle handle);
```
**表 4** I3cClose参数和返回值描述
**表 8** I3cClose参数和返回值描述
<a name="table4"></a>
<a name="table8"></a>
| 参数 | 参数描述 |
| ---------- | -------------- |
......@@ -326,15 +329,13 @@ I3cClose(i3cHandle); /* 关闭I3C控制器 */
## 使用实例<a name="section10"></a>
本例程以操作开发板上的I3C设备为例,详细展示I3C接口的完整使用流程。
由于Hi3516DV300系列SOC没有I3C控制器,本例拟在Hi3516DV300某开发板上对虚拟驱动进行简单的传输操作,基本硬件信息如下:
本例程以操作Hi3516DV300开发板上的I3C虚拟设备为例,详细展示I3C接口的完整使用流程,基本硬件信息如下。
- SOC:hi3516dv300。
- 虚拟:I3C地址为0x3f, 寄存器位宽为1字节。
- 虚拟I3C设备:I3C地址为0x3f, 寄存器位宽为1字节。
- 原理图信息:虚拟I3C设备挂接在18号和19号I3C控制器下。
- 硬件连接:虚拟I3C设备挂接在18号和19号I3C控制器下。
本例程进行简单的I3C传输,测试I3C通路是否正常。
......
......@@ -6,7 +6,7 @@
I3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一种简单、低成本的双向二线制同步串行总线。
I3C是两线双向串行总线,针对多个传感器从设备进行了优化,并且一次只能由一个I3C主设备控制。 相比于I2C,I3C总线拥有更高的速度、更低的功耗,支持带内中断、从设备热接入以及切换当前主设备,同时向后兼容I2C从设备。
I3C是两线双向串行总线,针对多个传感器从设备进行了优化,并且一次只能由一个I3C主设备控制。相比于I2C,I3C总线拥有更高的速度、更低的功耗,支持带内中断、从设备热接入以及切换当前主设备,同时向后兼容I2C从设备。I3C增加了带内中断(In-Bind Interrupt)功能,支持I3C设备进行热接入操作,弥补了I2C总线需要额外增加中断线来完成中断的不足。I3C总线上允许同时存在I2C设备、I3C从设备和I3C次级主设备。
### 基本概念<a name="3"></a>
......@@ -16,11 +16,11 @@ I3C是两线双向串行总线,针对多个传感器从设备进行了优化
- DAA(Dynamic Address Assignment):动态地址分配。
I3C支持对从设备地址进行动态分配从而避免地址冲突。在分配动态地址之前,连接到I3C总线上的每个I3C设备都应以两种方式之一来唯一标识:
I3C支持对从设备地址进行动态分配从而避免地址冲突。在分配动态地址之前,连接到I3C总线上的每个I3C/I2C设备都应以两种方式之一来唯一标识:
- 设备可能有一个符合I2C规范的静态地址,主机可以使用此静态地址。
- 在任何情况下,设备均应具有48位的临时ID。除非设备具有静态地址且主机使用静态地址,否则主机应使用此48位临时ID。
- 在任何情况下,I3C设备均应具有48位的临时ID。除非设备具有静态地址且主机使用静态地址,否则主机应使用此48位临时ID。
- CCC(Common Command Code):通用命令代码。
......@@ -37,31 +37,39 @@ I3C是两线双向串行总线,针对多个传感器从设备进行了优化
### 运作机制<a name="4"></a>
在HDF框架中,同类型控制器对象较多时(可能同时存在十几个同类型控制器),如果采用独立服务模式则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。I3C模块接口适配模式采用统一服务模式(如图1所示)。
在HDF框架中,同类型控制器对象较多时(可能同时存在十几个同类型控制器),如果采用独立服务模式则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。I3C模块采用统一服务模式(如图1)。
I3C模块各分层的作用为:
- 接口层提供打开控制器、传输消息、获取和设置控制器参数以及关闭控制器的接口。
- 核心层主要提供绑定设备、初始化设备以及释放设备的能力。
- 适配层实现其他具体的功能。
**图 1** I3C统一服务模式<a name="fig1"></a>
- 接口层:提供打开设备,写入数据,关闭设备的能力。
- 核心层:主要负责服务绑定、初始化以及释放管理器,并提供添加、删除以及获取控制器的能力。由于框架需要统一管理I3C总线上挂载的所有设备,因此还提供了添加、删除以及获取设备的能力,以及中断回调函数。
- 适配层:由驱动适配者实现与硬件相关的具体功能,如控制器的初始化等。
在统一模式下,所有的控制器都被核心层统一管理,并由核心层统一发布一个服务供接口层,因此这种模式下驱动无需再为每个控制器发布服务。
**图 1** I3C统一服务模式结构图<a name="fig1"></a>
![image1](figures/统一服务模式结构图.png)
### 约束与限制<a name="5"></a>
I3C模块当前仅支持轻量和小型系统内核(LiteOS) 。
I3C模块当前仅支持轻量和小型系统内核(LiteOS-A) 。
## 开发指导 <a name="6"></a>
### 场景介绍 <a name="7"></a>
I3C可连接单个或多个I3C、I2C从器件,它主要用于:
- 与传感器通信,如陀螺仪、气压计或支持I3C协议的图像传感器等。
- 通过软件或硬件协议转换,与其他通信接口(如UART串口等)的设备进行通信。
当驱动开发者需要将I3C设备适配到OpenHarmony时,需要进行I3C驱动适配,下文将介绍如何进行I3C驱动适配。
### 接口说明 <a name="8"></a>
为了保证上层在调用I3C接口时能够正确的操作硬件,核心层在//drivers/hdf_core/framework/support/platform/include/i3c/i3c_core.h中定义了以下钩子函数。驱动适配者需要在适配层实现这些函数的具体功能,并与这些钩子函数挂接,从而完成接口层与核心层的交互。
I3cMethod定义:
```c
struct I3cMethod {
......@@ -75,7 +83,7 @@ struct I3cMethod {
};
```
**表1** I3cMethod结构体成员的回调函数功能说明
**表1** I3cMethod结构体成员的钩子函数功能说明
|函数成员|入参|出参|返回值|功能|
|-|-|-|-|-|
|sendCccCmd| **cntlr**:结构体指针,核心层I3C控制器<br />**ccc**:传入的通用命令代码结构体指针 | **ccc**:传出的通用命令代码结构体指针 | HDF_STATUS相关状态|发送CCC(Common command Code,即通用命令代码)|
......@@ -98,54 +106,53 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
- 在device_info.hcs文件中添加deviceNode描述。
- 【可选】添加i3c_config.hcs器件属性文件。
- 实例化I3C控制器对象:
- 初始化I3cCntlr成员。
- 实例化I3cCntlr成员I3cMethod方法集合,其定义和成员函数说明见下文。
- 注册中断处理子程序:
为控制器注册中断处理程序,实现设备热接入和IBI(带内中断)功能。
1. 实例化驱动入口
驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
驱动入口必须为HdfDriverEntry(在//drivers/hdf_core/framework/include/core/hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
I3C驱动入口参考:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**<br>
> I3C控制器会出现很多个控制器挂接的情况,因而在HDF框架中首先会为此类型的控制器创建一个管理器对象,并同时对外发布一个管理器服务来统一处理外部访问。这样,用户需要打开某个控制器时,会先获取到管理器服务,然后管理器服务根据用户指定参数查找到指定控制器。
>
> I3C管理器服务的驱动由核心层实现,厂商不需要关注这部分内容的实现,但在实现Init函数的时候需要调用核心层的I3cCntlrAdd函数,它会实现相应功能。
> I3C管理器服务的驱动由核心层实现,驱动适配者不需要关注这部分内容的实现,但在实现Init函数的时候需要调用核心层的I3cCntlrAdd函数,它会实现相应功能。
```c
static struct HdfDriverEntry g_virtualI3cDriverEntry = {
.moduleVersion = 1,
.Init = VirtualI3cInit,
.Release = VirtualI3cRelease,
.moduleName = "virtual_i3c_driver", // 【必要且与hcs文件中的名字匹配】
.moduleName = "virtual_i3c_driver", // 【必要且与hcs文件中的名字匹配】
};
HDF_INIT(g_virtualI3cDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中
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对应
.moduleName = "HDF_PLATFORM_I3C_MANAGER", // 这与device_info.hcs文件中device0对应
};
HDF_INIT(g_i3cManagerEntry);
```
2. 配置属性文件
完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在i3c_config.hcs中配置器件属性。
完成驱动入口注册之后,下一步请在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件中添加deviceNode信息,并在i3c_config.hcs中配置器件属性。
deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层I3cCntlr相关成员的默认值或限制范围有密切关系。
deviceNode信息与驱动入口注册相关,器件属性值对于驱动适配者的驱动实现以及核心层I3cCntlr相关成员的默认值或限制范围有密切关系。
统一服务模式的特点是device_info文件中第一个设备节点必须为I3C管理器,其各项参数必须如下设置:
统一服务模式的特点是device_info.hcs文件中第一个设备节点必须为I3C管理器,其各项参数必须如下设置:
|成员名|值|
|-|-|
......@@ -154,7 +161,7 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
|policy|0|
|cntlrMatchAttr| 无(预留)|
从第二个节点开始配置具体I3C控制器信息,此节点并不表示某一路I3C控制器,而是代表一个资源性质设备,用于描述一类I3C控制器的信息。本例只有一个I3C控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在i3c_config文件中增加对应的器件属性。
从第二个节点开始配置具体I3C控制器信息,此节点并不表示某一路I3C控制器,而是代表一个资源性质设备,用于描述一类I3C控制器的信息。本例只有一个I3C控制器,如有多个控制器,则需要在device_info.hcs文件增加deviceNode信息,以及在i3c_config文件中增加对应的器件属性。
- device_info.hcs配置参考
......@@ -207,13 +214,21 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
}
```
需要注意的是,新增i3c_config.hcs配置文件后,必须在hdf.hcs文件中将其包含,否则配置文件无法生效。
例如:本例中i3c_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/i3c/i3c_config.hcs,则必须在产品对应的hdf.hcs中添加如下语句:
```c
#include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/i3c/i3c_config.hcs" // 配置文件相对路径
```
3. 实例化I3C控制器对象
配置属性文件完成后,要以核心层I3cCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化I3cCntlr成员I3cMethod(让用户可以通过接口来调用驱动底层函数)。
配置属性文件完成后,要以核心层I3cCntlr对象的初始化为核心,包括驱动适配者自定义结构体(传递参数和数据),实例化I3cCntlr成员I3cMethod(让用户可以通过接口来调用驱动底层函数)。
此步骤需要通过实现HdfDriverEntry成员函数(Bind,Init,Release)来完成。
I3cCntlr成员回调函数结构体I3cMethod的实例化,I3cLockMethod回调函数结构体本例未实现,若要实例化,可参考I2C驱动开发,其他成员在Init函数中初始化。
I3cCntlr成员钩子函数结构体I3cMethod的实例化,I3cLockMethod钩子函数结构体本例未实现,若要实例化,可参考I2C驱动开发,其他成员在Init函数中初始化。
- 自定义结构体参考
......@@ -222,11 +237,11 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
```c
struct VirtualI3cCntlr {
struct I3cCntlr cntlr; // 【必要】是核心层控制对象,具体描述见下面。
volatile unsigned char *regBase;// 【必要】寄存器基地址
uint32_t regBasePhy; // 【必要】寄存器物理基地址
uint32_t regSize; // 【必要】寄存器位宽
uint16_t busId; // 【必要】设备号
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;
......@@ -249,17 +264,15 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
};
```
- Init函数参考
- Init函数开发参考
**入参:**
HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。
HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。
**返回值:**
HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/hdf_core/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。
|状态(值)|问题描述|
......@@ -279,7 +292,7 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
static int32_t VirtualI3cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{
int32_t ret;
struct VirtualI3cCntlr *virtual = NULL; // 【必要】自定义结构体对象
struct VirtualI3cCntlr *virtual = NULL; // 【必要】自定义结构体对象
(void)device;
virtual = (struct VirtualI3cCntlr *)OsalMemCalloc(sizeof(*virtual)); // 【必要】内存分配
......@@ -288,7 +301,7 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
return HDF_ERR_MALLOC_FAIL;
}
ret = VirtualI3cReadDrs(virtual, node); // 【必要】将i3c_config文件的默认值填充到结构体中
ret = VirtualI3cReadDrs(virtual, node); // 【必要】将i3c_config文件的默认值填充到结构体中,函数定义见下方
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret);
goto __ERR__;
......@@ -342,13 +355,40 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
return ret;
}
static int32_t VirtualI3cReadDrs(struct VirtualI3cCntlr *virtual, const struct DeviceResourceNode *node)
{
struct DeviceResourceIface *drsOps = NULL;
/* 获取drsOps方法 */
drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) {
HDF_LOGE("%s: Invalid drs ops fail!", __func__);
return HDF_FAILURE;
}
/* 将配置参数依次读出,并填充至结构体中 */
if (drsOps->GetUint16(node, "busId", &virtual->busId, 0) != HDF_SUCCESS) {
HDF_LOGE("%s: Read busId fail!", __func__);
return HDF_ERR_IO;
}
if (drsOps->GetUint16(node, "busMode", &virtual->busMode, 0) != HDF_SUCCESS) {
HDF_LOGE("%s: Read busMode fail!", __func__);
return HDF_ERR_IO;
}
if (drsOps->GetUint16(node, "IrqNum", &virtual->IrqNum, 0) != HDF_SUCCESS) {
HDF_LOGE("%s: Read IrqNum fail!", __func__);
return HDF_ERR_IO;
}
···
return HDF_SUCCESS;
}
```
- Release函数参考
- Release函数开发参考
**入参:**
HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。
HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。
**返回值:**
......@@ -386,8 +426,8 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
cntlr = I3cCntlrGet(busId);
if (cntlr != NULL && cntlr->priv == node) {
I3cCntlrPut(cntlr);
I3cCntlrRemove(cntlr); // 【必要】主要是从管理器驱动那边移除I3cCntlr对象
virtual = (struct VirtualI3cCntlr *)cntlr;// 【必要】通过强制转换获取自定义的对象并进行release操作
I3cCntlrRemove(cntlr); // 【必要】主要是从管理器驱动那边移除I3cCntlr对象
virtual = (struct VirtualI3cCntlr *)cntlr; // 【必要】通过强制转换获取自定义的对象并进行release操作
(void)OsalSpinDestroy(&virtual->spin);
OsalMemFree(virtual);
}
......@@ -405,7 +445,7 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
return;
}
...
// 遍历、解析i3c_config.hcs中的所有配置节点,并分别进行release操作
/* 遍历、解析i3c_config.hcs中的所有配置节点,并分别进行release操作 */
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
VirtualI3cRemoveByNode(childNode); //函数定义如上
}
......@@ -438,12 +478,10 @@ I3C模块适配的四个环节是实例化驱动入口、配置属性文件、
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;
......
# MIPI DSI
## 概述
### 功能简介
DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设(通常是LCD或者类似的显示设备),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。
MIPI DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。
图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。
**图1** DSI发送、接收接口
**图1** DSI发送、接收接口
![image](figures/DSI发送-接收接口.png "DSI发送-接收接口")
![image](figures/DSI发送-接收接口.png "DSI发送-接收接口")
DSI标准对应D-PHY、DSI、DCS规范,可分为四层:
## 接口说明
- PHY Layer
**表1** MIPI DSI API接口功能介绍
定义了传输媒介,输入/输出电路和和时钟和信号机制。PHY层指定传输介质(电导体)、输入/输出电路和从串行比特流中捕获“1”和“0”的时钟机制。这一部分的规范记录了传输介质的特性、信号的电气参数以及时钟与数据通道之间的时序关系。在DSI链路的发送端,并行数据、信号事件和命令按照包组织在协议层转换为包。协议层附加包协议信息和报头,然后通过Lane Management层向PHY发送完整的字节。数据由PHY进行序列化,并通过串行链路发送。DSI链路的接收端执行与发送端相反的操作,将数据包分解为并行的数据、信号事件和命令。如果有多个Lane, Lane管理层将字节分配给单独的物理层,每个Lane一个PHY。
| 功能分类 | 接口名 |
| -------- | -------- |
| 设置/获取当前MIPI&nbsp;DSI相关配置 | -&nbsp;MipiDsiSetCfg:设置MIPI&nbsp;DSI相关配置<br/>-&nbsp;MipiDsiGetCfg:获取当前MIPI&nbsp;DSI相关配置 |
| 获取/释放MIPI&nbsp;DSI操作句柄 | -&nbsp;MipiDsiOpen:获取MIPI&nbsp;DSI操作句柄<br/>-&nbsp;MipiDsiClose:释放MIPI&nbsp;DSI操作句柄 |
| 设置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模式 |
| MIPI&nbsp;DSI发送/回读指令 | -&nbsp;MipiDsiTx:MIPI&nbsp;DSI发送相应指令的接口<br/>-&nbsp;MipiDsiRx:MIPI&nbsp;DSI按期望长度回读的接口 |
- Lane Management层
负责发送和收集数据流到每条Lane。数据Lane的三种操作模式 :espace mode,High-Speed(Burst) mode,Control mode。
- Low Level Protocol层
定义了如何组帧和解析以及错误检测等。
- Application层
描述高层编码和解析数据流。这一层描述了数据流中包含的数据的更高级的编码和解释。根据显示子系统架构的不同,它可能由具有指定格式的像素或编码的位流组成,或者由显示模块内的显示控制器解释的命令组成。DSI规范描述了像素值、位流、命令和命令参数到包集合中的字节的映射。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**<br>
> 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。
### 运作机制
MIPI DSI软件模块各分层的作用为:
- 接口层:提供打开设备、写入数据和关闭设备的接口。
- 核心层:主要提供绑定设备、初始化设备以及释放设备的能力。
- 适配层:实现其它具体的功能。
![](../public_sys-resources/icon-note.gif) **说明:**<br>核心层可以调用接口层的函数,核心层通过钩子函数调用适配层函数,从而适配层可以间接的调用接口层函数,但是不可逆转接口层调用适配层函数。
**图2** DSI无服务模式结构图
![image](figures/无服务模式结构图.png "DSI无服务模式结构图")
### 约束与限制
由于使用无服务模式,MIPI_DSI接口暂不支持用户态使用。
## 使用指导
### 场景介绍
MIPI DSI主要用于连接显示屏。
### 使用流程
### 接口说明
MIPI DSI模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/mipi_dsi_if.h。
**表1** MIPI DSI API接口功能介绍
| 功能分类 | 接口名 |
| -------- | -------- |
| DevHandle MipiDsiOpen(uint8_t id) | 获取MIPI&nbsp;DSI操作句柄 |
| void MipiDsiClose(DevHandle handle) | 释放MIPI&nbsp;DSI操作句柄 |
| int32_t MipiDsiSetCfg(DevHandle handle, struct MipiCfg \*cfg) | 设置MIPI&nbsp;DSI相关配置 |
| int32_t MipiDsiGetCfg(DevHandle handle, struct MipiCfg \*cfg) | 获取当前MIPI&nbsp;DSI相关配置 |
| void MipiDsiSetLpMode(DevHandle handle) | 设置MIPI&nbsp;DSI进入Low&nbsp;power模式 |
| void MipiDsiSetHsMode(DevHandle handle) | 设置MIPI&nbsp;DSI进入High&nbsp;speed模式 |
| int32_t MipiDsiTx(DevHandle handle, struct DsiCmdDesc \*cmd) | DSI发送指令 |
| int32_t MipiDsiRx(DevHandle handle, struct DsiCmdDesc \*cmd, int32_t readLen, uint8_t \*out) | MIPI&nbsp;DSI按期望长度回读数据 |
### 开发步骤
使用MIPI DSI的一般流程如下图所示。
**图2** MIPI DSI使用流程图
**图3** MIPI DSI使用流程图
![image](figures/MIPI-DSI使用流程图.png "MIPI-DSI使用流程图")
![image](figures/MIPI-DSI使用流程图.png "MIPI-DSI使用流程图")
### 获取MIPI DSI操作句柄
#### 获取MIPI DSI操作句柄
在进行MIPI DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。
```
```c
DevHandle MipiDsiOpen(uint8_t id);
```
......@@ -61,8 +102,8 @@ DevHandle MipiDsiOpen(uint8_t id);
假设系统中的MIPI DSI通道为0,获取该通道操作句柄的示例如下:
```
```c
DevHandle mipiDsiHandle = NULL; /* 设备句柄 */
chnId = 0; /* MIPI DSI通道ID */
......@@ -75,11 +116,11 @@ if (mipiDsiHandle == NULL) {
```
### MIPI DSI相应配置
#### MIPI DSI相应配置
- 写入MIPI DSI配置
```
```c
int32_t MipiDsiSetCfg(DevHandle handle, struct MipiCfg *cfg);
```
......@@ -93,8 +134,8 @@ if (mipiDsiHandle == NULL) {
| 0 | 设置成功 |
| 负数 | 设置失败 |
```
```c
int32_t ret;
struct MipiCfg cfg = {0};
......@@ -122,8 +163,8 @@ if (mipiDsiHandle == NULL) {
```
- 获取当前MIPI DSI的配置
```
```c
int32_t MipiDsiGetCfg(DevHandle handle, struct MipiCfg *cfg);
```
......@@ -137,8 +178,8 @@ if (mipiDsiHandle == NULL) {
| 0 | 获取成功 |
| 负数 | 获取失败 |
```
```c
int32_t ret;
struct MipiCfg cfg;
memset(&cfg, 0, sizeof(struct MipiCfg));
......@@ -150,11 +191,11 @@ if (mipiDsiHandle == NULL) {
```
### 发送/回读控制指令
#### 发送/回读控制指令
- 发送指令
```
```c
int32_t MipiDsiTx(PalHandle handle, struct DsiCmdDesc *cmd);
```
......@@ -168,8 +209,8 @@ if (mipiDsiHandle == NULL) {
| 0 | 发送成功 |
| 负数 | 发送失败 |
```
```c
int32_t ret;
struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc));
if (cmd == NULL) {
......@@ -197,8 +238,8 @@ if (mipiDsiHandle == NULL) {
```
- 回读指令
```
```c
int32_t MipiDsiRx(DevHandle handle, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out);
```
......@@ -214,8 +255,8 @@ if (mipiDsiHandle == NULL) {
| 0 | 获取成功 |
| 负数 | 获取失败 |
```
```c
int32_t ret;
uint8_t readVal = 0;
......@@ -245,12 +286,11 @@ if (mipiDsiHandle == NULL) {
```
### 释放MIPI DSI操作句柄
#### 释放MIPI DSI操作句柄
MIPI DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示:
```
```c
void MipiDsiClose(DevHandle handle);
```
......@@ -262,18 +302,18 @@ void MipiDsiClose(DevHandle handle);
| -------- | -------- |
| handle | MIPI&nbsp;DSI操作句柄 |
```
```c
MipiDsiClose(mipiHandle); /* 释放掉MIPI DSI操作句柄 */
```
## 使用实例
本例拟对Hi3516DV300开发板上MIPI DSI设备进行操作。
MIPI DSI完整的使用示例如下所示:
```
```c
#include "hdf.h"
#include "mipi_dsi_if.h"
......
......@@ -30,22 +30,23 @@ Regulator接口定义了操作Regulator设备的通用方法集合,包括:
电源管理芯片,内含多个电源甚至其他子系统。
### 运作机制
在HDF框架中,Regulator模块接口适配模式采用统一服务模式,这需要一个设备服务来作为Regulator模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如Regulator可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源
在HDF框架中,Regulator模块接口适配模式采用统一服务模式(如图1),这需要一个设备服务来作为Regulator模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如Regulator可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问,实现便捷管理和节约资源的目的
Regulator模块各分层的作用为:接口层提供打开设备,写入数据,关闭设备接口的能力。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其他具体的功能。
Regulator模块各分层的作用为:
![](../public_sys-resources/icon-note.gif) 说明:<br>核心层可以调用接口层的函数,也可以通过钩子函数调用适配层函数,从而使得适配层间接的可以调用接口层函数,但是不可逆转接口层调用适配层函数。
- 接口层:提供打开设备,操作Regulator,关闭设备的能力。
- 核心层:主要负责服务绑定、初始化以及释放管理器,并提供添加、删除以及获取Regulator设备的能力。
- 适配层:由驱动适配者实现与硬件相关的具体功能,如设备的初始化等。
**图 1** 统一服务模式结构图
**图 1** Regulator统一服务模式结构图<a name="fig1"></a>
![image1](figures/统一服务模式结构图.png)
### 约束与限制
Regulator模块当前仅支持轻量和小型系统内核(LiteOS)
Regulator模块API当前仅支持内核态调用
## 使用指导
......@@ -58,27 +59,25 @@ Regulator主要用于:
### 接口说明
Regulator模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/regulator_if.h。
**表1** Regulator设备API接口说明
| 接口名 | 描述 |
| 接口名 | 接口描述 |
| --------------------- | ------------------------- |
| RegulatorOpen | 获取Regulator设备驱动句柄 |
| RegulatorClose | 销毁Regulator设备驱动句柄 |
| RegulatorEnable | 使能Regulator |
| RegulatorDisable | 禁用Regulator |
| RegulatorForceDisable | 强制禁用Regulator |
| RegulatorSetVoltage | 设置Regulator输出电压 |
| RegulatorGetVoltage | 获取Regulator输出电压 |
| RegulatorSetCurrent | 设置Regulator输出电流 |
| RegulatorGetCurrent | 获取Regulator输出电流 |
| RegulatorGetStatus | 获取Regulator状态 |
| DevHandle RegulatorOpen(const char \*name) | 获取Regulator设备驱动句柄 |
| void RegulatorClose(DevHandle handle) | 销毁Regulator设备驱动句柄 |
| int32_t RegulatorEnable(DevHandle handle) | 使能Regulator |
| int32_t RegulatorDisable(DevHandle handle) | 禁用Regulator |
| int32_t RegulatorForceDisable(DevHandle handle) | 强制禁用Regulator |
| int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv) | 设置Regulator输出电压 |
| int32_t RegulatorGetVoltage(DevHandle handle, uint32_t \*voltage) | 获取Regulator输出电压 |
| int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa) | 设置Regulator输出电流 |
| int32_t RegulatorGetCurrent(DevHandle handle, uint32_t \*regCurrent) | 获取Regulator输出电流 |
| int32_t RegulatorGetStatus(DevHandle handle, uint32_t \*status) | 获取Regulator状态 |
### 开发步骤
在操作系统启动过程中,驱动管理模块根据配置文件加载Regulator驱动,Regulator驱动会检测Regulator器件并初始化驱动。
使用Regulator设备的一般流程如图2所示。
**图 2** Regulator设备使用流程图
......@@ -89,7 +88,7 @@ Regulator主要用于:
在操作Regulator设备时,首先要调用RegulatorOpen获取Regulator设备句柄,该函数会返回指定设备名称的Regulator设备句柄。
```
```c
DevHandle RegulatorOpen(const char *name);
```
......@@ -104,7 +103,7 @@ DevHandle RegulatorOpen(const char *name);
```
```c
/* Regulator设备名称 */
const char *name = "regulator_virtual_1";
DevHandle handle = NULL;
......@@ -120,7 +119,7 @@ if (handle == NULL) {
关闭Regulator设备,系统释放对应的资源。
```
```c
void RegulatorClose(DevHandle handle);
```
......@@ -130,7 +129,7 @@ void RegulatorClose(DevHandle handle);
| ------ | ----------------- |
| handle | Regulator设备句柄 |
```
```c
/* 销毁Regulator设备句柄 */
RegulatorClose(handle);
```
......@@ -139,7 +138,7 @@ RegulatorClose(handle);
启用Regulator设备。
```
```c
int32_t RegulatorEnable(DevHandle handle);
```
......@@ -154,7 +153,7 @@ int32_t RegulatorEnable(DevHandle handle);
```
```c
int32_t ret;
/* 启用Regulator设备 */
......@@ -168,7 +167,7 @@ if (ret != 0) {
禁用Regulator设备。如果Regulator设备状态为常开,或存在Regulator设备子节点未禁用,则禁用失败。
```
```c
int32_t RegulatorDisable(DevHandle handle);
```
......@@ -181,7 +180,7 @@ int32_t RegulatorDisable(DevHandle handle);
| 0 | 禁用成功 |
| 负数 | 禁用失败 |
```
```c
int32_t ret;
/* 禁用Regulator设备 */
......@@ -195,7 +194,7 @@ if (ret != 0) {
强制禁用Regulator设备。无论Regulator设备的状态是常开还是子节点已使能,Regulator设备都会被禁用。
```
```c
int32_t RegulatorForceDisable(DevHandle handle);
```
......@@ -209,7 +208,7 @@ int32_t RegulatorForceDisable(DevHandle handle);
| 0 | 禁用成功 |
| 负数 | 禁用失败 |
```
```c
int32_t ret;
/* 强制禁用Regulator设备 */
......@@ -221,9 +220,7 @@ if (ret != 0) {
#### 设置Regulator输出电压范围
设置Regulator电压输出电压范围。
```
```c
int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv);
```
......@@ -238,7 +235,7 @@ int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv);
| 0 | 设置成功 |
| 负数 | 设置失败 |
```
```c
int32_t ret;
int32_t minUv = 0; // 最小电压为0µV
int32_t maxUv = 20000; // 最大电压为20000µV
......@@ -252,9 +249,7 @@ if (ret != 0) {
#### 获取Regulator电压
获取Regulator电压。
```
```c
int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage);
```
......@@ -269,7 +264,7 @@ int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage);
| 0 | 获取成功 |
| 负数 | 获取失败 |
```
```c
int32_t ret;
uint32_t voltage;
......@@ -282,9 +277,7 @@ if (ret != 0) {
#### 设置Regulator输出电流范围
设置Regulator输出电流范围。
```
```c
int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa);
```
......@@ -299,9 +292,9 @@ int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa);
| 0<br>| 设置成功 |
| 负数 | 设置失败 |
```
```c
int32_t ret;
int32_t minUa = 0; // 最小电流为0μA
int32_t minUa = 0; // 最小电流为0μA
int32_t maxUa = 200; // 最大电流为200μA
/* 设置Regulator输出电流范围 */
......@@ -313,9 +306,7 @@ if (ret != 0) {
#### 获取Regulator电流
获取Regulator电流。
```
```c
int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent);
```
......@@ -329,7 +320,7 @@ int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent);
| 0 | 获取成功 |
| 负数 | 获取失败 |
```
```c
int32_t ret;
uint32_t regCurrent;
......@@ -342,9 +333,7 @@ if (ret != 0) {
#### 获取Regulator状态
获取Regulator状态。
```
```c
int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status);
```
......@@ -358,7 +347,7 @@ int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status);
| 0 | 获取成功 |
| 负数 | 获取失败 |
```
```c
int32_t ret;
uint32_t status;
......@@ -373,9 +362,11 @@ if (ret != 0) {
## 使用实例
本例拟对Hi3516DV300开发板上Regulator设备进行简单的读取操作。
Regulator设备完整的使用示例如下所示,首先获取Regulator设备句柄,然后使能,设置电压,获取电压、状态,禁用,最后销毁Regulator设备句柄。
```
```c
void RegulatorTestSample(void)
{
int32_t ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册