【鸿蒙OS开发入门】18 - HDF驱动子系统:加速度计传感器 Driver层驱动代码分析
【鸿蒙OS开发入门】18 - HDF驱动子系统:加速度计传感器 Driver层代码分析
- 一、如何添加速度计传感器驱动代码(代码、编译、配置)
- 1、驱动代码实现
- 2、驱动编译配置
- 2.1 linux 编译宏控配置
- 2.2 liteos 编译宏控配置
- 3、设备配置描述
- 二、加速度计传感器Driver层代码逻辑分析
- 2.1 driverLoader->LoadNode()方法: HdfDriverLoaderLoadNode() 加载驱动 bind() 方法
- 2.2 driverEntry->Bind()方法: Bmi160BindDriver() 分配并初始化驱动结构体g_bmi160DrvData
- 2.3 device->super.Attach()方法: HdfDeviceAttach() 开始加载驱动.Init 方法探测驱动设备
- 2.4 driverEntry->Init方法:
本系列文章汇总:
- 《【鸿蒙OS开发入门】01 - 搭建Ubuntu虚拟机开发环境》
- 《【鸿蒙OS开发入门】02 - 启动流程代码分析之Uboot 第一阶段:之解压并引导加载u-boot.bin》
- 《【鸿蒙OS开发入门】03 - 启动流程代码分析之Uboot 第二阶段:之board_init初始化》
- 《【鸿蒙OS开发入门】04 - 启动流程代码分析之Uboot 第二阶段:之U_BOOT_CMD原理》
- 《【鸿蒙OS开发入门】05 - 启动流程代码分析之Uboot 第二阶段:之bootm引导加载Kernel OS》
- 《【鸿蒙OS开发入门】06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核》
- 《【鸿蒙OS开发入门】07 - 安装docker环境编译openharmony 2.0代码》
- 《【鸿蒙OS开发入门】08 - 启动流程代码分析之KernelOS:之启动 liteos_a 内核》
- 《【鸿蒙OS开发入门】09 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 中do_basic_setup()所干的大事》
- 《【鸿蒙OS开发入门】10 - 启动流程代码分析之第一个用户态进程:init 进程》
- 《【鸿蒙OS开发入门】11 - 启动流程代码分析之第一个用户态进程:init 进程 之 Services简介》
- 《【鸿蒙OS开发入门】12 - 启动流程代码分析之第一个用户态进程:init 进程 之 pre-init 任务详解》
- 《【鸿蒙OS开发入门】13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解》
- 《【鸿蒙OS开发入门】14 - 启动流程代码分析之第一个用户态进程:init 进程 之 post-init 任务详解》
- 《【鸿蒙OS开发入门】15 - 启动流程代码分析之第一个用户态进程:init 进程 之 StartParamService源码分析 及 setparam、getparam代码分析》
- 《【鸿蒙OS开发入门】16 - 重头搭建Ubuntu新环境编译OpenHarmony 3.0 LTS》
- 《【鸿蒙OS开发入门】17 - HDF驱动子系统:hdf_devmgr服务 驱动框架管理模块源码分析》
- 《【鸿蒙OS开发入门】18 - HDF驱动子系统:加速度计传感器 Driver层驱动代码分析》
之所以选择加速度计传感器来作为首篇驱动分析,主要是因为官方文档有对它介绍,《SENSOR》,
本文就参考着官方文档,来学习下加速度计传感器的驱动逻辑。
参考官方文档,先来上一张Sensor驱动模型图:
从上面Sensor
驱动模型图,从下往上,按我的理解,我们大致可以分为三层:
Hardware
层: 这一层是实实在在的物理器件,比如加速度计、陀螺仪等。Platform IF
层: 这一层主要是提供与物理器件的交互方法,比如I2C、SPI等总线驱动。Driver
层:这一层的核心就是各个驱动的struct HdfDriverEntry
结构体,在结构体中封装了相关sensor的具体实现逻辑。HDI
层(Hardware Driver Interface
):这一层,主要是对所有sensor操作方法的封装,给上层app提供操作接口。
本文重点分析的就是加速度计传感器的Driver层代码实现。
好,废话不多说,先来看代码吧。
一、如何添加速度计传感器驱动代码(代码、编译、配置)
1、驱动代码实现
# drivers\framework\model\sensor\driver\chipset\accel\accel_bmi160.cstatic int32_t ReadBmi160RawData(struct SensorCfgData *data, struct AccelData *rawData, int64_t *timestamp) { }
int32_t ReadBmi160Data(struct SensorCfgData *data){ }
static int32_t InitBmi160(struct SensorCfgData *data){ }
static int32_t InitAccelPreConfig(void){ }
static int32_t DispatchBMI160(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply){ }int32_t Bmi160BindDriver(struct HdfDeviceObject *device){ } // 加速度计传感器绑定函数
int32_t Bmi160InitDriver(struct HdfDeviceObject *device){ } // 加速度计传感器初始化函数
void Bmi160ReleaseDriver(struct HdfDeviceObject *device){ } // 加速度计传感器资源释放函数// 注册加速度计传感器入口数据结构体对象
struct HdfDriverEntry g_accelBmi160DevEntry = {.moduleVersion = 1, // 加速度计传感器模块版本号.moduleName = "HDF_SENSOR_ACCEL_BMI160", // 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样.Bind = Bmi160BindDriver, // 加速度计传感器绑定函数.Init = Bmi160InitDriver, // 加速度计传感器初始化函数.Release = Bmi160ReleaseDriver, // 加速度计传感器资源释放函数
};// 调用HDF_INIT将驱动入口注册到HDF框架中,
// 在加载驱动时HDF框架会先调用Bind函数, 再调用Init函数加载该驱动,
// 当Init调用异常时,HDF框架会调用Release释放驱动资源并退出
HDF_INIT(g_accelBmi160DevEntry);
2、驱动编译配置
2.1 linux 编译宏控配置
如果内核跑的是linux
,那宏控配置主要是在Kconfig
中:
# drivers\adapter\khdf\linux\model\sensor\Kconfigconfig DRIVERS_HDF_SENSOR_ACCELbool "Enable HDF accel sensor driver"default ndepends on DRIVERS_HDF_SENSORhelpAnswer Y to enable HDF accel sensor driver.
config DRIVERS_HDF_SENSOR_ACCEL_BMI160bool "Enable HDF accel sensor driver"default ndepends on DRIVERS_HDF_SENSOR_ACCELhelpAnswer Y to enable HDF accel bmi160 sensor driver.
Makefile
来控制相应的编译规则:
# drivers\adapter\khdf\linux\model\sensor\MakefileSENSOR_ROOT_DIR = ../../../../../framework/model/sensor/driverobj-$(CONFIG_DRIVERS_HDF_SENSOR) += \$(SENSOR_ROOT_DIR)/common/src/sensor_config_controller.o \$(SENSOR_ROOT_DIR)/common/src/sensor_config_parser.o \$(SENSOR_ROOT_DIR)/common/src/sensor_device_manager.o \$(SENSOR_ROOT_DIR)/common/src/sensor_platform_if.o obj-$(CONFIG_DRIVERS_HDF_SENSOR_ACCEL) += $(SENSOR_ROOT_DIR)/accel/sensor_accel_driver.oobj-$(CONFIG_DRIVERS_HDF_SENSOR_ACCEL_BMI160) += $(SENSOR_ROOT_DIR)/chipset/accel/accel_bmi160.o
2.2 liteos 编译宏控配置
如果内核跑的是liteos
,则是由BUILD.gn、makefile、Kconfig共同控制:
# drivers\adapter\khdf\liteos\model\sensor\BUILD.gnimport("//drivers/adapter/khdf/liteos/hdf.gni")module_switch = defined(LOSCFG_DRIVERS_HDF_SENSOR)
module_name = "hdf_sensor_driver"
hdf_driver(module_name) {FRAMEWORKS_SENSOR_ROOT = "$HDF_FRAMEWORKS_PATH/model/sensor/driver"sources = ["$FRAMEWORKS_SENSOR_ROOT/common/src/sensor_config_controller.c","$FRAMEWORKS_SENSOR_ROOT/common/src/sensor_config_parser.c","$FRAMEWORKS_SENSOR_ROOT/common/src/sensor_device_manager.c","$FRAMEWORKS_SENSOR_ROOT/common/src/sensor_platform_if.c",]if (defined(LOSCFG_DRIVERS_HDF_SENSOR_ACCEL)) {sources += [ "$FRAMEWORKS_SENSOR_ROOT/accel/sensor_accel_driver.c" ]}if (defined(LOSCFG_DRIVERS_HDF_SENSOR_ACCEL_BMI160)) {sources += [ "$FRAMEWORKS_SENSOR_ROOT/chipset/accel/accel_bmi160.c" ]}include_dirs = ["$FRAMEWORKS_SENSOR_ROOT/include","$FRAMEWORKS_SENSOR_ROOT/common/include","$FRAMEWORKS_SENSOR_ROOT/accel","$FRAMEWORKS_SENSOR_ROOT/chipset/accel",]
}
Makefile
内容如下:
# drivers\adapter\khdf\liteos\model\sensor\Makefileinclude $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk
MODULE_NAME := hdf_sensor_driverFRAMEWORKS_SENSOR_ROOT = $(LITEOSTOPDIR)/../../drivers/framework/model/sensor/driverLOCAL_INCLUDE := $(FRAMEWORKS_SENSOR_ROOT)/include \$(FRAMEWORKS_SENSOR_ROOT)/common/include \$(FRAMEWORKS_SENSOR_ROOT)/accel LOCAL_SRCS += $(FRAMEWORKS_SENSOR_ROOT)/common/src/sensor_config_controller.c \$(FRAMEWORKS_SENSOR_ROOT)/common/src/sensor_config_parser.c \$(FRAMEWORKS_SENSOR_ROOT)/common/src/sensor_device_manager.c \$(FRAMEWORKS_SENSOR_ROOT)/common/src/sensor_platform_if.cifeq ($(LOSCFG_DRIVERS_HDF_SENSOR_ACCEL), y)
LOCAL_SRCS += $(FRAMEWORKS_SENSOR_ROOT)/accel/sensor_accel_driver.c \$(FRAMEWORKS_SENSOR_ROOT)/chipset/accel/accel_bmi160.c
endifinclude $(HDF_DRIVER)
Kconfig
内容如下:
# drivers\adapter\khdf\liteos\model\sensor\Kconfigconfig DRIVERS_HDF_SENSORbool "Enable HDF sensor driver"default ndepends on DRIVERS_HDFhelpAnswer Y to enable HDF sensor driver.config DRIVERS_HDF_SENSOR_ACCELbool "Enable HDF accel sensor driver"default ndepends on DRIVERS_HDF_SENSORhelpAnswer Y to enable HDF accel sensor driver.
config DRIVERS_HDF_SENSOR_ACCEL_BMI160bool "Enable HDF accel sensor driver"default ndepends on DRIVERS_HDF_SENSOR_ACCELhelpAnswer Y to enable HDF accel bmi160 sensor driver.
分析到这,我发现其实Makefile 和BUILD.gn的内容其实差不多,这就很奇怪了,为啥要配两份?
3、设备配置描述
以 Hi3516DV300
为例,这个平台的 device_info.hcs
在vendor/hisilicon/Hi3516DV300/hdf_config/khdf/device_info/
目录下:
# vendor/hisilicon/Hi3516DV300/hdf_config/khdf/device_info/device_info.hcsroot {device_info {match_attr = "hdf_manager";template host {hostName = "";priority = 100;template device {template deviceNode {policy = 0;priority = 100;preload = 0;permission = 0664;moduleName = "";serviceName = "";deviceMatchAttr = "";}}}platform :: host {hostName = "platform_host";priority = 50;device_gpio :: device {device0 :: deviceNode {policy = 0;priority = 10;permission = 0644;moduleName = "linux_gpio_adapter";deviceMatchAttr = "linux_gpio_adapter";}}device_i2c :: device {device0 :: deviceNode {policy = 2;priority = 50;permission = 0644;moduleName = "HDF_PLATFORM_I2C_MANAGER";serviceName = "HDF_PLATFORM_I2C_MANAGER";deviceMatchAttr = "hdf_platform_i2c_manager";}device1 :: deviceNode {policy = 0;priority = 55;permission = 0644;moduleName = "linux_i2c_adapter";deviceMatchAttr = "linux_i2c_adapter";}}}display :: host {hostName = "display_host";}input :: host {hostName = "input_host";priority = 100;}network :: host {hostName = "network_host";}sensor :: host {hostName = "sensor_host";device_sensor_manager :: device {device0 :: deviceNode {policy = 2;priority = 100;preload = 0;permission = 0664;moduleName = "HDF_SENSOR_MGR_AP";serviceName = "hdf_sensor_manager_ap";}}device_sensor_accel :: device {device0 :: deviceNode {policy = 1;priority = 110;preload = 2;permission = 0664;moduleName = "HDF_SENSOR_ACCEL";serviceName = "hdf_sensor_accel";deviceMatchAttr = "hdf_sensor_accel_driver";}}device_sensor_bmi160 :: device {device0 :: deviceNode {policy = 1;priority = 120;preload = 2;permission = 0664;moduleName = "HDF_SENSOR_ACCEL_BMI160";serviceName = "hdf_accel_bmi160";deviceMatchAttr = "hdf_sensor_accel_bmi160_driver";}}}usb_pnp_linux :: host {hostName = "usb_pnp_linux_host";device_usb_pnp_linux :: device {}}audio :: host {hostName = "audio_host";priority = 60;}vibrator :: host {hostName = "vibrator_host";}dsoftbus :: host {hostName = "dsoftbus_host";}
可以看到,配置方面,相对还是比较简单的。
看到这里,其实您可以返回上一篇文章继续看了: 《【鸿蒙OS开发入门】17 - HDF驱动子系统:hdf_devmgr服务 驱动框架管理模块源码分析》
二、加速度计传感器Driver层代码逻辑分析
在前面《【鸿蒙OS开发入门】17 - HDF驱动子系统:hdf_devmgr服务 驱动框架管理模块源码分析》 中,
我们分析到 DevHostServiceAddDevice()
函数,它就是整个驱动的总入口:
主要工作如下:
- 获取
driverLoader
入口 - 获取
HdfDevice
结构体,其中定义了hostId/deviceId
和Attach/Detach
方法 - 调用
LoadNode()
,加载设备驱动 - 调用
device->super.Attach()
方法开始探测驱动,实际调用的是.Init
方法
# drivers\framework\core\host\src\devhost_service.c
int DevHostServiceAddDevice(struct IDevHostService *inst, const struct HdfDeviceInfo *deviceInfo)
{int ret = HDF_FAILURE;struct HdfDevice *device = NULL;struct HdfDeviceNode *devNode = NULL;struct DevHostService *hostService = CONTAINER_OF(inst, struct DevHostService, super);// 1. 获取 driverLoader 入口struct IDriverLoader *driverLoader = HdfDriverLoaderGetInstance(); ================>static struct HdfDriverLoader driverLoader;HdfDriverLoaderConstruct(&driverLoader);--------------->+ struct IDriverLoader *driverLoaderIf = (struct IDriverLoader *)inst;+ driverLoaderIf->LoadNode = HdfDriverLoaderLoadNode;+ driverLoaderIf->UnLoadNode = HdfDriverLoaderUnLoadNode;+ driverLoaderIf->GetDriverEntry = HdfDriverLoaderGetDriverEntry;<---------------return (struct HdfObject *)&driverLoader;<================// 2. 获取 HdfDevice 结构体,其中定义了hostId/deviceId 和 Attach/Detach方法device = DevHostServiceGetDevice(hostService, deviceInfo->deviceId);------------->+ device = HdfDeviceNewInstance();+ ========> return (struct HdfDevice *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVICE);+ + struct HdfDevice *device = (struct HdfDevice *)OsalMemCalloc(sizeof(struct HdfDevice));+ + HdfDeviceConstruct(device);+ + --------->+ + + device->super.Attach = HdfDeviceAttach; // 最终调用驱动的 .Init+ + + DListHeadInit(&device->devNodes);+ + <---------+ <========+ device->hostId = inst->hostId;+ device->deviceId = deviceId;+ DListInsertHead(&device->node, &inst->devices);<------------if (device == NULL || device->super.Attach == NULL) {ret = HDF_DEV_ERR_NO_DEVICE;goto error;}// 3. 调用LoadNode() ,加载设备驱动devNode = driverLoader->LoadNode(driverLoader, deviceInfo);// 4. 调用device->super.Attach() 方法开始探测驱动,实际调用的是.Init方法devNode->hostService = hostService;ret = device->super.Attach(&device->super, devNode);return HDF_SUCCESS;
}
我们本文就以ACCEL_BMI160
为例来分析下调用流程:
2.1 driverLoader->LoadNode()方法: HdfDriverLoaderLoadNode() 加载驱动 bind() 方法
主要工作如下:
- 获取驱动函数结构体
struct HdfDriverEntry g_accelBmi160DevEntry
,其中包含了bmi160
的bind
和init
方法
// 注册加速度计传感器入口数据结构体对象
struct HdfDriverEntry g_accelBmi160DevEntry = {.moduleVersion = 1, // 加速度计传感器模块版本号.moduleName = "HDF_SENSOR_ACCEL_BMI160", // 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样.Bind = Bmi160BindDriver, // 加速度计传感器绑定函数.Init = Bmi160InitDriver, // 加速度计传感器初始化函数.Release = Bmi160ReleaseDriver, // 加速度计传感器资源释放函数
};
- 初始化驱动相关的设备节点,调用
HDF_OBJECT_ID_DEVICE_SERVICE
所对应的函数DeviceNodeExtCreate()
- 配置
Bmi160
的devNode
结构体,绑定driverEntry
- 调用驱动的
bind
方法开始绑定驱动
# drivers\framework\core\host\src\hdf_driver_loader.c
struct HdfDeviceNode *HdfDriverLoaderLoadNode(struct IDriverLoader *loader, const struct HdfDeviceInfo *deviceInfo)
{struct HdfDriverEntry *driverEntry = NULL;struct HdfDeviceNode *devNode = NULL;// 1. 获取驱动函数结构体struct HdfDriverEntry g_accelBmi160DevEntrydriverEntry = loader->GetDriverEntry(deviceInfo);// 2. 初始化驱动相关的设备节点,调用HDF_OBJECT_ID_DEVICE_SERVICE所对应的函数DeviceNodeExtCreate()devNode = HdfDeviceNodeNewInstance();================> return (struct HdfDeviceNode *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVICE_SERVICE);+ struct DeviceNodeExt *instance = (struct DeviceNodeExt *)OsalMemCalloc(sizeof(struct DeviceNodeExt));+ DeviceNodeExtConstruct(instance);+ ------------>+ - struct IDeviceNode *nodeIf = &devNode->super;+ - HdfDeviceNodeConstruct(&inst->super);+ - ==========>+ - HdfDeviceObjectConstruct(&devNode->deviceObject);+ - -------->+ - + deviceObject->property = NULL;+ - + deviceObject->service = NULL;+ - + deviceObject->deviceClass = DEVICE_CLASS_DEFAULT;+ - <--------+ - devNode->token = HdfDeviceTokenNewInstance();+ - nodeIf->LaunchNode = HdfDeviceLaunchNode; // 调用sensor init方法,初始化sensor+ - nodeIf->PublishService = HdfDeviceNodePublishPublicService;+ - <==========+ - nodeIf->PublishService = DeviceNodeExtPublishService;+ <------------+ instance->ioService = NULL;<================// 3. 配置Bmi160的 devNode结构体,绑定driverEntrydevNode->driverEntry = driverEntry;devNode->deviceInfo = deviceInfo; // device listdevNode->deviceObject.property = HcsGetNodeByMatchAttr(HdfGetRootNode(), deviceInfo->deviceMatchAttr);devNode->deviceObject.priv = (void *)(deviceInfo->private);// 4. 调用驱动的 bind 方法开始绑定驱动driverEntry->Bind(&devNode->deviceObject);return devNode;
}
2.2 driverEntry->Bind()方法: Bmi160BindDriver() 分配并初始化驱动结构体g_bmi160DrvData
- 分配并初始化
struct Bmi160DrvData
内存 - 将设备节点的
HdfDeviceObject
结构体与驱动结构体Bmi160DrvData
绑定在一起 - 配置全局驱动结构体指针
g_bmi160DrvData
# drivers\framework\model\sensor\driver\chipset\accel\accel_bmi160.c
int32_t Bmi160BindDriver(struct HdfDeviceObject *device)
{// 1. 分配并初始经`struct Bmi160DrvData` 内存struct Bmi160DrvData *drvData = (struct Bmi160DrvData *)OsalMemCalloc(sizeof(*drvData));// 2. 将设备节点的HdfDeviceObject结构体与驱动结构体Bmi160DrvData绑定在一起drvData->ioService.Dispatch = DispatchBMI160;drvData->device = device;device->service = &drvData->ioService;// 3. 配置全局驱动结构体指针g_bmi160DrvData g_bmi160DrvData = drvData;return HDF_SUCCESS;
}
2.3 device->super.Attach()方法: HdfDeviceAttach() 开始加载驱动.Init 方法探测驱动设备
# drivers\framework\core\host\src\hdf_device.c
static int HdfDeviceAttach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)
{struct HdfDevice *device = (struct HdfDevice *)devInst;struct IDeviceNode *nodeIf = (struct IDeviceNode *)devNode;DListInsertTail(&devNode->entry, &device->devNodes);return nodeIf->LaunchNode(devNode, devInst);
}
在HdfDeviceAttach()
中主要是调用了DeviceNode
的LaunchNode()
方法,
它是在前面初始化驱动相关的设备节点时配置的,代码为:nodeIf->LaunchNode = HdfDeviceLaunchNode;
我们来看看HdfDeviceLaunchNode()
函数:
- 调用驱动
.Init()
方法探测并初始化驱动设备 - 注册
device node
对应的service
- 将驱动添加进
device node service
中, 对应的函数为DevmgrServiceAttachDevice()
# drivers\framework\core\host\src\hdf_device_node.c
int HdfDeviceLaunchNode(struct HdfDeviceNode *devNode, struct IHdfDevice *devInst)
{struct HdfDevice *device = (struct HdfDevice *)devInst; // HdfDevice 结构体,其中定义了hostId/deviceId和Attach/Detach方法struct HdfDriverEntry *driverEntry = devNode->driverEntry; // 驱动函数结构体const struct HdfDeviceInfo *deviceInfo = devNode->deviceInfo; // 设备device list结构体struct IHdfDeviceToken *deviceToken = NULL;// 1. 调用驱动 .Init() 方法探测并初始化驱动设备int ret = driverEntry->Init(&devNode->deviceObject);// 2. 注册device node 对应的serviceret = HdfDeviceNodePublishService(devNode, deviceInfo, devInst);------------>- struct IDeviceNode *nodeIf = &devNode->super;- status = nodeIf->PublishService(devNode, deviceInfo->svcName); // 调用的是 HdfDeviceNodePublishPublicService() 方法- ===========>- + return DevSvcManagerClntAddService(svcName, &devNode->deviceObject);- + --------->- + struct DevSvcManagerClnt *devSvcMgrClnt = DevSvcManagerClntGetInstance();- + struct IDevSvcManager *serviceManager = devSvcMgrClnt->devSvcMgrIf;- + return serviceManager->AddService(serviceManager, svcName, service);- + <---------- <===========<------------// 3. 将驱动添加进device node service中, 对应的函数为 DevmgrServiceAttachDevice()deviceToken = devNode->token;ret = DevmgrServiceClntAttachDevice(deviceInfo, deviceToken);------------>struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance();devMgrSvcIf = inst->devMgrSvcIf;return devMgrSvcIf->AttachDevice(devMgrSvcIf, deviceInfo, deviceToken); <------------return ret;
}
2.4 driverEntry->Init方法:
此时,终于进入我们驱动的正题了,开始探测并初始化驱动设备。
# drivers\framework\model\sensor\driver\chipset\accel\accel_bmi160.c
int32_t Bmi160InitDriver(struct HdfDeviceObject *device)
{int32_t ret;struct AccelOpsCall ops;struct Bmi160DrvData *drvData = (struct Bmi160DrvData *)device->service;// 初始化I2C6的控制寄存器:PIN肢配置为I2C模式和配置I2C时钟ret = InitAccelPreConfig();// drvData->sensorCfg = AccelCreateCfgData(device->property);------------>GetSensorBaseConfigData(node, drvData->accelCfg);DetectSensorDevice(drvData->accelCfg);drvData->detectFlag = true;InitAccelAfterDetected(drvData->accelCfg);<------------ops.Init = NULL;ops.ReadData = ReadBmi160Data; // 配置 sensor 读取寄存器的方法ret = AccelRegisterChipOps(&ops);------------->drvData->ops.Init = ops->Init;drvData->ops.ReadData = ops->ReadData; // 配置加速度计传感器寄存器读取方法<-------------ret = InitBmi160(drvData->sensorCfg);------------->ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);<-------------return HDF_SUCCESS;
}
文档参考:
《SENSOR》
《驱动开发》
《配置管理》
【鸿蒙OS开发入门】18 - HDF驱动子系统:加速度计传感器 Driver层驱动代码分析相关推荐
- 【鸿蒙OS开发入门】06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 启动init进程
[鸿蒙OS开发入门]06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 一.head.S 启动start_kernel() 1.1 start_kernel() ...
- 【鸿蒙OS开发入门】16 - 重头搭建Ubuntu新环境编译OpenHarmony 3.0 LTS
[鸿蒙OS开发入门]16 - 重头搭建Ubuntu新环境编译OpenHarmony 3.0 LTSv 一.配置Telnet 和 samba 二.下载code-v3.0-LTS.tar.gz源码 三.配 ...
- 【鸿蒙OS开发入门】13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解
[鸿蒙OS开发入门]13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解 一. /etc/init.cfg 系统默认cfg:启动lo回环网卡 1.1 init.Hi35 ...
- 鸿蒙APP开发入门到进阶 | 入门完整篇。
大家好,我是 码工,一个有十年工作经验的码农,一心追求技术. 先说说我的开发经历,10年毕业,到目前已经十多年开发经验,大学学习了多种语言,Java,Android,c,c++,到毕业时真正掌握了几乎 ...
- 【小白入门】超详细的OCRnet详解(含代码分析)
[小白入门]超详细的OCRnet详解(含代码分析) OCRnet 简介 网络结构 具体实现(含代码分析) 实验结果 本文仅梳理总结自己在学习过程中的一些理解和思路,不保证绝对正确,请酌情参考.如果各位 ...
- 鸿蒙os开发哪里学,鸿蒙OS发布以后,我们去哪里学习?
2020年9月10日,华为强势发布了鸿蒙OS 2.0,这次终于不是"PPT"开源了. 源代码公布,相关开发套件公布,恨不得连开发板的购买链接都公布了. 诚意满满. 但问题又来了. ...
- 鸿蒙是学生开发的系统,9岁小学生展示鸿蒙OS开发
华为的鸿蒙OS正在迅速成熟,这背后离不开无数开发者的支持. 近日,鸿蒙OS技术社区就向大家介绍了一位特殊的鸿蒙开发者,今年只有9岁,还是个小学生-- 在鸿蒙社区,这位小开发者坐在镜头前,向大家演示了鸿 ...
- 鸿蒙os开发小程序,9岁小学生展示鸿蒙OS开发:这操作太秀了
华为的鸿蒙 OS 正在迅速成熟,这背后离不开无数开发者的支持. 近日,鸿蒙 OS 技术社区就向大家介绍了一位特殊的鸿蒙开发者,今年只有 9 岁,还是个小学生 -- 在鸿蒙社区,这位小开发者坐在镜头前, ...
- 鸿蒙其实就是一场秀,9岁小学生展示鸿蒙OS开发:这操作太秀了
华为的鸿蒙OS正在迅速成熟,这背后离不开无数开发者的支持. 近日,鸿蒙OS技术社区就向大家介绍了一位特殊的鸿蒙开发者,今年只有9岁,还是个小学生-- 在鸿蒙社区,这位小开发者坐在镜头前,向大家演示了鸿 ...
最新文章
- 1.1 一个简单的脚本
- Linux内核基础--事件通知链(notifier chain)【转】
- python123第七周测验编程题答案_Python第七周编程题
- 蓝天集团董事长郎凤娥专访
- 对比鸿蒙,Google 的 Fuchsia 当前进度如何?
- pythonflask开发web网页编辑_总结Python+Flask+MysqL的web建设技术过程
- 在shell或bash执行一个bin文件或者脚本的流程
- 安装SQL Server 2005中文开发版后,界面变英文改中文解决方法
- unrar在linux如何编译,rarlinux(rar\unrar在linux使用)
- 2021年高压电工模拟考试题及高压电工模拟考试题库
- Matlab中插值函数汇总及使用说明
- html尖角效果,CSS3之尖角标签_html/css_WEB-ITnose
- vue动态调节背景图片
- 离散数学复习笔记——命题逻辑——命题
- [INFO1110课件讲解 一] USYD悉尼大学INFO1110 ED lessons Week1 课件 作业 assignment讲解
- 我爱赚钱吧:你知道自己建网站可以赚钱吗?①
- C语言:指针的偏移步长、结构体成员的偏移量、嵌套结构体成员的偏移量、结构体的内存对齐
- 西邮Linux兴趣小组纳新笔试试题
- 关于出版《AR Foundation增强现实开发实战(ARKit版)》(2022-09-11创建)
- 基于SSM小区智能物业管理
热门文章
- OpenEuler安装Docker及OpenGuass最全教程
- 《好玩游戏物品清单》实现
- 下列不是用于制作计算机动画,计算机应用基础动画制作软件_2019答案章节答案期末答案...
- linux查询某域线程是否满了,Linux多线程编程的时候怎么查看一个进程中的某个线程是否存活...
- HTML5网页设计样式-基本CSS选择器
- html中怎样选择第几个,CSS选取第几个标签元素:first-child、last-child、nth-child
- 2019年最新版嵌入式开发教程大纲免费分享
- [CC-TRIPS]Children Trips
- linux三剑客有什么区别,学习Linux三剑客
- QT的QTreeWidget节点触发事件(一)