【鸿蒙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方法:

本系列文章汇总:

  1. 《【鸿蒙OS开发入门】01 - 搭建Ubuntu虚拟机开发环境》
  2. 《【鸿蒙OS开发入门】02 - 启动流程代码分析之Uboot 第一阶段:之解压并引导加载u-boot.bin》
  3. 《【鸿蒙OS开发入门】03 - 启动流程代码分析之Uboot 第二阶段:之board_init初始化》
  4. 《【鸿蒙OS开发入门】04 - 启动流程代码分析之Uboot 第二阶段:之U_BOOT_CMD原理》
  5. 《【鸿蒙OS开发入门】05 - 启动流程代码分析之Uboot 第二阶段:之bootm引导加载Kernel OS》
  6. 《【鸿蒙OS开发入门】06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核》
  7. 《【鸿蒙OS开发入门】07 - 安装docker环境编译openharmony 2.0代码》
  8. 《【鸿蒙OS开发入门】08 - 启动流程代码分析之KernelOS:之启动 liteos_a 内核》
  9. 《【鸿蒙OS开发入门】09 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 中do_basic_setup()所干的大事》
  10. 《【鸿蒙OS开发入门】10 - 启动流程代码分析之第一个用户态进程:init 进程》
  11. 《【鸿蒙OS开发入门】11 - 启动流程代码分析之第一个用户态进程:init 进程 之 Services简介》
  12. 《【鸿蒙OS开发入门】12 - 启动流程代码分析之第一个用户态进程:init 进程 之 pre-init 任务详解》
  13. 《【鸿蒙OS开发入门】13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解》
  14. 《【鸿蒙OS开发入门】14 - 启动流程代码分析之第一个用户态进程:init 进程 之 post-init 任务详解》
  15. 《【鸿蒙OS开发入门】15 - 启动流程代码分析之第一个用户态进程:init 进程 之 StartParamService源码分析 及 setparam、getparam代码分析》
  16. 《【鸿蒙OS开发入门】16 - 重头搭建Ubuntu新环境编译OpenHarmony 3.0 LTS》
  17. 《【鸿蒙OS开发入门】17 - HDF驱动子系统:hdf_devmgr服务 驱动框架管理模块源码分析》
  18. 《【鸿蒙OS开发入门】18 - HDF驱动子系统:加速度计传感器 Driver层驱动代码分析》

之所以选择加速度计传感器来作为首篇驱动分析,主要是因为官方文档有对它介绍,《SENSOR》,
本文就参考着官方文档,来学习下加速度计传感器的驱动逻辑。

参考官方文档,先来上一张Sensor驱动模型图:

从上面Sensor驱动模型图,从下往上,按我的理解,我们大致可以分为三层:

  1. Hardware: 这一层是实实在在的物理器件,比如加速度计、陀螺仪等。
  2. Platform IF: 这一层主要是提供与物理器件的交互方法,比如I2C、SPI等总线驱动。
  3. Driver:这一层的核心就是各个驱动的struct HdfDriverEntry结构体,在结构体中封装了相关sensor的具体实现逻辑。
  4. 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.hcsvendor/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()函数,它就是整个驱动的总入口:

主要工作如下:

  1. 获取 driverLoader 入口
  2. 获取 HdfDevice 结构体,其中定义了hostId/deviceIdAttach/Detach方法
  3. 调用LoadNode() ,加载设备驱动
  4. 调用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() 方法

主要工作如下:

  1. 获取驱动函数结构体struct HdfDriverEntry g_accelBmi160DevEntry,其中包含了bmi160bindinit方法
// 注册加速度计传感器入口数据结构体对象
struct HdfDriverEntry g_accelBmi160DevEntry = {.moduleVersion = 1,                            // 加速度计传感器模块版本号.moduleName = "HDF_SENSOR_ACCEL_BMI160",  // 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样.Bind = Bmi160BindDriver,                 // 加速度计传感器绑定函数.Init = Bmi160InitDriver,                    // 加速度计传感器初始化函数.Release = Bmi160ReleaseDriver,             // 加速度计传感器资源释放函数
};
  1. 初始化驱动相关的设备节点,调用HDF_OBJECT_ID_DEVICE_SERVICE所对应的函数DeviceNodeExtCreate()
  2. 配置Bmi160devNode结构体,绑定driverEntry
  3. 调用驱动的 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

  1. 分配并初始化struct Bmi160DrvData 内存
  2. 将设备节点的HdfDeviceObject结构体与驱动结构体Bmi160DrvData绑定在一起
  3. 配置全局驱动结构体指针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() 中主要是调用了DeviceNodeLaunchNode()方法,
它是在前面初始化驱动相关的设备节点时配置的,代码为:nodeIf->LaunchNode = HdfDeviceLaunchNode;
我们来看看HdfDeviceLaunchNode() 函数:

  1. 调用驱动 .Init() 方法探测并初始化驱动设备
  2. 注册device node 对应的service
  3. 将驱动添加进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层驱动代码分析相关推荐

  1. 【鸿蒙OS开发入门】06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 启动init进程

    [鸿蒙OS开发入门]06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 一.head.S 启动start_kernel() 1.1 start_kernel() ...

  2. 【鸿蒙OS开发入门】16 - 重头搭建Ubuntu新环境编译OpenHarmony 3.0 LTS

    [鸿蒙OS开发入门]16 - 重头搭建Ubuntu新环境编译OpenHarmony 3.0 LTSv 一.配置Telnet 和 samba 二.下载code-v3.0-LTS.tar.gz源码 三.配 ...

  3. 【鸿蒙OS开发入门】13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解

    [鸿蒙OS开发入门]13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解 一. /etc/init.cfg 系统默认cfg:启动lo回环网卡 1.1 init.Hi35 ...

  4. 鸿蒙APP开发入门到进阶 | 入门完整篇。

    大家好,我是 码工,一个有十年工作经验的码农,一心追求技术. 先说说我的开发经历,10年毕业,到目前已经十多年开发经验,大学学习了多种语言,Java,Android,c,c++,到毕业时真正掌握了几乎 ...

  5. 【小白入门】超详细的OCRnet详解(含代码分析)

    [小白入门]超详细的OCRnet详解(含代码分析) OCRnet 简介 网络结构 具体实现(含代码分析) 实验结果 本文仅梳理总结自己在学习过程中的一些理解和思路,不保证绝对正确,请酌情参考.如果各位 ...

  6. 鸿蒙os开发哪里学,鸿蒙OS发布以后,我们去哪里学习?

    2020年9月10日,华为强势发布了鸿蒙OS 2.0,这次终于不是"PPT"开源了. 源代码公布,相关开发套件公布,恨不得连开发板的购买链接都公布了. 诚意满满. 但问题又来了. ...

  7. 鸿蒙是学生开发的系统,9岁小学生展示鸿蒙OS开发

    华为的鸿蒙OS正在迅速成熟,这背后离不开无数开发者的支持. 近日,鸿蒙OS技术社区就向大家介绍了一位特殊的鸿蒙开发者,今年只有9岁,还是个小学生-- 在鸿蒙社区,这位小开发者坐在镜头前,向大家演示了鸿 ...

  8. 鸿蒙os开发小程序,9岁小学生展示鸿蒙OS开发:这操作太秀了

    华为的鸿蒙 OS 正在迅速成熟,这背后离不开无数开发者的支持. 近日,鸿蒙 OS 技术社区就向大家介绍了一位特殊的鸿蒙开发者,今年只有 9 岁,还是个小学生 -- 在鸿蒙社区,这位小开发者坐在镜头前, ...

  9. 鸿蒙其实就是一场秀,9岁小学生展示鸿蒙OS开发:这操作太秀了

    华为的鸿蒙OS正在迅速成熟,这背后离不开无数开发者的支持. 近日,鸿蒙OS技术社区就向大家介绍了一位特殊的鸿蒙开发者,今年只有9岁,还是个小学生-- 在鸿蒙社区,这位小开发者坐在镜头前,向大家演示了鸿 ...

最新文章

  1. 1.1 一个简单的脚本
  2. Linux内核基础--事件通知链(notifier chain)【转】
  3. python123第七周测验编程题答案_Python第七周编程题
  4. 蓝天集团董事长郎凤娥专访
  5. 对比鸿蒙,Google 的 Fuchsia 当前进度如何?
  6. pythonflask开发web网页编辑_总结Python+Flask+MysqL的web建设技术过程
  7. 在shell或bash执行一个bin文件或者脚本的流程
  8. 安装SQL Server 2005中文开发版后,界面变英文改中文解决方法
  9. unrar在linux如何编译,rarlinux(rar\unrar在linux使用)
  10. 2021年高压电工模拟考试题及高压电工模拟考试题库
  11. Matlab中插值函数汇总及使用说明
  12. html尖角效果,CSS3之尖角标签_html/css_WEB-ITnose
  13. vue动态调节背景图片
  14. 离散数学复习笔记——命题逻辑——命题
  15. [INFO1110课件讲解 一] USYD悉尼大学INFO1110 ED lessons Week1 课件 作业 assignment讲解
  16. 我爱赚钱吧:你知道自己建网站可以赚钱吗?①
  17. C语言:指针的偏移步长、结构体成员的偏移量、嵌套结构体成员的偏移量、结构体的内存对齐
  18. 西邮Linux兴趣小组纳新笔试试题
  19. 关于出版《AR Foundation增强现实开发实战(ARKit版)》(2022-09-11创建)
  20. 基于SSM小区智能物业管理

热门文章

  1. OpenEuler安装Docker及OpenGuass最全教程
  2. 《好玩游戏物品清单》实现
  3. 下列不是用于制作计算机动画,计算机应用基础动画制作软件_2019答案章节答案期末答案...
  4. linux查询某域线程是否满了,Linux多线程编程的时候怎么查看一个进程中的某个线程是否存活...
  5. HTML5网页设计样式-基本CSS选择器
  6. html中怎样选择第几个,CSS选取第几个标签元素:first-child、last-child、nth-child
  7. 2019年最新版嵌入式开发教程大纲免费分享
  8. [CC-TRIPS]Children Trips
  9. linux三剑客有什么区别,学习Linux三剑客
  10. QT的QTreeWidget节点触发事件(一)