1e41f4b71Sopenharmony_ci# I3C 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## 概述 <a name="1"></a> 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### 功能简介<a name="2"></a> 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciI3C(Improved Inter Integrated Circuit)总线是由MIPI Alliance开发的一种简单、低成本的双向二线制同步串行总线。 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciI3C是两线双向串行总线,针对多个传感器从设备进行了优化,并且一次只能由一个I3C主设备控制。相比于I2C,I3C总线拥有更高的速度、更低的功耗,支持带内中断、从设备热接入以及切换当前主设备,同时向后兼容I2C从设备。I3C增加了带内中断(In-Bind Interrupt)功能,支持I3C设备进行热接入操作,弥补了I2C总线需要额外增加中断线来完成中断的不足。I3C总线上允许同时存在I2C设备、I3C从设备和I3C次级主设备。 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci### 基本概念<a name="3"></a> 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci- IBI(In-Band Interrupt):带内中断。 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci 在SCL线没有启动信号时,I3C从设备可以通过拉低SDA线使主设备发出SCL启动信号,从而发出带内中断请求。若有多个从设备同时发出中断请求,I3C主设备则通过从设备地址进行仲裁,低地址优先相应。 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci- DAA(Dynamic Address Assignment):动态地址分配。 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci I3C支持对从设备地址进行动态分配从而避免地址冲突。在分配动态地址之前,连接到I3C总线上的每个I3C/I2C设备都应以两种方式之一来唯一标识: 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci - 设备可能有一个符合I2C规范的静态地址,主机可以使用此静态地址。 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci - 在任何情况下,I3C设备均应具有48位的临时ID。除非设备具有静态地址且主机使用静态地址,否则主机应使用此48位临时ID。 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci- CCC(Common Command Code):通用命令代码。 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci 所有I3C设备均支持CCC,可以直接将其传输到特定的I3C从设备,也可以同时传输到所有I3C从设备。 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci- BCR(Bus Characteristic Register):总线特性寄存器。 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci 每个连接到I3C总线的I3C设备都应具有相关的只读总线特性寄存器(BCR),该寄存器描述了I3C兼容设备在动态地址分配和通用命令代码中的作用和功能。 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ci- DCR(Device Characteristic Register):设备特性寄存器。 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci 连接到I3C总线的每个I3C设备都应具有相关的只读设备特性寄存器(DCR),该寄存器描述了用于动态地址分配和通用命令代码的I3C兼容设备类型(例如加速度计、陀螺仪等)。 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ci### 运作机制<a name="4"></a> 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci在HDF框架中,同类型控制器对象较多时(可能同时存在十几个同类型控制器),如果采用独立服务模式则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。I3C模块采用统一服务模式(如图1)。 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ciI3C模块各分层的作用为: 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ci- 接口层:提供打开设备,写入数据,关闭设备的能力。 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci- 核心层:主要负责服务绑定、初始化以及释放管理器,并提供添加、删除以及获取控制器的能力。由于框架需要统一管理I3C总线上挂载的所有设备,因此还提供了添加、删除以及获取设备的能力,以及中断回调函数。 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci- 适配层:由驱动适配者实现与硬件相关的具体功能,如控制器的初始化等。 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ci在统一模式下,所有的控制器都被核心层统一管理,并由核心层统一发布一个服务供接口层,因此这种模式下驱动无需再为每个控制器发布服务。 51e41f4b71Sopenharmony_ci 52e41f4b71Sopenharmony_ci**图 1** I3C统一服务模式结构图<a name="fig1"></a> 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_ci### 约束与限制<a name="5"></a> 57e41f4b71Sopenharmony_ci 58e41f4b71Sopenharmony_ciI3C模块当前仅支持轻量和小型系统内核(LiteOS-A) 。 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ci## 开发指导 <a name="6"></a> 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci### 场景介绍 <a name="7"></a> 63e41f4b71Sopenharmony_ci 64e41f4b71Sopenharmony_ciI3C可连接单个或多个I3C、I2C从器件,它主要用于: 65e41f4b71Sopenharmony_ci 66e41f4b71Sopenharmony_ci- 与传感器通信,如陀螺仪、气压计或支持I3C协议的图像传感器等。 67e41f4b71Sopenharmony_ci 68e41f4b71Sopenharmony_ci- 通过软件或硬件协议转换,与其他通信接口(如UART串口等)的设备进行通信。 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci当驱动开发者需要将I3C设备适配到OpenHarmony时,需要进行I3C驱动适配,下文将介绍如何进行I3C驱动适配。 71e41f4b71Sopenharmony_ci 72e41f4b71Sopenharmony_ci### 接口说明 <a name="8"></a> 73e41f4b71Sopenharmony_ci 74e41f4b71Sopenharmony_ci为了保证上层在调用I3C接口时能够正确的操作硬件,核心层在//drivers/hdf_core/framework/support/platform/include/i3c/i3c_core.h中定义了以下钩子函数。驱动适配者需要在适配层实现这些函数的具体功能,并与这些钩子函数挂接,从而完成接口层与核心层的交互。 75e41f4b71Sopenharmony_ci 76e41f4b71Sopenharmony_ciI3cMethod定义: 77e41f4b71Sopenharmony_ci 78e41f4b71Sopenharmony_ci```c 79e41f4b71Sopenharmony_cistruct I3cMethod { 80e41f4b71Sopenharmony_ci int32_t (*sendCccCmd)(struct I3cCntlr *cntlr, struct I3cCccCmd *ccc); 81e41f4b71Sopenharmony_ci int32_t (*transfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count); 82e41f4b71Sopenharmony_ci int32_t (*i2cTransfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count); 83e41f4b71Sopenharmony_ci int32_t (*setConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config); 84e41f4b71Sopenharmony_ci int32_t (*getConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config); 85e41f4b71Sopenharmony_ci int32_t (*requestIbi)(struct I3cDevice *dev); 86e41f4b71Sopenharmony_ci void (*freeIbi)(struct I3cDevice *dev); 87e41f4b71Sopenharmony_ci}; 88e41f4b71Sopenharmony_ci``` 89e41f4b71Sopenharmony_ci 90e41f4b71Sopenharmony_ci**表 1** I3cMethod结构体成员的钩子函数功能说明 91e41f4b71Sopenharmony_ci| 函数成员 | 入参 | 出参 | 返回值 | 功能 | 92e41f4b71Sopenharmony_ci| - | - | - | - | - | 93e41f4b71Sopenharmony_ci| sendCccCmd | **cntlr**:结构体指针,核心层I3C控制器<br />**ccc**:传入的通用命令代码结构体指针 | **ccc**:传出的通用命令代码结构体指针 | HDF_STATUS相关状态|发送CCC(Common command Code,即通用命令代码)| 94e41f4b71Sopenharmony_ci| Transfer | **cntlr**:结构体指针,核心层I3C控制器<br />**msgs**:结构体指针,用户消息<br />**count**:int16_t,消息数量 | **msgs**:结构体指针,用户消息 | HDF_STATUS相关状态 | 使用I3C模式传递用户消息 | 95e41f4b71Sopenharmony_ci|i2cTransfer | **cntlr**:结构体指针,核心层I3C控制器<br />**msgs**:结构体指针,用户消息<br />**count**:int16_t,消息数量 | **msgs**:结构体指针,用户消息 | HDF_STATUS相关状态 | 使用I2C模式传递用户消息 | 96e41f4b71Sopenharmony_ci| setConfig | **cntlr**:结构体指针,核心层I3C控制器<br />**config**:控制器配置参数| 无 | HDF_STATUS相关状态 | 设置I3C控制器配置参数 | 97e41f4b71Sopenharmony_ci| getConfig | **cntlr**:结构体指针,核心层I3C控制器 | **config**:控制器配置参数 | HDF_STATUS相关状态 | 获取I3C控制器配置参数 | 98e41f4b71Sopenharmony_ci| requestIbi | **device**:结构体指针,核心层I3C设备 | 无 | HDF_STATUS相关状态 | 为I3C设备请求IBI(In-Bind Interrupt,即带内中断) | 99e41f4b71Sopenharmony_ci| freeIbi | **device**:结构体指针,核心层I3C设备 | 无 | HDF_STATUS相关状态 | 释放IBI | 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci### 开发步骤 <a name="9"></a> 102e41f4b71Sopenharmony_ci 103e41f4b71Sopenharmony_ciI3C模块适配包含以下五个步骤: 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ci- 实例化驱动入口 106e41f4b71Sopenharmony_ci 107e41f4b71Sopenharmony_ci - 实例化HdfDriverEntry结构体成员。 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ci - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 110e41f4b71Sopenharmony_ci 111e41f4b71Sopenharmony_ci- 配置属性文件 112e41f4b71Sopenharmony_ci 113e41f4b71Sopenharmony_ci - 在device_info.hcs文件中添加deviceNode描述。 114e41f4b71Sopenharmony_ci 115e41f4b71Sopenharmony_ci - 【可选】添加i3c_config.hcs器件属性文件。 116e41f4b71Sopenharmony_ci 117e41f4b71Sopenharmony_ci- 实例化I3C控制器对象 118e41f4b71Sopenharmony_ci 119e41f4b71Sopenharmony_ci - 初始化I3cCntlr成员。 120e41f4b71Sopenharmony_ci 121e41f4b71Sopenharmony_ci - 实例化I3cCntlr成员I3cMethod方法集合,其定义和成员函数说明见下文。 122e41f4b71Sopenharmony_ci 123e41f4b71Sopenharmony_ci- 注册中断处理子程序 124e41f4b71Sopenharmony_ci 125e41f4b71Sopenharmony_ci 为控制器注册中断处理程序,实现设备热接入和IBI(带内中断)功能。 126e41f4b71Sopenharmony_ci 127e41f4b71Sopenharmony_ci- 驱动调试 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的测试用例是否成功,数据能否传输等。 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci### 开发实例 132e41f4b71Sopenharmony_ci 133e41f4b71Sopenharmony_ci下方将以Hi3516DV300的虚拟驱动//drivers/hdf_core/framework/test/unittest/platform/virtual/i3c_virtual.c为示例,展示需要驱动适配者提供哪些内容来完整实现设备功能。 134e41f4b71Sopenharmony_ci 135e41f4b71Sopenharmony_ci1. 实例化驱动入口 136e41f4b71Sopenharmony_ci 驱动入口必须为HdfDriverEntry(在//drivers/hdf_core/framework/include/core/hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 137e41f4b71Sopenharmony_ci 138e41f4b71Sopenharmony_ci 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 139e41f4b71Sopenharmony_ci 140e41f4b71Sopenharmony_ci I3C驱动入口参考: 141e41f4b71Sopenharmony_ci 142e41f4b71Sopenharmony_ci >  **说明:**<br> 143e41f4b71Sopenharmony_ci > I3C控制器会出现很多个控制器挂接的情况,因而在HDF框架中首先会为此类型的控制器创建一个管理器对象,并同时对外发布一个管理器服务来统一处理外部访问。这样,用户需要打开某个控制器时,会先获取到管理器服务,然后管理器服务根据用户指定参数查找到指定控制器。 144e41f4b71Sopenharmony_ci > 145e41f4b71Sopenharmony_ci > I3C管理器服务的驱动由核心层实现,驱动适配者不需要关注这部分内容的实现,但在实现Init函数的时候需要调用核心层的I3cCntlrAdd函数,它会实现相应功能。 146e41f4b71Sopenharmony_ci 147e41f4b71Sopenharmony_ci ```c 148e41f4b71Sopenharmony_ci static struct HdfDriverEntry g_virtualI3cDriverEntry = { 149e41f4b71Sopenharmony_ci .moduleVersion = 1, 150e41f4b71Sopenharmony_ci .Init = VirtualI3cInit, 151e41f4b71Sopenharmony_ci .Release = VirtualI3cRelease, 152e41f4b71Sopenharmony_ci .moduleName = "virtual_i3c_driver", // 【必要且与hcs文件中的名字匹配】 153e41f4b71Sopenharmony_ci }; 154e41f4b71Sopenharmony_ci HDF_INIT(g_virtualI3cDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 155e41f4b71Sopenharmony_ci 156e41f4b71Sopenharmony_ci // 核心层i3c_core.c管理器服务的驱动入口 157e41f4b71Sopenharmony_ci struct HdfDriverEntry g_i3cManagerEntry = { 158e41f4b71Sopenharmony_ci .moduleVersion = 1, 159e41f4b71Sopenharmony_ci .Init = I3cManagerInit, 160e41f4b71Sopenharmony_ci .Release = I3cManagerRelease, 161e41f4b71Sopenharmony_ci .moduleName = "HDF_PLATFORM_I3C_MANAGER", // 这与device_info.hcs文件中device0对应 162e41f4b71Sopenharmony_ci }; 163e41f4b71Sopenharmony_ci HDF_INIT(g_i3cManagerEntry); 164e41f4b71Sopenharmony_ci ``` 165e41f4b71Sopenharmony_ci 166e41f4b71Sopenharmony_ci2. 配置属性文件 167e41f4b71Sopenharmony_ci 完成驱动入口注册之后,下一步请在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件中添加deviceNode信息,并在i3c_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于驱动适配者的驱动实现以及核心层I3cCntlr相关成员的默认值或限制范围有密切关系。 168e41f4b71Sopenharmony_ci 169e41f4b71Sopenharmony_ci 统一服务模式的特点是device_info.hcs文件中第一个设备节点必须为I3C管理器,其各项参数必须如表2设置: 170e41f4b71Sopenharmony_ci 171e41f4b71Sopenharmony_ci **表 2** device_info.hcs节点参数说明 172e41f4b71Sopenharmony_ci 173e41f4b71Sopenharmony_ci | 成员名 | 值 | 174e41f4b71Sopenharmony_ci | -------- | -------- | 175e41f4b71Sopenharmony_ci | policy | 驱动服务发布的策略,I3C管理器具体配置为0,表示驱动不需要发布服务 | 176e41f4b71Sopenharmony_ci | priority | 驱动启动优先级(0-200),值越大优先级越低。I3C管理器具体配置为52 | 177e41f4b71Sopenharmony_ci | permission | 驱动创建设备节点权限,I3C管理器具体配置为0664 | 178e41f4b71Sopenharmony_ci | moduleName | 驱动名称,I3C管理器固定为HDF_PLATFORM_I3C_MANAGER | 179e41f4b71Sopenharmony_ci | serviceName | 驱动对外发布服务的名称,I3C管理器服务名设置为HDF_PLATFORM_I3C_MANAGER | 180e41f4b71Sopenharmony_ci | deviceMatchAttr | 驱动私有数据匹配的关键字,I3C管理器没有使用,可忽略 | 181e41f4b71Sopenharmony_ci 182e41f4b71Sopenharmony_ci 从第二个节点开始配置具体I3C控制器信息,此节点并不表示某一路I3C控制器,而是代表一个资源性质设备,用于描述一类I3C控制器的信息。本例只有一个I3C控制器,如有多个控制器,则需要在device_info.hcs文件增加deviceNode信息,以及在i3c_config文件中增加对应的器件属性。 183e41f4b71Sopenharmony_ci 184e41f4b71Sopenharmony_ci - device_info.hcs配置参考 185e41f4b71Sopenharmony_ci 186e41f4b71Sopenharmony_ci ```c 187e41f4b71Sopenharmony_ci root { 188e41f4b71Sopenharmony_ci device_i3c :: device { 189e41f4b71Sopenharmony_ci device0 :: deviceNode { 190e41f4b71Sopenharmony_ci policy = 0; 191e41f4b71Sopenharmony_ci priority = 52; 192e41f4b71Sopenharmony_ci permission = 0644; 193e41f4b71Sopenharmony_ci serviceName = "HDF_PLATFORM_I3C_MANAGER"; 194e41f4b71Sopenharmony_ci moduleName = "HDF_PLATFORM_I3C_MANAGER"; 195e41f4b71Sopenharmony_ci } 196e41f4b71Sopenharmony_ci } 197e41f4b71Sopenharmony_ci i3c_virtual :: deviceNode { 198e41f4b71Sopenharmony_ci policy = 0; // 等于0,不需要发布服务。 199e41f4b71Sopenharmony_ci priority = 56; // 驱动启动优先级。 200e41f4b71Sopenharmony_ci permission = 0644; // 驱动创建设备节点权限。 201e41f4b71Sopenharmony_ci moduleName = "virtual_i3c_driver"; // 【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致。 202e41f4b71Sopenharmony_ci serviceName = "VIRTUAL_I3C_DRIVER"; // 【必要】驱动对外发布服务的名称,必须唯一。 203e41f4b71Sopenharmony_ci deviceMatchAttr = "virtual_i3c"; // 【必要】用于配置控制器私有数据,要与i3c_config.hcs中对应控制器保持一致。 204e41f4b71Sopenharmony_ci } // 具体的控制器信息在i3c_config.hcs中。 205e41f4b71Sopenharmony_ci } 206e41f4b71Sopenharmony_ci ``` 207e41f4b71Sopenharmony_ci 208e41f4b71Sopenharmony_ci - i3c_config.hcs 配置参考 209e41f4b71Sopenharmony_ci 210e41f4b71Sopenharmony_ci ```c 211e41f4b71Sopenharmony_ci root { 212e41f4b71Sopenharmony_ci platform { 213e41f4b71Sopenharmony_ci i3c_config { 214e41f4b71Sopenharmony_ci match_attr = "virtual_i3c"; // 【必要】需要和device_info.hcs中的deviceMatchAttr值一致 215e41f4b71Sopenharmony_ci template i3c_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省。 216e41f4b71Sopenharmony_ci busId = 0; // 【必要】i3c总线号 217e41f4b71Sopenharmony_ci busMode = 0x0; // 总线模式,0x0:纯净;0x1:混合高速;0x2:混合受限;0x3:混合低速。 218e41f4b71Sopenharmony_ci regBasePhy = 0x120b0000; // 【必要】物理基地址 219e41f4b71Sopenharmony_ci regSize = 0xd1; // 【必要】寄存器位宽 220e41f4b71Sopenharmony_ci IrqNum = 20; // 【必要】中断号 221e41f4b71Sopenharmony_ci i3cMaxRate = 12900000; // 【可选】i3c模式最大时钟速率 222e41f4b71Sopenharmony_ci i3cRate = 12500000; // 【可选】i3c模式时钟速率 223e41f4b71Sopenharmony_ci i2cFmRate = 1000000; // 【可选】i2c FM模式时钟速率 224e41f4b71Sopenharmony_ci i2cFmPlusRate = 400000; // 【可选】i2c FM+模式时钟速率 225e41f4b71Sopenharmony_ci } 226e41f4b71Sopenharmony_ci controller_0 :: i3c_controller { 227e41f4b71Sopenharmony_ci busId = 18; 228e41f4b71Sopenharmony_ci IrqNum = 20; 229e41f4b71Sopenharmony_ci } 230e41f4b71Sopenharmony_ci } 231e41f4b71Sopenharmony_ci } 232e41f4b71Sopenharmony_ci } 233e41f4b71Sopenharmony_ci ``` 234e41f4b71Sopenharmony_ci 235e41f4b71Sopenharmony_ci 需要注意的是,新增i3c_config.hcs配置文件后,必须在对应的hdf.hcs文件中包含i3c_config.hcs所在路径信息,否则配置文件无法生效。 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_ci3. 实例化I3C控制器对象 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci 配置属性文件完成后,要以核心层I3cCntlr对象的初始化为核心,包括驱动适配者自定义结构体(传递参数和数据),实例化I3cCntlr成员I3cMethod(让用户可以通过接口来调用驱动底层函数)。 240e41f4b71Sopenharmony_ci 241e41f4b71Sopenharmony_ci 此步骤需要通过实现HdfDriverEntry成员函数(Bind,Init,Release)来完成。 242e41f4b71Sopenharmony_ci 243e41f4b71Sopenharmony_ci I3cCntlr成员钩子函数结构体I3cMethod的实例化,I3cLockMethod钩子函数结构体本例未实现,若要实例化,可参考I2C驱动开发。 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci - 自定义结构体参考 246e41f4b71Sopenharmony_ci 247e41f4b71Sopenharmony_ci >  **说明:**<br> 248e41f4b71Sopenharmony_ci > 从驱动的角度看,自定义结构体是参数和数据的载体,而且i3c_config.hcs文件中的数值会被HDF读入并通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层I3cCntlr对象,例如设备号、总线号等。 249e41f4b71Sopenharmony_ci 250e41f4b71Sopenharmony_ci ```c 251e41f4b71Sopenharmony_ci struct VirtualI3cCntlr { 252e41f4b71Sopenharmony_ci struct I3cCntlr cntlr; // 【必要】是核心层控制对象,具体描述见下面。 253e41f4b71Sopenharmony_ci volatile unsigned char *regBase; // 【必要】寄存器基地址 254e41f4b71Sopenharmony_ci uint32_t regBasePhy; // 【必要】寄存器物理基地址 255e41f4b71Sopenharmony_ci uint32_t regSize; // 【必要】寄存器位宽 256e41f4b71Sopenharmony_ci uint16_t busId; // 【必要】设备号 257e41f4b71Sopenharmony_ci uint16_t busMode; 258e41f4b71Sopenharmony_ci uint16_t IrqNum; 259e41f4b71Sopenharmony_ci uint32_t i3cMaxRate; 260e41f4b71Sopenharmony_ci uint32_t i3cRate; 261e41f4b71Sopenharmony_ci uint32_t i2cFmRate; 262e41f4b71Sopenharmony_ci uint32_t i2cFmPlusRate; 263e41f4b71Sopenharmony_ci }; 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci // I3cCntlr是核心层控制器结构体,其中的成员在Init函数中被赋值。 266e41f4b71Sopenharmony_ci struct I3cCntlr { 267e41f4b71Sopenharmony_ci OsalSpinlock lock; 268e41f4b71Sopenharmony_ci void *owner; 269e41f4b71Sopenharmony_ci int16_t busId; 270e41f4b71Sopenharmony_ci struct I3cConfig config; 271e41f4b71Sopenharmony_ci uint16_t addrSlot[(I3C_ADDR_MAX + 1) / ADDRS_PER_UINT16]; 272e41f4b71Sopenharmony_ci struct I3cIbiInfo *ibiSlot[I3C_IBI_MAX]; 273e41f4b71Sopenharmony_ci const struct I3cMethod *ops; 274e41f4b71Sopenharmony_ci const struct I3cLockMethod *lockOps; 275e41f4b71Sopenharmony_ci void *priv; 276e41f4b71Sopenharmony_ci }; 277e41f4b71Sopenharmony_ci ``` 278e41f4b71Sopenharmony_ci 279e41f4b71Sopenharmony_ci - Init函数开发参考 280e41f4b71Sopenharmony_ci 281e41f4b71Sopenharmony_ci **入参:** 282e41f4b71Sopenharmony_ci 283e41f4b71Sopenharmony_ci HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。 284e41f4b71Sopenharmony_ci 285e41f4b71Sopenharmony_ci **返回值:** 286e41f4b71Sopenharmony_ci 287e41f4b71Sopenharmony_ci HDF_STATUS相关状态(表3为部分展示,如需使用其他状态,可参考//drivers/hdf_core/interfaces/inner_api/utils/hdf_base.h中HDF_STATUS定义)。 288e41f4b71Sopenharmony_ci 289e41f4b71Sopenharmony_ci **表 3** HDF_STATUS相关状态说明 290e41f4b71Sopenharmony_ci 291e41f4b71Sopenharmony_ci | 状态(值) | 问题描述 | 292e41f4b71Sopenharmony_ci | -------- | -------- | 293e41f4b71Sopenharmony_ci | HDF_ERR_INVALID_OBJECT | 控制器对象非法 | 294e41f4b71Sopenharmony_ci | HDF_ERR_INVALID_PARAM | 参数非法 | 295e41f4b71Sopenharmony_ci | HDF_ERR_MALLOC_FAIL | 内存分配失败 | 296e41f4b71Sopenharmony_ci | HDF_ERR_IO | I/O错误 | 297e41f4b71Sopenharmony_ci | HDF_SUCCESS | 传输成功 | 298e41f4b71Sopenharmony_ci | HDF_FAILURE | 传输失败 | 299e41f4b71Sopenharmony_ci 300e41f4b71Sopenharmony_ci **函数说明:** 301e41f4b71Sopenharmony_ci 302e41f4b71Sopenharmony_ci 初始化自定义结构体对象,初始化I3cCntlr成员,调用核心层I3cCntlrAdd函数。 303e41f4b71Sopenharmony_ci 304e41f4b71Sopenharmony_ci ```c 305e41f4b71Sopenharmony_ci static int32_t VirtualI3cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) 306e41f4b71Sopenharmony_ci { 307e41f4b71Sopenharmony_ci int32_t ret; 308e41f4b71Sopenharmony_ci struct VirtualI3cCntlr *virtual = NULL; // 【必要】自定义结构体对象 309e41f4b71Sopenharmony_ci (void)device; 310e41f4b71Sopenharmony_ci 311e41f4b71Sopenharmony_ci virtual = (struct VirtualI3cCntlr *)OsalMemCalloc(sizeof(*virtual)); // 【必要】内存分配 312e41f4b71Sopenharmony_ci if (virtual == NULL) { 313e41f4b71Sopenharmony_ci HDF_LOGE("%s: Malloc virtual fail!", __func__); 314e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 315e41f4b71Sopenharmony_ci } 316e41f4b71Sopenharmony_ci 317e41f4b71Sopenharmony_ci ret = VirtualI3cReadDrs(virtual, node); // 【必要】将i3c_config文件的默认值填充到结构体中,函数定义见下方 318e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 319e41f4b71Sopenharmony_ci HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); 320e41f4b71Sopenharmony_ci goto __ERR__; 321e41f4b71Sopenharmony_ci } 322e41f4b71Sopenharmony_ci ...... 323e41f4b71Sopenharmony_ci virtual->regBase = OsalIoRemap(virtual->regBasePhy, virtual->regSize); // 【必要】地址映射 324e41f4b71Sopenharmony_ci ret = OsalRegisterIrq(hi35xx->softIrqNum, OSAL_IRQF_TRIGGER_NONE, I3cIbiHandle, "I3C", virtual); //【必要】注册中断程序 325e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 326e41f4b71Sopenharmony_ci HDF_LOGE("%s: register irq failed!", __func__); 327e41f4b71Sopenharmony_ci return ret; 328e41f4b71Sopenharmony_ci } 329e41f4b71Sopenharmony_ci ...... 330e41f4b71Sopenharmony_ci VirtualI3cCntlrInit(virtual); // 【必要】I3C设备的初始化 331e41f4b71Sopenharmony_ci virtual->cntlr.priv = (void *)node; // 【必要】存储设备属性 332e41f4b71Sopenharmony_ci virtual->cntlr.busId = virtual->busId; // 【必要】初始化I3cCntlr成员 333e41f4b71Sopenharmony_ci virtual->cntlr.ops = &g_method; // 【必要】I3cMethod的实例化对象的挂载 334e41f4b71Sopenharmony_ci (void)OsalSpinInit(&virtual->spin); 335e41f4b71Sopenharmony_ci ret = I3cCntlrAdd(&virtual->cntlr); // 【必要且重要】调用此函数将控制器添加至核心,返回成功信号后驱动才完全接入平台核心层。 336e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 337e41f4b71Sopenharmony_ci HDF_LOGE("%s: add i3c controller failed! ret = %d", __func__, ret); 338e41f4b71Sopenharmony_ci (void)OsalSpinDestroy(&virtual->spin); 339e41f4b71Sopenharmony_ci goto __ERR__; 340e41f4b71Sopenharmony_ci } 341e41f4b71Sopenharmony_ci 342e41f4b71Sopenharmony_ci return HDF_SUCCESS; 343e41f4b71Sopenharmony_ci __ERR__: // 若控制器添加失败,需要执行去初始化相关函数。 344e41f4b71Sopenharmony_ci if (virtual != NULL) { 345e41f4b71Sopenharmony_ci OsalMemFree(virtual); 346e41f4b71Sopenharmony_ci virtual = NULL; 347e41f4b71Sopenharmony_ci } 348e41f4b71Sopenharmony_ci 349e41f4b71Sopenharmony_ci return ret; 350e41f4b71Sopenharmony_ci } 351e41f4b71Sopenharmony_ci 352e41f4b71Sopenharmony_ci static int32_t VirtualI3cInit(struct HdfDeviceObject *device) 353e41f4b71Sopenharmony_ci { 354e41f4b71Sopenharmony_ci int32_t ret; 355e41f4b71Sopenharmony_ci const struct DeviceResourceNode *childNode = NULL; 356e41f4b71Sopenharmony_ci 357e41f4b71Sopenharmony_ci if (device == NULL || device->property == NULL) { 358e41f4b71Sopenharmony_ci HDF_LOGE("%s: device or property is NULL", __func__); 359e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 360e41f4b71Sopenharmony_ci } 361e41f4b71Sopenharmony_ci 362e41f4b71Sopenharmony_ci DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { 363e41f4b71Sopenharmony_ci ret = VirtualI3cParseAndInit(device, childNode); 364e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 365e41f4b71Sopenharmony_ci break; 366e41f4b71Sopenharmony_ci } 367e41f4b71Sopenharmony_ci } 368e41f4b71Sopenharmony_ci 369e41f4b71Sopenharmony_ci return ret; 370e41f4b71Sopenharmony_ci } 371e41f4b71Sopenharmony_ci 372e41f4b71Sopenharmony_ci static int32_t VirtualI3cReadDrs(struct VirtualI3cCntlr *virtual, const struct DeviceResourceNode *node) 373e41f4b71Sopenharmony_ci { 374e41f4b71Sopenharmony_ci struct DeviceResourceIface *drsOps = NULL; 375e41f4b71Sopenharmony_ci 376e41f4b71Sopenharmony_ci // 获取drsOps方法 377e41f4b71Sopenharmony_ci drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 378e41f4b71Sopenharmony_ci if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) { 379e41f4b71Sopenharmony_ci HDF_LOGE("%s: Invalid drs ops fail!", __func__); 380e41f4b71Sopenharmony_ci return HDF_FAILURE; 381e41f4b71Sopenharmony_ci } 382e41f4b71Sopenharmony_ci // 将配置参数依次读出,并填充至结构体中 383e41f4b71Sopenharmony_ci if (drsOps->GetUint16(node, "busId", &virtual->busId, 0) != HDF_SUCCESS) { 384e41f4b71Sopenharmony_ci HDF_LOGE("%s: Read busId fail!", __func__); 385e41f4b71Sopenharmony_ci return HDF_ERR_IO; 386e41f4b71Sopenharmony_ci } 387e41f4b71Sopenharmony_ci if (drsOps->GetUint16(node, "busMode", &virtual->busMode, 0) != HDF_SUCCESS) { 388e41f4b71Sopenharmony_ci HDF_LOGE("%s: Read busMode fail!", __func__); 389e41f4b71Sopenharmony_ci return HDF_ERR_IO; 390e41f4b71Sopenharmony_ci } 391e41f4b71Sopenharmony_ci if (drsOps->GetUint16(node, "IrqNum", &virtual->IrqNum, 0) != HDF_SUCCESS) { 392e41f4b71Sopenharmony_ci HDF_LOGE("%s: Read IrqNum fail!", __func__); 393e41f4b71Sopenharmony_ci return HDF_ERR_IO; 394e41f4b71Sopenharmony_ci } 395e41f4b71Sopenharmony_ci ...... 396e41f4b71Sopenharmony_ci return HDF_SUCCESS; 397e41f4b71Sopenharmony_ci } 398e41f4b71Sopenharmony_ci ``` 399e41f4b71Sopenharmony_ci 400e41f4b71Sopenharmony_ci - Release函数开发参考 401e41f4b71Sopenharmony_ci 402e41f4b71Sopenharmony_ci **入参:** 403e41f4b71Sopenharmony_ci 404e41f4b71Sopenharmony_ci HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。 405e41f4b71Sopenharmony_ci 406e41f4b71Sopenharmony_ci **返回值:** 407e41f4b71Sopenharmony_ci 408e41f4b71Sopenharmony_ci 无。 409e41f4b71Sopenharmony_ci 410e41f4b71Sopenharmony_ci **函数说明:** 411e41f4b71Sopenharmony_ci 412e41f4b71Sopenharmony_ci 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。 413e41f4b71Sopenharmony_ci 414e41f4b71Sopenharmony_ci >  **说明:**<br> 415e41f4b71Sopenharmony_ci > 所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 416e41f4b71Sopenharmony_ci 417e41f4b71Sopenharmony_ci ```c 418e41f4b71Sopenharmony_ci static void VirtualI3cRemoveByNode(const struct DeviceResourceNode *node) 419e41f4b71Sopenharmony_ci { 420e41f4b71Sopenharmony_ci int32_t ret; 421e41f4b71Sopenharmony_ci int16_t busId; 422e41f4b71Sopenharmony_ci struct I3cCntlr *cntlr = NULL; 423e41f4b71Sopenharmony_ci struct VirtualI3cCntlr *virtual = NULL; 424e41f4b71Sopenharmony_ci struct DeviceResourceIface *drsOps = NULL; 425e41f4b71Sopenharmony_ci 426e41f4b71Sopenharmony_ci drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 427e41f4b71Sopenharmony_ci if (drsOps == NULL || drsOps->GetUint32 == NULL) { 428e41f4b71Sopenharmony_ci HDF_LOGE("%s: invalid drs ops fail!", __func__); 429e41f4b71Sopenharmony_ci return; 430e41f4b71Sopenharmony_ci } 431e41f4b71Sopenharmony_ci 432e41f4b71Sopenharmony_ci ret = drsOps->GetUint16(node, "busId", (uint16_t *)&busId, 0); 433e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 434e41f4b71Sopenharmony_ci HDF_LOGE("%s: read busId fail!", __func__); 435e41f4b71Sopenharmony_ci return; 436e41f4b71Sopenharmony_ci } 437e41f4b71Sopenharmony_ci ...... 438e41f4b71Sopenharmony_ci // 可以调用I3cCntlrGet函数通过设备的cntlrNum获取I3cCntlr对象,以及调用I3cCntlrRemove函数来释放I3cCntlr对象的内容。 439e41f4b71Sopenharmony_ci cntlr = I3cCntlrGet(busId); 440e41f4b71Sopenharmony_ci if (cntlr != NULL && cntlr->priv == node) { 441e41f4b71Sopenharmony_ci I3cCntlrPut(cntlr); 442e41f4b71Sopenharmony_ci I3cCntlrRemove(cntlr); // 【必要】主要是从管理器驱动那边移除I3cCntlr对象 443e41f4b71Sopenharmony_ci virtual = (struct VirtualI3cCntlr *)cntlr; // 【必要】通过强制转换获取自定义的对象并进行release操作 444e41f4b71Sopenharmony_ci (void)OsalSpinDestroy(&virtual->spin); 445e41f4b71Sopenharmony_ci OsalMemFree(virtual); 446e41f4b71Sopenharmony_ci } 447e41f4b71Sopenharmony_ci return; 448e41f4b71Sopenharmony_ci } 449e41f4b71Sopenharmony_ci 450e41f4b71Sopenharmony_ci static void VirtualI3cRelease(struct HdfDeviceObject *device) 451e41f4b71Sopenharmony_ci { 452e41f4b71Sopenharmony_ci const struct DeviceResourceNode *childNode = NULL; 453e41f4b71Sopenharmony_ci 454e41f4b71Sopenharmony_ci HDF_LOGI("%s: enter", __func__); 455e41f4b71Sopenharmony_ci 456e41f4b71Sopenharmony_ci if (device == NULL || device->property == NULL) { 457e41f4b71Sopenharmony_ci HDF_LOGE("%s: device or property is NULL", __func__); 458e41f4b71Sopenharmony_ci return; 459e41f4b71Sopenharmony_ci } 460e41f4b71Sopenharmony_ci ...... 461e41f4b71Sopenharmony_ci // 遍历、解析i3c_config.hcs中的所有配置节点,并分别进行release操作 462e41f4b71Sopenharmony_ci DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { 463e41f4b71Sopenharmony_ci VirtualI3cRemoveByNode(childNode); //函数定义如上 464e41f4b71Sopenharmony_ci } 465e41f4b71Sopenharmony_ci } 466e41f4b71Sopenharmony_ci ``` 467e41f4b71Sopenharmony_ci 468e41f4b71Sopenharmony_ci4. 注册中断处理子程序 469e41f4b71Sopenharmony_ci 470e41f4b71Sopenharmony_ci 在中断处理程序中通过判断中断产生的地址,实现热接入、IBI等操作。 471e41f4b71Sopenharmony_ci 472e41f4b71Sopenharmony_ci ```c 473e41f4b71Sopenharmony_ci static int32_t VirtualI3cReservedAddrWorker(struct VirtualI3cCntlr *virtual, uint16_t addr) 474e41f4b71Sopenharmony_ci { 475e41f4b71Sopenharmony_ci (void)virtual; 476e41f4b71Sopenharmony_ci switch (addr) { 477e41f4b71Sopenharmony_ci case I3C_HOT_JOIN_ADDR: 478e41f4b71Sopenharmony_ci VirtualI3cHotJoin(virtual); 479e41f4b71Sopenharmony_ci break; 480e41f4b71Sopenharmony_ci case I3C_RESERVED_ADDR_7H3E: 481e41f4b71Sopenharmony_ci case I3C_RESERVED_ADDR_7H5E: 482e41f4b71Sopenharmony_ci case I3C_RESERVED_ADDR_7H6E: 483e41f4b71Sopenharmony_ci case I3C_RESERVED_ADDR_7H76: 484e41f4b71Sopenharmony_ci case I3C_RESERVED_ADDR_7H7A: 485e41f4b71Sopenharmony_ci case I3C_RESERVED_ADDR_7H7C: 486e41f4b71Sopenharmony_ci case I3C_RESERVED_ADDR_7H7F: 487e41f4b71Sopenharmony_ci // 广播地址单比特错误的所有情形 488e41f4b71Sopenharmony_ci HDF_LOGW("%s: broadcast Address single bit error!", __func__); 489e41f4b71Sopenharmony_ci break; 490e41f4b71Sopenharmony_ci default: 491e41f4b71Sopenharmony_ci HDF_LOGD("%s: Reserved address which is not supported!", __func__); 492e41f4b71Sopenharmony_ci break; 493e41f4b71Sopenharmony_ci } 494e41f4b71Sopenharmony_ci 495e41f4b71Sopenharmony_ci return HDF_SUCCESS; 496e41f4b71Sopenharmony_ci } 497e41f4b71Sopenharmony_ci 498e41f4b71Sopenharmony_ci static int32_t I3cIbiHandle(uint32_t irq, void *data) 499e41f4b71Sopenharmony_ci { 500e41f4b71Sopenharmony_ci struct VirtualI3cCntlr *virtual = NULL; 501e41f4b71Sopenharmony_ci struct I3cDevice *device = NULL; 502e41f4b71Sopenharmony_ci uint16_t ibiAddr; 503e41f4b71Sopenharmony_ci char *testStr = "Hello I3C!"; 504e41f4b71Sopenharmony_ci 505e41f4b71Sopenharmony_ci (void)irq; 506e41f4b71Sopenharmony_ci if (data == NULL) { 507e41f4b71Sopenharmony_ci HDF_LOGW("%s: data is NULL!", __func__); 508e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 509e41f4b71Sopenharmony_ci } 510e41f4b71Sopenharmony_ci virtual = (struct VirtualI3cCntlr *)data; 511e41f4b71Sopenharmony_ci // 【必要】获取产生中断的地址,使用CHECK_RESERVED_ADDR宏判断该地址是否为I3C保留地址。 512e41f4b71Sopenharmony_ci ibiAddr = VirtualI3cGetIbiAddr(); 513e41f4b71Sopenharmony_ci if (CHECK_RESERVED_ADDR(ibiAddr) == I3C_ADDR_RESERVED) { 514e41f4b71Sopenharmony_ci HDF_LOGD("%s: Calling VirtualI3cResAddrWorker...", __func__); 515e41f4b71Sopenharmony_ci return VirtualI3cReservedAddrWorker(virtual, ibiAddr); 516e41f4b71Sopenharmony_ci } else { 517e41f4b71Sopenharmony_ci HDF_LOGD("%s: Calling I3cCntlrIbiCallback...", __func__); 518e41f4b71Sopenharmony_ci device = GetDeviceByAddr(&virtual->cntlr, ibiAddr); 519e41f4b71Sopenharmony_ci if (device == NULL) { 520e41f4b71Sopenharmony_ci HDF_LOGE("func:%s device is NULL!",__func__); 521e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 522e41f4b71Sopenharmony_ci } 523e41f4b71Sopenharmony_ci if (device->ibi->payload > VIRTUAL_I3C_TEST_STR_LEN) { 524e41f4b71Sopenharmony_ci // 将字符串"Hello I3C!"放入IBI缓冲区内 525e41f4b71Sopenharmony_ci *device->ibi->data = *testStr; 526e41f4b71Sopenharmony_ci } 527e41f4b71Sopenharmony_ci // 根据产生IBI的I3C设备调用IBI回调函数 528e41f4b71Sopenharmony_ci return I3cCntlrIbiCallback(device); 529e41f4b71Sopenharmony_ci } 530e41f4b71Sopenharmony_ci 531e41f4b71Sopenharmony_ci return HDF_SUCCESS; 532e41f4b71Sopenharmony_ci } 533e41f4b71Sopenharmony_ci ``` 534e41f4b71Sopenharmony_ci 535e41f4b71Sopenharmony_ci5. 驱动调试 536e41f4b71Sopenharmony_ci 537e41f4b71Sopenharmony_ci 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的测试用例是否成功,数据能否传输等。 538