diff --git a/zh-cn/device-dev/driver/Readme-CN.md b/zh-cn/device-dev/driver/Readme-CN.md index 1db6007a4f7910b431d957c70cecc76c883c36b4..257ae75de412f89746fb2218c21dfdd4148bedb8 100755 --- a/zh-cn/device-dev/driver/Readme-CN.md +++ b/zh-cn/device-dev/driver/Readme-CN.md @@ -16,7 +16,9 @@ - [MIPI-CSI](driver-platform-mipicsi-develop.md) - [MIPI-DSI](driver-platform-mipidsi-develop.md) - [MMC](driver-platform-mmc-develop.md) + - [PIN](driver-platform-pin-develop.md) - [PWM](driver-platform-pwm-develop.md) + - [REGULATOR](driver-platform-regulator-develop.md) - [RTC](driver-platform-rtc-develop.md) - [SDIO](driver-platform-sdio-develop.md) - [SPI](driver-platform-spi-develop.md) @@ -31,6 +33,7 @@ - [MIPI-CSI](driver-platform-mipicsi-des.md) - [MIPI-DSI](driver-platform-mipidsi-des.md) - [PWM](driver-platform-pwm-des.md) + - [REGULATOR](driver-platform-regulator-des.md) - [RTC](driver-platform-rtc-des.md) - [SDIO](driver-platform-sdio-des.md) - [SPI](driver-platform-spi-des.md) diff --git a/zh-cn/device-dev/driver/driver-platform-pin-develop.md b/zh-cn/device-dev/driver/driver-platform-pin-develop.md new file mode 100755 index 0000000000000000000000000000000000000000..ca0ca47d8e16a3988067e904104d4cc6e1be7fee --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-pin-develop.md @@ -0,0 +1,316 @@ +# PIN + +- [概述](#section1_PinDevelop) +- [接口说明](#section2_PinDevelop) +- [开发步骤](#section3_PinDevelop) +- [开发实例](#section4_PinDevelop) + +## 概述 + +PIN模块用于控制系统中管脚的状态和功能特性。在HDF框架中,PIN的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 + +图 1 无服务模式结构图 +![image1](figures/无服务模式结构图.png) + +## 接口说明 + +PinCntlrMethod定义: + +```c +struct PinCntlrMethod { + int32_t (*SetPinPull)(struct PinCntlr *cntlr, uint32_t index, enum PinPullType pullType); + int32_t (*GetPinPull)(struct PinCntlr *cntlr, uint32_t index, enum PinPullType *pullType); + int32_t (*SetPinStrength)(struct PinCntlr *cntlr, uint32_t index, uint32_t strength); + int32_t (*GetPinStrength)(struct PinCntlr *cntlr, uint32_t index, uint32_t *strength); + int32_t (*SetPinFunc)(struct PinCntlr *cntlr, uint32_t index, const char *funcName); + int32_t (*GetPinFunc)(struct PinCntlr *cntlr, uint32_t index, const char **funcName); +}; +``` + +**表 1** PinCntlrMethod成员的回调函数功能说明 + +| 成员函数 | 入参 | 返回值 | 功能 | +| ------------ | ------------------------------------------- | ------ | ---- | +| SetPinPull | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**pullType**:枚举常量,Pin管脚推拉方式; |HDF_STATUS相关状态|设置Pin管脚推拉方式| +| GetPinPull | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**pullType**:枚举常量指针,传出Pin管脚推拉方式; | HDF_STATUS相关状态 | 获取Pin管脚推拉方式 | +| SetPinStrength | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**strength**:uint32_t变量,Pin推拉强度; | HDF_STATUS相关状态 | 设置Pin推拉强度 | +| GetPinStrength | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**strength**:uint32_t变量指针,传出Pin推拉强度; | HDF_STATUS相关状态 | 获取Pin推拉强度 | +| SetPinFunc | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**funcName**:char指针常量,传入Pin管脚功能; | HDF_STATUS相关状态 | 设置Pin管脚功能 | +| GetPinFunc | **cntlr**:结构体指针,核心层Pin控制器;
**index**:uint32_t变量,管脚索引号;
**funcName**:char双重指针常量,传出Pin管脚功能; | HDF_STATUS相关状态 | 获取Pin管脚功能 | + +## 开发步骤 + +PIN模块适配的三个环节是实例化驱动入口、配置属性文件、以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + + - 在device_info.hcs文件中添加deviceNode描述。 + - 【可选】添加pin_config.hcs器件属性文件。 + +3. **实例化PIN控制器对象:** + + - 初始化PinCntlr成员。 + + - 实例化PinCntlr成员PinCntlrMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化PinCntlr成员PinCntlrMethod,其定义和成员说明见[接口说明](#section2_PINDevelop)。 + +4. **驱动调试:** + + - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,数据传输的成功与否等。 + +## 开发实例 + +下方将以pin_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + PIN驱动入口参考 + + ```c + static struct HdfDriverEntry g_hi35xxPinDriverEntry = { + .moduleVersion = 1, + .Bind = Hi35xxPinBind, + .Init = Hi35xxPinInit, + .Release = Hi35xxPinRelease, + .moduleName = "hi35xx_pin_driver",//【必要且与HCS文件中里面的moduleName匹配】 + }; + //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_hi35xxPinDriverEntry); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在pin\_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层PinCntlr成员的默认值或限制范围有密切关系。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如有更多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在pin\_config文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考。 + + ```c + root { + device_info { + platform :: host { + hostName = "platform_host"; + priority = 50; + device_pin :: device { + device0 :: deviceNode { //为每一个Pin控制器配置一个HDF设备节点,存在多个时须添加,否则不用 + policy = 0; //2:用户态可见,1:内核态可见,0:不需要发布服务 + priority = 10; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + /*【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致;*/ + moduleName = "hi35xx_Pin_driver"; + /*【必要】用于配置控制器私有数据,要与Pin_config.hcs中对应控制器保持一致,具体的控制器信息在Pin_config.hcs 中*/ + deviceMatchAttr = "hisilicon_hi35xx_Pin_0"; + } + device1 :: deviceNode { + policy = 0; + priority = 10; + permission = 0644; + moduleName = "hi35xx_Pin_driver"; + deviceMatchAttr = "hisilicon_hi35xx_Pin_1"; + } + ... + } + } + } + } + ``` + + - Pin\_config.hcs 配置参考。 + + ```c + root { + platform { + Pin_config_hi35xx { + template Pin_controller { //【必要】模板配置,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + number = 0; //【必要】controller 编号 + regStartBasePhy = 0; //【必要】寄存器物理基地址起始地址 + regSize = 0; //【必要】寄存器位宽 + PinCount = 0; //【必要】管脚数量 + match_attr = ""; + template Pin_desc { + PinName = ""; //【必要】管脚名称 + init = 0; //【必要】寄存器默认值 + F0 = ""; //【必要】功能0 + F1 = ""; //功能1 + F2 = ""; //功能2 + F3 = ""; //功能3 + F4 = ""; //功能4 + F5 = ""; //功能5 + } + } + controller_0 :: Pin_controller { + number = 0; + regStartBasePhy = 0x10FF0000; + regSize = 0x48; + PinCount = 18; + match_attr = "hisilicon_hi35xx_Pin_0"; + T1 :: Pin_desc { + PinName = "T1"; + init = 0x0600; + F0 = "EMMC_CLK"; + F1 = "SFC_CLK"; + F2 = "SFC_BOOT_MODE"; + } + ... + } + ...//每个Pin控制器对应一个controller节点,如存在多个Pin控制器,请依次添加对应的controller节点。 + } + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是对核心层PinCntlr对象的初始化,包括厂商自定义结构体(传递参数和数据),实例化PinCntlr成员PinCntlrMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + + - 自定义结构体参考。 + + 从驱动的角度看,PinCntlr结构体是参数和数据的载体,HDF框架通过DeviceResourceIface将pin\_config.hcs文件中的数值读入其中。 + + ```c + // PinCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct PinCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + struct PinCntlrMethod *method; + struct DListHead node; + OsalSPinlock sPin; + uint16_t number; + uint16_t PinCount; + struct PinDesc *Pins; + void *priv; + }; + + struct PinDesc { + const char *PinName; //Pin管脚名 + void *priv; + }; + ``` + + - 实例化PinCntlr成员PinCntlrMethod,其他成员在Init函数中初始化。 + + ```c + // Pin_hi35xx.c 中的示例:钩子函数的填充 + static struct PinCntlrMethod g_method = { + .SetPinPull = Hi35xxPinSetPull, + .GetPinPull = Hi35xxPinGetPull, + .SetPinStrength = Hi35xxPinSetStrength, + .GetPinStrength = Hi35xxPinGetStrength, + .SetPinFunc = Hi35xxPinSetFunc, + .GetPinFunc = Hi35xxPinGetFunc, + }; + ``` + + - Init函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见/drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 2** HDF\_STATUS相关状态 + + + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

控制器对象非法

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_INVALID_PARAM

+

参数非法

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

初始化成功

+

HDF_FAILURE

+

初始化失败

+
+ + 函数说明: + 初始化自定义结构体和PinCntlr成员,并通过调用核心层PinCntlrAdd函数挂载Pin控制器。 + + ```c + static int32_t Hi35xxPinInit(struct HdfDeviceObject *device) + { + ... + struct Hi35xxPinCntlr *hi35xx = NULL; + ... + ret = Hi35xxPinCntlrInit(device, hi35xx); //读取hcs文件信息 + ... + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = Hi35xxPinParsePinNode(childNode, hi35xx, index); //【必要】实现如下 + ... + } + + hi35xx->cntlr.method = &g_method; //实例化ops + ret = PinCntlrAdd(&hi35xx->cntlr); //挂载控制器 + ... + } + + static int32_t Hi35xxPinParsePinNode(const struct DeviceResourceNode *node, + struct Hi35xxPinCntlr *hi35xx, + int32_t index) + { + ... + hi35xx->cntlr.Pins[index].PinName = hi35xx->desc[index].PinName; //实例化PinName + hi35xx->cntlr.Pins[index].priv = (void *)node; //实例化节点 + ... + } + + + - Release 函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 + + ```c + static void Hi35xxPinRelease(struct HdfDeviceObject *device) + { + struct PinCntlr *cntlr = NULL; + ... + PinCntlrRemove(cntlr);//【必要】调用核心层函数,释放PinCntlr的设备和服务 + ... + } + ``` diff --git a/zh-cn/device-dev/driver/driver-platform-regulator-des.md.md b/zh-cn/device-dev/driver/driver-platform-regulator-des.md.md new file mode 100755 index 0000000000000000000000000000000000000000..11af14de0e2daca02878b0d4b201d0dc8ddb2d4f --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-regulator-des.md.md @@ -0,0 +1,479 @@ +# REGULATOR + +- [概述](#section1_REGULATOR_des) +- [接口说明](#section2_REGULATOR_des) +- [使用指导](#section3_REGULATOR_des) + - [使用流程](#section3.1_REGULATOR_des) + - [获取REGULATOR设备句柄](#section3.2_REGULATOR_des) + - [销毁REGULATOR设备句柄](#section3.3_REGULATOR_des) + - [使能](#section3.4_REGULATOR_des) + - [禁用](#section3.5_REGULATOR_des) + - [强制禁用](#section3.6_REGULATOR_des) + - [设置REGULATOR电压输出电压范围](#section3.7_REGULATOR_des) + - [获取REGULATOR设备电压](#section3.8_REGULATOR_des) + - [设置REGULATOR设备输出电流范围](#section3.9_REGULATOR_des) + - [获取REGULATOR设备电流](#section3.10_REGULATOR_des) + - [获取REGULATOR设备状态](#section3.11_REGULATOR_des) +- [使用实例](#section4_REGULATOR_des) + +## 概述 + +- REGULATOR模块用于控制系统中某些设备的电压/电流供应。在嵌入式系统(尤其是手机)中,控制耗电量很重要,直接影响到电池的续航时间。所以,如果系统中某一个模块暂时不需要使用,就可以通过regulator关闭其电源供应;或者降低提供给该模块的电压、电流大小。 + +- REGULATOR接口定义了操作REGULATOR设备的通用方法集合,包括: + - REGULATOR设备句柄获取和销毁。 + - REGULATOR设备电压、电流的设置。 + - REGULATOR设备使能和关闭。 + - REGULATOR设备电压、电流和状态的获取 + +## 接口说明 + +**表1** REGULATOR设备API功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能分类接口名描述
REGULATOR句柄操作RegulatorOpen获取REGULATOR设备驱动句柄
RegulatorClose销毁REGULATOR设备驱动句柄
使能/禁用REGULATORRegulatorEnable使能REGULATOR
RegulatorDisable禁用REGULATOR
RegulatorForceDisable强制禁用REGULATOR
设置/获取REGULATOR输出电压RegulatorSetVoltage设置REGULATOR输出电压
RegulatorGetVoltage获取REGULATOR输出电压
设置/获取REGULATOR输出电流RegulatorSetCurrent设置REGULATOR输出电流
RegulatorGetCurrent获取REGULATOR输出电流
获取REGULATOR状态RegulatorGetStatus获取REGULATOR状态
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>REGULATOR当前仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +在操作系统启动过程中,驱动管理模块根据配置文件加载REGULATOR驱动,REGULATOR驱动会检测REGULATOR器件并初始化驱动。 + +使用REGULATOR设备的一般流程如[图1](#fig1_REGULATOR_des)所示。 + +**图 1** REGULATOR设备使用流程图 + + +![](figures/REGULATOR设备使用流程图.png) + +### 获取REGULATOR设备句柄 + +在操作REGULATOR设备时,首先要调用RegulatorOpen获取REGULATOR设备句柄,该函数会返回指定设备名称的REGULATOR设备句柄。 + +```c +DevHandle RegulatorOpen(const char *name); +``` + +**表2** RegulatorOpen参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------------------- | +| name | REGULATOR设备名称 | +| **返回值** | **返回值描述** | +| handle | 获取成功返回REGULATOR设备句柄 | +| NULL | 获取失败 | + + +```c +/* REGULATOR设备名称 */ +const char *name = "regulator_virtual_1"; +DevHandle handle = NULL; + +/* 获取REGULATOR设备句柄 */ +handle = RegulatorOpen(name); +if (handle == NULL) { + /* 错误处理 */ +} +``` + +### 销毁REGULATOR设备句柄 + +关闭REGULATOR设备,系统释放对应的资源。 + +```c +void RegulatorClose(DevHandle handle); +``` + +**表3** RegulatorClose参数描述 + + + +| 参数 | 参数描述 | +| ------ | ----------------- | +| handle | REGULATOR设备句柄 | + + +```c +/* 销毁REGULATOR设备句柄 */ +RegulatorClose(handle); +``` + +### 使能 + +启用REGULATOR设备。 + +```c +int32_t RegulatorEnable(DevHandle handle); +``` + +**表4** RegulatorEnable参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------- | +| handle | REGULATOR设备句柄 | +| **返回值** | **返回值描述** | +| 0 | 使能成功 | +| 负数 | 使能失败 | + +```c +int32_t ret; + +/*启用REGULATOR设备*/ +ret = RegulatorEnable(handle); +if (ret != 0) { + /*错误处理*/ +} +``` + +### 禁用 + +禁用REGULATOR设备。 + +```c +int32_t RegulatorDisable(DevHandle handle); +``` + +**表5** RegulatorDisable参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------- | +| handle | REGULATOR设备句柄 | +| **返回值** | **返回值描述** | +| 0 | 禁用成功 | +| 负数 | 禁用失败 | + +```c +int32_t ret; + +/*禁用REGULATOR设备,如果REGULATOR设备状态为常开,或存在REGULATOR设备子节点未禁用,则禁用失败*/ +ret = RegulatorDisable(handle); +if (ret != 0) { + /*错误处理*/ +} +``` + +### 强制禁用 + +强制禁用REGULATOR设备。 + +```c +int32_t RegulatorForceDisable(DevHandle handle); +``` + +**表6** RegulatorForceDisable参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------- | +| handle | REGULATOR设备句柄 | +| **返回值** | **返回值描述** | +| 0 | 强制禁用成功 | +| 负数 | 强制禁用失败 | + +```c +int32_t ret; + +/*强制禁用REGULATOR设备,无论REGULATOR设备的状态是常开还是子节点已使能,REGULATOR设备都会被禁用*/ +ret = RegulatorForceDisable(handle); +if (ret != 0) { + /*错误处理*/ +} +``` +### 设置REGULATOR输出电压范围 + +设置REGULATOR电压输出电压范围。 + +```c +int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv); +``` + +**表7** RegulatorSetVoltage参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------- | +| handle | REGULATOR设备句柄 | +| minUv | 最小电压 | +| maxUv | 最大电压 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c +int32_t ret; +int32_t minUv = 0; //最小电压为0Uv +int32_t maxUv = 20000; //最大电压为20000Uv + +/*设置REGULATOR电压输出电压范围*/ +ret = RegulatorSetVoltage(handle, minUv, maxUv); +if (ret != 0) { + /*错误处理*/ +} +``` +### 获取REGULATOR电压 + +获取REGULATOR电压。 + +```c +int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage); +``` + +**表8** RegulatorGetVoltage参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------- | +| handle | REGULATOR设备句柄 | +| *voltage | 参数指针 | +| **返回值** | **返回值描述** | +| 0 | 获取成功 | +| 负数 | 获取失败 | + +```c +int32_t ret; +uint32_t voltage; + +/*获取REGULATOR电压*/ +ret = RegulatorGetVoltage(handle, &voltage); +if (ret != 0) { + /*错误处理*/ +} +``` + + +### 设置REGULATOR输出电流范围 + +设置REGULATOR输出电流范围。 + +```c +int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa); +``` + +**表9** RegulatorSetCurrent参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------- | +| handle | REGULATOR设备句柄 | +| minUa | 最小电流 | +| maxUa | 最大电流 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c +int32_t ret; +int32_t minUa = 0; //最小电流为0Ua +int32_t maxUa = 200; //最大电流为200Ua + +/*设置REGULATOR输出电流范围*/ +ret = RegulatorSetCurrent(handle, minUa, maxUa); +if (ret != 0) { + /*错误处理*/ +} +``` + +### 获取REGULATOR电流 + +获取REGULATOR电流。 + +```c +int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent); +``` + +**表10** RegulatorGetCurrent参数描述 + + + +| 参数 | 参数描述 | +| ----------- | ----------------- | +| handle | REGULATOR设备句柄 | +| *regCurrent | 参数指针 | +| **返回值** | **返回值描述** | +| 0 | 获取成功 | +| 负数 | 获取失败 | + +```c +int32_t ret; +uint32_t regCurrent; + +/*获取REGULATOR电流*/ +ret = RegulatorGetCurrent(handle, ®Current); +if (ret != 0) { + /*错误处理*/ +} +``` +### 获取REGULATOR状态 + +获取REGULATOR状态。 + +```c +int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status); +``` + +**表11** RegulatorGetStatus参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------- | +| handle | REGULATOR设备句柄 | +| *status | 参数指针 | +| **返回值** | **返回值描述** | +| 0 | 获取成功 | +| 负数 | 获取失败 | + +```c +int32_t ret; +uint32_t status; + +/*获取REGULATOR状态*/ +ret = RegulatorGetStatus(handle, &status); +if (ret != 0) { + /*错误处理*/ +} +``` + +## 使用实例 + +REGULATOR设备完整的使用示例如下所示,首先获取REGULATOR设备句柄,然后使能,设置电压,获取电压、状态,禁用,最后销毁REGULATOR设备句柄。 + +```c +void RegulatorTestSample(void) +{ + int32_t ret; + + /* REGULATOR设备名称 */ + const char *name = "regulator_virtual_1"; + DevHandle handle = NULL; + + /* 获取REGULATOR设备句柄 */ + handle = RegulatorOpen(name); + if (handle == NULL) { + HDF_LOGE("RegulatorOpen: failed!\n"); + return; + } + + /*启用REGULATOR设备*/ + ret = RegulatorEnable(handle); + if (ret != 0) { + HDF_LOGE("RegulatorEnable: failed, ret %d\n", ret); + goto _ERR; + } + + int32_t minUv = 0; //最小电压为0Uv + int32_t maxUv = 20000; //最大电压为20000Uv + + /*设置REGULATOR输出电压范围*/ + ret = RegulatorSetVoltage(handle, minUv, maxUv); + if (ret != 0) { + HDF_LOGE("RegulatorSetVoltage: failed, ret %d\n", ret); + goto _ERR; + } + + uint32_t voltage; + + /*获取REGULATOR电压*/ + ret = RegulatorGetVoltage(handle, &voltage); + if (ret != 0) { + HDF_LOGE("RegulatorGetVoltage: failed, ret %d\n", ret); + goto _ERR; + } + + uint32_t status; + + /*获取REGULATOR状态*/ + ret = RegulatorGetStatus(handle, &status); + if (ret != 0) { + HDF_LOGE("RegulatorGetStatus: failed, ret %d\n", ret); + goto _ERR; + } + + /*禁用REGULATOR设备*/ + ret = RegulatorDisable(handle); + if (ret != 0) { + HDF_LOGE("RegulatorDisable: failed, ret %d\n", ret); + goto _ERR; + } + +_ERR: + /* 销毁REGULATOR设备句柄 */ + RegulatorClose(handle); +} +``` \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-regulator-develop.md b/zh-cn/device-dev/driver/driver-platform-regulator-develop.md new file mode 100755 index 0000000000000000000000000000000000000000..69b06d2b86712cb2c62df5075642d8bd6680c5be --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-regulator-develop.md @@ -0,0 +1,339 @@ +# REGULATOR + +- [概述](#section1_REGULATORDevelop) +- [接口说明](#section2_REGULATORDevelop) +- [开发步骤](#section3_REGULATORDevelop) +- [开发实例](#section4_REGULATORDevelop) + +## 概述 + +REGULATOR模块用于控制系统中某些设备的电压/电流供应。在HDF框架中,REGULATOR模块接口适配模式采用统一服务模式,这需要一个设备服务来作为REGULATOR模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如REGULATOR可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 + +图 1 统一服务模式结构图 +![image1](figures/统一服务模式结构图.png) + +## 接口说明 + +RegulatorMethod 定义: + +```c +struct RegulatorMethod { + int32_t (*open)(struct RegulatorNode *node); + int32_t (*close)(struct RegulatorNode *node); + int32_t (*release)(struct RegulatorNode *node); + int32_t (*enable)(struct RegulatorNode *node); + int32_t (*disable)(struct RegulatorNode *node); + int32_t (*forceDisable)(struct RegulatorNode *node); + int32_t (*setVoltage)(struct RegulatorNode *node, uint32_t minUv, uint32_t maxUv); + int32_t (*getVoltage)(struct RegulatorNode *node, uint32_t *voltage); + int32_t (*setCurrent)(struct RegulatorNode *node, uint32_t minUa, uint32_t maxUa); + int32_t (*getCurrent)(struct RegulatorNode *node, uint32_t *regCurrent); + int32_t (*getStatus)(struct RegulatorNode *node, uint32_t *status); +}; +``` + +**表 1** RegulatorMethod 成员的回调函数功能说明 + +| 成员函数 | 入参 | 返回值 | 功能 | +| ------------ | ------------------------------------------- | ------ | ---- | +| open | **node**:结构体指针,核心层regulator节点; |HDF_STATUS相关状态|打开设备| +| close | **node**:结构体指针,核心层regulator节点; | HDF_STATUS相关状态 | 关闭设备 | +| release | **node**:结构体指针,核心层regulator节点; | HDF_STATUS相关状态 | 释放设备句柄 | +| enable | **node**:结构体指针,核心层regulator节点; | HDF_STATUS相关状态 | 使能 | +| disable | **node**:结构体指针,核心层regulator节点; | HDF_STATUS相关状态 | 禁用 | +| forceDisable | **node**:结构体指针,核心层regulator节点; | HDF_STATUS相关状态 | 强制禁用 | +| setVoltage | **node**:结构体指针,核心层regulator节点;
**minUv**:uint32_t变量,最小电压;
**maxUv**:uint32_t变量,最大电压; | HDF_STATUS相关状态 | 设置输出电压范围 | +| getVoltage | **node**:结构体指针,核心层regulator节点;
**voltage**:uint32_t指针,传出电压值; | HDF_STATUS相关状态 | 获取电压 | +| setCurrent | **node**:结构体指针,核心层regulator节点;
**minUa**:uint32_t变量,最小电流;
**maxUa**:uint32_t变量,最大电流; | HDF_STATUS相关状态 | 设置输出电流范围 | +| getCurrent | **node**:结构体指针,核心层regulator节点;
**regCurrent**:uint32_t指针,传出电流值; | HDF_STATUS相关状态 | 获取电流 | +| getStatus | **node**:结构体指针,核心层regulator节点;
**status**:uint32_t指针,传出状态值; | HDF_STATUS相关状态 | 获取设备状态 | + +## 开发步骤 + +REGULATOR模块适配的三个环节是实例化驱动入口、配置属性文件、以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + + - 在device_info.hcs文件中添加deviceNode描述。 + - 【可选】添加regulator_config.hcs器件属性文件。 + +3. **实例化REGULATOR控制器对象:** + + - 初始化RegulatorNode成员。 + + - 实例化RegulatorNode成员RegulatorMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化RegulatorNode成员RegulatorMethod,其定义和成员说明见[接口说明](#section2_REGULATORDevelop)。 + +4. **驱动调试:** + - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,数据传输的成功与否等。 + +## 开发实例 + +下方将以regulator_virtual.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + REGULATOR驱动入口参考 + + ```c + struct HdfDriverEntry g_regulatorDriverEntry = { + .moduleVersion = 1, + .moduleName = "virtual_regulator_driver",//【必要且与HCS文件中里面的moduleName匹配】 + .Init = VirtualRegulatorInit, + .Release = VirtualRegulatorRelease, + }; + //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_regulatorDriverEntry); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在regulator\_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层RegulatorNode成员的默认值或限制范围有密切关系。 + + >![](W:\docs\zh-cn\device-dev\public_sys-resources\icon-note.gif) **说明:** + >如有更多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在regulator\_config文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考。 + + ```c + root { + device_info { + platform :: host { + hostName = "platform_host"; + priority = 50; + device_regulator :: device { + device0 :: deviceNode { //为每一个REGULATOR控制器配置一个HDF设备节点,存在多个时添加,否则不用 + policy = 1; // 2:用户态可见,1:内核态可见,0:不需要发布服务 + priority = 50; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + /*【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致;*/ + moduleName = "HDF_PLATFORM_REGULATOR_MANAGER"; + serviceName = "HDF_PLATFORM_REGULATOR_MANAGER"; //【必要且唯一】驱动对外发布服务的名称 + /*【必要】用于配置控制器私有数据,要与regulator_config.hcs中对应控制器保持一致,具体的控制器信息在regulator_config.hcs 中*/ + deviceMatchAttr = "hdf_platform_regulator_manager"; + } + device1 :: deviceNode { + policy = 0; + priority = 55; + permission = 0644; + moduleName = "linux_regulator_adapter"; + deviceMatchAttr = "linux_regulator_adapter"; + } + } + } + } + } + ``` + + - regulator\_config.hcs 配置参考。 + + ```c + root { + platform { + regulator_config { + match_attr = "linux_regulator_adapter"; + template regulator_controller { //【必要】模板配置,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + device_num = 1; + name = ""; + devName = "regulator_adapter_consumer01"; + supplyName = ""; + mode = 1; + minUv = 0; + maxUv = 20000; + minUa = 0; + maxUa = 0; + } + controller_0x130d0000 :: regulator_controller { + device_num = 1; + name = "regulator_adapter_1"; + devName = "regulator_adapter_consumer01"; + supplyName = "virtual-regulator-hdf-adapter"; + mode = 1; + minUv = 1000; + maxUv = 50000; + minUa = 0; + maxUa = 0; + } + /*每个Regulator控制器对应一个controller节点,如存在多个Regulator控制器,请依次添加对应的controller节点。*/ + controller_0x130d0001 :: regulator_controller { + device_num = 1; + name = "regulator_adapter_2"; + devName = "regulator_adapter_consumer01"; + supplyName = "virtual2-regulator-hdf-adapter"; + mode = 2; + minUv = 0; + maxUv = 0; + minUa = 1000; + maxUa = 50000; + } + } + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是对核心层RegulatorNode对象的初始化,包括厂商自定义结构体(传递参数和数据),实例化RegulatorNode成员RegulatorMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + + - 自定义结构体参考。 + + 从驱动的角度看,RegulatorNode结构体是参数和数据的载体,HDF框架通过DeviceResourceIface将regulator\_config.hcs文件中的数值读入其中。 + + ```c + // RegulatorNode是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct RegulatorNode { + struct RegulatorDesc regulatorInfo; + struct DListHead node; + struct RegulatorMethod *ops; + void *priv; + struct OsalMutex lock; + }; + + struct RegulatorDesc { + const char *name; /* regulator 名称 */ + const char *parentName; /* regulator 父节点名称 */ + struct RegulatorConstraints constraints; /* regulator 约束信息 */ + uint32_t minUv; /* 最小输出电压值 */ + uint32_t maxUv; /* 最大输出电压值 */ + uint32_t minUa; /* 最小输出电流值 */ + uint32_t maxUa; /* 最大输出电流值 */ + uint32_t status; /* regulator的状态,开或关 */ + int useCount; + int consumerRegNums; /* regulator用户数量 */ + RegulatorStatusChangecb cb; /* 当regulator状态改变时,可通过此变量通知 */ + }; + + struct RegulatorConstraints { + uint8_t alwaysOn; /* regulator是否常开 */ + uint8_t mode; /* 模式:电压或者电流 */ + uint32_t minUv; /* 最小可设置输出电压 */ + uint32_t maxUv; /* 最大可设置输出电压 */ + uint32_t minUa; /* 最小可设置输出电流 */ + uint32_t maxUa; /* 最大可设置输出电流 */ + }; + ``` + + - 实例化RegulatorNode成员RegulatorMethod,其他成员在Init函数中初始化。 + + ```c + // regulator_virtual.c 中的示例:钩子函数的填充 + static struct RegulatorMethod g_method = { + .enable = VirtualRegulatorEnable, + .disable = VirtualRegulatorDisable, + .setVoltage = VirtualRegulatorSetVoltage, + .getVoltage = VirtualRegulatorGetVoltage, + .setCurrent = VirtualRegulatorSetCurrent, + .getCurrent = VirtualRegulatorGetCurrent, + .getStatus = VirtualRegulatorGetStatus, + }; + ``` + + - Init函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 2** HDF\_STATUS相关状态 + + + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

控制器对象非法

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_INVALID_PARAM

+

参数非法

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

初始化成功

+

HDF_FAILURE

+

初始化失败

+
+ 函数说明: + 初始化自定义结构体和RegulatorNode成员,并通过调用核心层RegulatorNodeAdd函数挂载Regulator控制器。 + + ```c + static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device) + { + int32_t ret; + const struct DeviceResourceNode *childNode = NULL; + ... + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = VirtualRegulatorParseAndInit(device, childNode);//【必要】实现见下 + ... + } + ... + } + + static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) + { + int32_t ret; + struct RegulatorNode *regNode = NULL; + (void)device; + + regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode));//加载HCS文件 + ... + ret = VirtualRegulatorReadHcs(regNode, node);//读取HCS文件信息 + ... + regNode->priv = (void *)node; //实例化节点 + regNode->ops = &g_method; //实例化ops + + ret = RegulatorNodeAdd(regNode); //挂载节点 + ... + } + + + - Release 函数参考 + + 入参: + + HdfDeviceObject是整个驱动对外暴露的接口参数,其包含了HCS配置文件中的相关配置信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。 + + ```c + static void VirtualRegulatorRelease(struct HdfDeviceObject *device) + { + ... + RegulatorNodeRemoveAll();//【必要】调用核心层函数,释放RegulatorNode的设备和服务 + } diff --git "a/zh-cn/device-dev/driver/figures/REGULATOR\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/REGULATOR\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..a8cbea04e6f2d4bed08cd61c31db8c6b3cf16c88 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/REGULATOR\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" differ