鸿蒙南向设备开发(OpenHarmony)Sensor屏蔽硬件器件

海哥  金牌会员 | 2024-12-29 17:56:37 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 979|帖子 979|积分 2937

鸿蒙NEXT开发实战往期必看文章:
一分钟相识”纯血版!鸿蒙HarmonyOS Next应用开发!
“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通)
HarmonyOS NEXT应用开发案例实践总结合(持续更新......)
HarmonyOS NEXT应用开发性能优化实践总结(持续更新......)

功能简介

Sensor驱动模型屏蔽硬件器件差别,为上层Sensor服务系统提供稳固的Sensor基础能力接口,包罗Sensor列表查询、Sensor启停、Sensor订阅及取消订阅,Sensor参数设置等功能。Sensor设备驱动的开发是基于HDF驱动框架基础上,结合操作系统适配层(OSAL)和平台驱动接口(比如I2C/SPI/UART总线等平台资源)能力,屏蔽差别操作系统和平台总线资源差别,实现Sensor驱动“一次开发,多系统摆设”的目的。Sensor驱动模型如图1所示。
图 1 Sensor驱动模型图

根本概念

如今根据sensorId将Sensor分为医学类Sensor、传统类Sensor两种。


  • 医学类Sensor:已订阅的sensorId枚举值在128-160范围的为医学类Sensor。
  • 传统类Sensor:已订阅的sensorId枚举值不在128-160范围的为传统类Sensor。
运作机制

通过先容Sensor驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,团体加载流程如图2所示:
图 2 Sensor驱动运行图

Sensor驱动模型以标准系统RK3568产品中的加快率传感器驱动为例,先容整个驱动加载及运行流程:

  • 从device_info.hcs设置文件中的Sensor Host读取到Sensor设备管理设置信息。
  • HDF设置框架从HCB数据库中解析Sensor设备管理设置信息,并关联对应设备驱动。
  • 加载并初始化Sensor设备管理驱动。
  • Sensor设备管理驱动向HDI发布Sensor基础能力接口。
  • 从device_info.hcs设置文件中的Sensor Host读取到加快率传感器驱动设置信息。
  • 加载加快率传感器抽象驱动,调用初始化接口,完成Sensor器件的驱动资源分配和数据处理队列的创建。
  • 从accel_xxx_config.hcs设置文件中读取到加快率传感器差别化驱动设置和私有化设置信息。
  • 加快率传感器芯片差别化驱动,调用通用设置解析接口,完成器件属性信息解析,器件寄存器解析。
  • 加快率传感器芯片差别化驱动完成器件的探测,并分配加快率传感器设置资源和加快率传感器差别化接口注册。
  • 加快率传感器乐成探测到器件之后,加快率传感器芯片差别化驱动通知加快率传感器抽象驱动,注册加快率传感器设备到Sensor设备管理中。
开发引导

场景先容



  • 通过重力和陀螺仪传感器数据,能感知设备倾斜和旋转量,进步用户在游戏场景中的体验。
  • 通过靠近光传感器数据,感知距离遮挡物的距离,使设备能够自动亮灭屏,到达防误触目的。例如,手机通话时,如屏幕距离人脸过近,则自动关闭屏幕,防止误触的同时低落功耗。
  • 通过气压计传感器数据,可以正确的判断设备当前所处的海拔。
  • 通过环境光传感器数据,设备能够实现背光自动调节。
  • 通过霍尔传感器数据,设备可以实现皮套功能,皮套合上,手机上开一个小窗口,可低落功耗。
接口说明

Sensor驱动模型对外开放的API接口能力如下:


  • 提供Sensor HDI(Hardware Device Interface)能力接口,简化服务开发。
  • 提供Sensor驱动模型能力接口:

    • 依靠HDF驱动框架实现Sensor器件驱动的加载、器件探测、注册和去注册等能力。
    • 提供同一范例Sensor器件驱动归一接口、寄存器设置解析操作接口、总线访问抽象接口和平台抽象接口。

  • 提供开发者实现的能力接口:依靠HDF驱动框架的HCS(HDF Configuration Source)设置管理,根据同范例Sensor差别化设置,实现Sensor器件参数序列化设置和器件部分操作接口,简化Sensor器件驱动开发。
Sensor驱动模型对外开放的API接口能力的详细实现请参考:
表 1 Sensor驱动模型对外API接口功能先容
注:以下接口列举的为C接口,接口声明见文件/drivers/peripheral/sensor/interfaces/include。
接口名功能形貌int32_t GetAllSensors(struct SensorInformation **sensorInfo, int32_t *count)获取系统中注册的所有传感器信息,一组完备传感器信息包罗传感器名字、设备厂商、固件版本号、硬件版本号、传感器范例编号、传感器标识、最大量程、精度、功耗。int32_t Enable(int32_t sensorId)使能指定传感器设备,只有数据订阅者使能传感器后,才气获取订阅的传感器数据。int32_t Disable(int32_t sensorId)去使能指定传感器设备。int32_t SetBatch(int32_t sensorId, int64_t samplingInterval, int64_t reportInterval)设置指定传感器的数据采样间隔和数据上报间隔。int32_t SetMode(int32_t sensorId, int32_t mode)设置指定传感器的工作模式,差别的工作模式,上报数据方式差别。int32_t SetOption(int32_t sensorId, uint32_t option)设置指定传感器量程,精度等可选设置。int32_t Register(int32_t groupId, RecordDataCallback cb)订阅者根据差别groupId注册传感器数据回调函数,系统会将获取到的传感器数据上报给订阅者。int32_t Unregister(int32_t groupId, RecordDataCallback cb)订阅者根据groupId和回调函数注销对应订阅者的传感器数据回调函数。 Sensor驱动模型对驱动开发者开放的功能接口,驱动开发者无需实现,直接使用,请参考:
表2 Sensor驱动模型对驱动开发者开放的功能接口列表
接口名功能形貌int32_t AddSensorDevice(const struct SensorDeviceInfo *deviceInfo)添加当前范例的传感器设备到传感器设备管理。int32_t DeleteSensorDevice(const struct SensorBasicInfo *sensorBaseInfo)删除传感器设备管理里指定的传感器设备。int32_t ReportSensorEvent(const struct SensorReportEvent *events)上报指定范例传感器的数据到用户侧。int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen)按照设置的总线方式,读取传感器寄存器设置数据。int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t len)按照设置的总线方式,将传感器设置数据写入寄存器。int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorRegCfgGroupNode *group);根据传感器总线范例信息,下发寄存器分组设置。int32_t GetSensorBaseConfigData(const struct DeviceResourceNode *node, struct SensorCfgData *config)根据传感器设备HCS资源设置,获取传感器信息,总线设置信息,属性设置等根本设置信息,并初始化对应的根本设置数据结构体。int32_t ParseSensorRegConfig(struct SensorCfgData *config)根据传感器设备HCS资源设置,解析寄存器分组信息,并初始化设置数据结构体。void ReleaseSensorAllRegConfig(struct SensorCfgData *config)释放传感器设置数据结构体里分配的资源。int32_t GetSensorBusHandle(struct SensorBusCfg *busCfg)获取传感器总线句柄信息。int32_t ReleaseSensorBusHandle(struct SensorBusCfg *busCfg)释放传感器句柄信息。 Sensor驱动模型要求驱动开发者实现的接口功能,请参考:
表 3 Sensor驱动模型要求驱动开发者实现的接口列表
接口名功能形貌int32_t init(void)传感器设备探测乐成后,需要对传感器设备初始化设置。int32_t Enable(void)根据当前传感器设备的HCS设置,下发传感器设备使能操作组的寄存器设置。int32_t Disable(void)根据当前传感器设备的HCS设置,下发传感器设备去使能操作组的寄存器设置。int32_t SetBatch(int64_t samplingInterval, int64_t reportInterval)根据数据采样率和数据上报间隔,设置当前传感器设备的数据上报线程处理时间。int32_t SetMode(int32_t mode)设置当前传感器设备数据上报方式。int32_t SetOption(uint32_t option)根据可选设置、下发量程和精度等寄存器设置。void ReadSensorData(void)读取传感器数据。 接口实现参考开发步骤章节。
开发步骤

基于HDF驱动框架,按照驱动Driver Entry程序,以加快率传感器驱动为例,先容传感器驱动的开发。传感器的驱动开发包罗抽象驱动开发和差别化驱动开发两部分。传感器的抽象驱动开发包罗同一个传感器id中差别器件的公共接口实现;传感器的差别化驱动开发包罗差别器件差别化接口的实现。

  • 开发加快率传感器抽象驱动。

    • 加快率传感器抽象驱动在Sensor Host中的设置信息,代码实现路径如下:vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs。
      详细代码实现如下:
      1. /* 加速度计传感器设备HCS配置 */
      2. device_sensor_accel :: device {
      3.     device0 :: deviceNode {
      4.         policy = 1;                                  // 驱动服务发布的策略
      5.         priority = 110;                              // 驱动启动优先级(0-200),值越大优先级越低,建议配置为100,优先级相同则不保证device的加载顺序
      6.         preload = 0;                                 // 驱动按需加载字段,0表示加载,2表示不加载
      7.         permission = 0664;                           // 驱动创建设备节点权限
      8.         moduleName = "HDF_SENSOR_ACCEL";             // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
      9.         serviceName = "sensor_accel";                // 驱动对外发布服务的名称,必须唯一
      10.         deviceMatchAttr = "hdf_sensor_accel_driver"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
      11.     }
      12. }
      13. <strong>c</strong>
      复制代码
    • 加快率传感器抽象驱动代码实现路径为:drivers\hdf_core\framework\model\sensor\driver\accel\sensor_accel_driver.c。

      • 加快率传感器抽象驱动对应的HdfDriverEntry对象,此中,Driver Entry入口函数定义如下:
        1. struct HdfDriverEntry g_sensorAccelDevEntry = {
        2.     .moduleVersion = 1,                // 加速度计传感器模块版本号
        3.     .moduleName = "HDF_SENSOR_ACCEL",  // 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样
        4.     .Bind = BindAccelDriver,           // 加速度计传感器绑定函数
        5.     .Init = InitAccelDriver,           // 加速度计传感器初始化函数
        6.     .Release = ReleaseAccelDriver,     // 加速度计传感器资源释放函数
        7. };
        8. /* 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */
        9. HDF_INIT(g_sensorAccelDevEntry);
        10. <strong>c</strong>
        复制代码
      • 加快率传感器抽象驱动Bind接口实现如下:
        1. int32_t AccelBindDriver(struct HdfDeviceObject *device)
        2. {
        3.     CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
        4.     struct AccelDrvData *drvData = (struct AccelDrvData *)OsalMemCalloc(sizeof(*drvData));
        5.     if (drvData == NULL) {
        6.         HDF_LOGE("%s: Malloc accel drv data fail!", __func__);
        7.         return HDF_ERR_MALLOC_FAIL;
        8.     }
        9.     drvData->ioService.Dispatch = DispatchAccel;
        10.     drvData->device = device;
        11.     device->service = &drvData->ioService;
        12.     g_accelDrvData = drvData;
        13.     return HDF_SUCCESS;
        14. }
        15. <strong>c</strong>
        复制代码
      • 加快率传感器抽象驱动Init接口实现如下:
        1. int32_t AccelInitDriver(struct HdfDeviceObject *device)
        2. {
        3.     CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
        4.     struct AccelDrvData *drvData = (struct AccelDrvData *)device->service;
        5.     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
        6.          /* 工作队列资源初始化 */
        7.     if (InitAccelData(drvData) != HDF_SUCCESS) {
        8.         HDF_LOGE("%s: Init accel config failed", __func__);
        9.         return HDF_FAILURE;
        10.     }
        11.         /* 分配加速度配置信息资源 */
        12.     drvData->accelCfg = (struct SensorCfgData            *)OsalMemCalloc(sizeof(*drvData->accelCfg));
        13.     if (drvData->accelCfg == NULL) {
        14.         HDF_LOGE("%s: Malloc accel config data failed", __func__);
        15.         return HDF_FAILURE;
        16.     }
        17.         /* 注册寄存器分组信息 */
        18.     drvData->accelCfg->regCfgGroup = &g_regCfgGroup[0];
        19.     drvData->cb = NULL;
        20.        
        21.     HDF_LOGI("%s: Init accel driver success", __func__);
        22.     return HDF_SUCCESS;
        23. }
        24. <strong>c</strong>
        复制代码
      • 加快率抽象传感器驱动Release接口在驱动卸载或者Init实验失败时,会调用此接口释放资源,详细实现如下:
        1. void AccelReleaseDriver(struct HdfDeviceObject *device)
        2. {
        3.     CHECK_NULL_PTR_RETURN(device);
        4.     struct AccelDrvData *drvData = (struct AccelDrvData *)device->service;
        5.     CHECK_NULL_PTR_RETURN(drvData);
        6.         /* 器件在位,释放已分配资源 */
        7.     if (drvData->detectFlag && drvData->accelCfg != NULL) {
        8.         AccelReleaseCfgData(drvData->accelCfg);
        9.     }
        10.     OsalMemFree(drvData->accelCfg);
        11.     drvData->accelCfg = NULL;
        12.         /* 器件在位,销毁工作队列资源 */
        13.     HdfWorkDestroy(&drvData->accelWork);
        14.     HdfWorkQueueDestroy(&drvData->accelWorkQueue);
        15.     OsalMemFree(drvData);
        16. }
        17. <strong>c</strong>
        复制代码
      • 加快率传感器抽象驱动内部接口代码实现如下:

        • 提供给差别化驱动的初始化接口,完成加快率传感器器件的根本设置信息解析(加快率传感器信息,加快率传感器总线设置,加快率传感器器件探测寄存器设置),器件探测,器件寄存器解析,详细实现如下:
          1. static int32_t InitAccelAfterDetected(struct SensorCfgData *config)
          2. {
          3.     struct SensorDeviceInfo deviceInfo;
          4.     CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
          5.         /* 初始化加速度计接口函数 */
          6.     if (InitAccelOps(config, &deviceInfo) != HDF_SUCCESS) {
          7.         HDF_LOGE("%s: Init accel ops failed", __func__);
          8.         return HDF_FAILURE;
          9.     }
          10.         /* 注册加速度计器件到传感器设备管理模块 */
          11.     if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) {
          12.         HDF_LOGE("%s: Add accel device failed", __func__);
          13.         return HDF_FAILURE;
          14.     }
          15.         /* 器件寄存器解析 */
          16.     if (ParseSensorDirection(config) != HDF_SUCCESS) {
          17.         HDF_LOGE("%s: Parse accel direction failed", __func__);
          18.         (void)DeleteSensorDevice(&config->sensorInfo);
          19.         return HDF_FAILURE;
          20.     }
          21.     if (ParseSensorRegConfig(config) != HDF_SUCCESS) {
          22.         HDF_LOGE("%s: Parse sensor register failed", __func__);
          23.         (void)DeleteSensorDevice(&config->sensorInfo);
          24.         ReleaseSensorAllRegConfig(config);
          25.         ReleaseSensorDirectionConfig(config);
          26.         return HDF_FAILURE;
          27.     }
          28.     return HDF_SUCCESS;
          29. }
          30. struct SensorCfgData *AccelCreateCfgData(const struct DeviceResourceNode *node)
          31. {
          32.     struct AccelDrvData *drvData = AccelGetDrvData();
          33.         /* 如果器件不在位,返回进行下个器件探测 */
          34.     if (drvData == NULL || node == NULL) {
          35.         HDF_LOGE("%s: Accel node pointer NULL", __func__);
          36.         return NULL;
          37.     }
          38.     if (drvData->detectFlag) {
          39.         HDF_LOGE("%s: Accel sensor have detected", __func__);
          40.         return NULL;
          41.     }
          42.     if (drvData->accelCfg == NULL) {
          43.         HDF_LOGE("%s: Accel accelCfg pointer NULL", __func__);
          44.         return NULL;
          45.     }
          46.         /* 设备基本配置信息解析 */
          47.     if (GetSensorBaseConfigData(node, drvData->accelCfg) != HDF_SUCCESS) {
          48.         HDF_LOGE("%s: Get sensor base config failed", __func__);
          49.         goto BASE_CONFIG_EXIT;
          50.     }
          51.         /* 如果器件不在位(存在器件ID的情况),返回进行下个器件探测 */
          52.     if (DetectSensorDevice(drvData->accelCfg) != HDF_SUCCESS) {
          53.         HDF_LOGI("%s: Accel sensor detect device no exist", __func__);
          54.         drvData->detectFlag = false;
          55.         goto BASE_CONFIG_EXIT;
          56.     }
          57.         /* 器件寄存器解析 */
          58.     drvData->detectFlag = true;
          59.     if (InitAccelAfterDetected(drvData->accelCfg) != HDF_SUCCESS) {
          60.         HDF_LOGE("%s: Accel sensor detect device no exist", __func__);
          61.         goto INIT_EXIT;
          62.     }
          63.     return drvData->accelCfg;
          64. INIT_EXIT:
          65.     (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg);
          66. BASE_CONFIG_EXIT:
          67.     drvData->accelCfg->root = NULL;
          68.     (void)memset_s(&drvData->accelCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
          69.     (void)memset_s(&drvData->accelCfg->busCfg, sizeof(struct SensorBusCfg), 0, sizeof(struct SensorBusCfg));
          70.     (void)memset_s(&drvData->accelCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
          71.     return drvData->accelCfg;
          72. }
          73. <strong>c</strong>
          复制代码
        • Enable接口的代码实现如下:
          1. static int32_t SetAccelEnable(void)
          2. {
          3.     int32_t ret;
          4.     struct AccelDrvData *drvData = AccelGetDrvData();
          5.     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
          6.     CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM);
          7.     if (drvData->enable) {
          8.         HDF_LOGE("%s: Accel sensor is enabled", __func__);
          9.         return HDF_SUCCESS;
          10.     }
          11.         /* 设置寄存器 */
          12.     ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_ENABLE_GROUP]);
          13.     if (ret != HDF_SUCCESS) {
          14.         HDF_LOGE("%s: Accel sensor enable config failed", __func__);
          15.         return ret;
          16.     }
          17.         /* 创建定时器 */
          18.     ret = OsalTimerCreate(&drvData->accelTimer, SENSOR_TIMER_MIN_TIME, AccelTimerEntry, (uintptr_t)drvData);
          19.     if (ret != HDF_SUCCESS) {
          20.         HDF_LOGE("%s: Accel create timer failed[%d]", __func__, ret);
          21.         return ret;
          22.     }
          23.         /* 开启定时器进行数据上报 */
          24.     ret = OsalTimerStartLoop(&drvData->accelTimer);
          25.     if (ret != HDF_SUCCESS) {
          26.         HDF_LOGE("%s: Accel start timer failed[%d]", __func__, ret);
          27.         return ret;
          28.     }
          29.     drvData->enable = true;
          30.     return HDF_SUCCESS;
          31. }
          32. <strong>c</strong>
          复制代码
        • Disable接口的代码实现如下:
          1. static int32_t SetAccelDisable(void)
          2. {
          3.     int32_t ret;
          4.     struct AccelDrvData *drvData = AccelGetDrvData();
          5.     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
          6.     CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM);
          7.     if (!drvData->enable) {
          8.         HDF_LOGE("%s: Accel sensor had disable", __func__);
          9.         return HDF_SUCCESS;
          10.     }
          11.         /* 设置寄存器 */
          12.     ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_DISABLE_GROUP]);
          13.     if (ret != HDF_SUCCESS) {
          14.         HDF_LOGE("%s: Accel sensor disable config failed", __func__);
          15.         return ret;
          16.     }
          17.         /* 删除定时器 */
          18.     ret = OsalTimerDelete(&drvData->accelTimer);
          19.     if (ret != HDF_SUCCESS) {
          20.         HDF_LOGE("%s: Accel delete timer failed", __func__);
          21.         return ret;
          22.     }
          23.     drvData->enable = false;
          24.     return HDF_SUCCESS;
          25. }
          26. <strong>c</strong>
          复制代码
        • SetBatch接口的代码实现如下:
          1. static int32_t SetAccelBatch(int64_t samplingInterval, int64_t interval)
          2. {
          3.     (void)interval;
          4.     struct AccelDrvData *drvData = NULL;
          5.     drvData = AccelGetDrvData();
          6.     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
          7.         /* 给定时器设置采样率 */
          8.     drvData->interval = samplingInterval;
          9.     return HDF_SUCCESS;
          10. }
          11. <strong>c</strong>
          复制代码
        • SetMode接口的代码实现如下:
          1. static int32_t SetAccelMode(int32_t mode)
          2. {
          3.     if (mode <= SENSOR_WORK_MODE_DEFAULT || mode >= SENSOR_WORK_MODE_MAX) {
          4.         HDF_LOGE("%s: The current mode is not supported", __func__);
          5.         return HDF_FAILURE;
          6.     }
          7.     return HDF_SUCCESS;
          8. }
          9. <strong>c</strong>
          复制代码
        • SetOption接口的代码实现如下:
          1. static int32_t SetAccelOption(uint32_t option)
          2. {
          3.     (void)option;
          4.     return HDF_SUCCESS;
          5. }
          6. <strong>c</strong>
          复制代码



  • 开发加快率传感器差别化驱动。

    • 加快率传感器差别化驱动在Sensor Host中的设置信息,代码实现路径如下:vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs。
      详细代码实现如下:
      1. device_sensor_mxc6655xa :: device {
      2.     device0 :: deviceNode {
      3.         policy = 1;                // policy字段是驱动服务发布的策略
      4.         priority = 120; // 驱动启动优先级(0-200),值越大优先级越低,建议配置为100,优先级相同则不保证device的加载顺序
      5.         preload = 0;    // 驱动按需加载字段,0表示加载,2表示不加载
      6.         permission = 0664; // 驱动创建设备节点权限
      7.         moduleName = "HDF_SENSOR_ACCEL_MXC6655XA"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
      8.         serviceName = "hdf_accel_mxc6655xa"; // 加速度mxc6655xa对外发布服务的名称,必须唯一
      9.         deviceMatchAttr = "hdf_sensor_accel_mxc6655xa_driver"; // 加速度差异化驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
      10.     }
      11. }
      12. <strong>c</strong>
      复制代码
    • 加快率传感器差别化驱动私有HCS设置:

      • 代码实现路径:vendor\hihope\rk3568\hdf_config\khdf\sensor\accel\mxc6655xa_config.hcs。
      • 详细代码实现如下:
        1. #include "../sensor_common.hcs"
        2. root {
        3.     accel_mxc6655xa_chip_config : sensorConfig {
        4.         match_attr = "hdf_sensor_accel_mxc6655xa_driver";
        5.         sensorInfo :: sensorDeviceInfo {
        6.             sensorName = "accelerometer";
        7.             vendorName = "memsi_mxc6655xa"; // max string length is 16 bytes
        8.             sensorTypeId = 1; // enum SensorTypeTag
        9.             sensorId = 1; // user define sensor id
        10.             power = 230;
        11.             minDelay = 5000000; // nanosecond
        12.             maxDelay = 200000000; // nanosecond
        13.         }
        14.         sensorBusConfig :: sensorBusInfo {
        15.             busType = 0; // 0:i2c 1:spi
        16.             busNum = 5;
        17.             busAddr = 0x15;
        18.             regWidth = 1; // 1byte
        19.         }
        20.         sensorIdAttr :: sensorIdInfo {
        21.             chipName = "mxc6655xa";
        22.             chipIdRegister = 0x0f;
        23.             chipIdValue = 0x05; // 根据器件ID寄存器,读取的值,或查看相关芯片datasheet手册确认该值
        24.         }
        25.         sensorDirection {
        26.             direction = 1; // chip direction range of value:0-7
        27.             /* <sign> 1:negative  0:positive
        28.                <map> 0:AXIS_X  1:AXIS_Y  2:AXIS_Z
        29.             */
        30.             /* sign[AXIS_X], sign[AXIS_Y], sign[AXIS_Z], map[AXIS_X], map[AXIS_Y], map[AXIS_Z] */
        31.             convert = [
        32.                 0, 0, 0, 0, 1, 2,
        33.                 1, 0, 0, 1, 0, 2,
        34.                 0, 0, 1, 0, 1, 2,
        35.                 0, 1, 0, 1, 0, 2,
        36.                 1, 0, 1, 0, 1, 2,
        37.                 0, 0, 1, 1, 0, 2,
        38.                 0, 1, 1, 0, 1, 2,
        39.                 1, 1, 1, 1, 0, 2
        40.             ];
        41.         }
        42.         sensorRegConfig {
        43.             /*  regAddr: register address
        44.                 value: config register value
        45.                 len: size of value
        46.                 mask: mask of value
        47.                 delay: config register delay time (ms)
        48.                 opsType: enum SensorOpsType 0-none 1-read 2-write 3-read_check 4-update_bit
        49.                 calType: enum SensorBitCalType 0-none 1-set 2-revert 3-xor 4-left shift 5-right shift
        50.                 shiftNum: shift bits
        51.                 debug: 0-no debug 1-debug
        52.                 save: 0-no save 1-save
        53.             */
        54.             /* regAddr, value, mask, len, delay, opsType, calType, shiftNum, debug, save */
        55.             initSeqConfig = [
        56.                 0x7e,    0xb6, 0xff,   1,     5,       2,       0,        0,     0,    0,
        57.                 0x7e,    0x10, 0xff,   1,     5,       2,       0,        0,     0,    0
        58.             ];
        59.             enableSeqConfig = [
        60.                 0x7e,    0x11, 0xff,   1,     5,       2,       0,        0,     0,    0,
        61.                 0x41,    0x03, 0xff,   1,     0,       2,       0,        0,     0,    0,
        62.                 0x40,    0x08, 0xff,   1,     0,       2,       0,        0,     0,    0
        63.             ];
        64.             disableSeqConfig = [
        65.                 0x7e,    0x10, 0xff,   1,     5,       2,       0,        0,     0,    0
        66.             ];
        67.         }
        68.     }
        69. }
        70. <strong>c</strong>
        复制代码

    • 加快率差别化驱动的代码实现路径:drivers\peripheral\sensor\chipset\accel\accel_mxc6655xa.c

      • 加快率传感器差别化驱动对应的HdfDriverEntry对象,此中,Driver Entry入口函数定义如下:
        1. /* 注册加速度mxc6655xa传感器入口数据结构体对象 */
        2. struct HdfDriverEntry g_accelMxc6655xaDevEntry = {
        3.     .moduleVersion = 1, // 加速度mxc6655xa传感器模块版本号
        4.     .moduleName = "HDF_SENSOR_ACCEL_MXC6655XA", // 加速度mxc6655xa传感器模块名,要与device_info.hcs文件里加速度mxc6655xa传感器moduleName字段值一致
        5.     .Bind = Mxc6655xaBindDriver, // 加速度mxc6655xa传感器的绑定函数
        6.     .Init = Mxc6655xaInitDriver, // 加速度mxc6655xa传感器的初始化函数
        7.     .Release = Mxc6655xaReleaseDriver, // 加速度mxc6655xa传感器资源释放函数
        8. };
        9. /* 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */
        10. HDF_INIT(g_accelMxc6655xaDevEntry);
        11. <strong>c</strong>
        复制代码
      • 加快率传感器差别化驱动Bind接口实现如下:
        1. int32_t Mxc6655xaBindDriver(struct HdfDeviceObject *device)
        2. {
        3.     CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
        4.     struct Mxc6655xaDrvData *drvData = (struct Mxc6655xaDrvData *)OsalMemCalloc(sizeof(*drvData));
        5.     if (drvData == NULL) {
        6.         HDF_LOGE("%s: Malloc MXC6655XA drv data fail", __func__);
        7.         return HDF_ERR_MALLOC_FAIL;
        8.     }
        9.     drvData->ioService.Dispatch = DispatchMXC6655xa;
        10.     drvData->device = device;
        11.     device->service = &drvData->ioService;
        12.     g_mxc6655xaDrvData = drvData;
        13.     return HDF_SUCCESS;
        14. }
        15. <strong>c</strong>
        复制代码
      • 加快率传感器差别化驱动Init接口实现如下:
        1. int32_t Mxc6655xaInitDriver(struct HdfDeviceObject *device)
        2. {
        3.     int32_t ret;
        4.     struct AccelOpsCall ops;
        5.     CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
        6.     struct Mxc6655xaDrvData *drvData = (struct Mxc6655xaDrvData *)device->service;
        7.     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
        8.     drvData->sensorCfg = AccelCreateCfgData(device->property);
        9.     if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
        10.         HDF_LOGD("%s: Creating accelcfg failed because detection failed", __func__);
        11.         return HDF_ERR_NOT_SUPPORT;
        12.     }
        13.     ops.Init = NULL;
        14.     ops.ReadData = ReadMxc6655xaData;
        15.     ret = AccelRegisterChipOps(&ops);
        16.     if (ret != HDF_SUCCESS) {
        17.         HDF_LOGE("%s: Register MXC6655XA accel failed", __func__);
        18.         return HDF_FAILURE;
        19.     }
        20.     ret = InitMxc6655xa(drvData->sensorCfg);
        21.     if (ret != HDF_SUCCESS) {
        22.         HDF_LOGE("%s: Init MXC6655XA accel failed", __func__);
        23.         return HDF_FAILURE;
        24.     }
        25.     return HDF_SUCCESS;
        26. }
        27. <strong>c</strong>
        复制代码
      • 加快率传感器差别化驱动Release接口实现如下:
        1. void Mxc6655xaReleaseDriver(struct HdfDeviceObject *device)
        2. {
        3.     CHECK_NULL_PTR_RETURN(device);
        4.     struct Mxc6655xaDrvData *drvData = (struct Mxc6655xaDrvData *)device->service;
        5.     CHECK_NULL_PTR_RETURN(drvData);
        6.     if (drvData->sensorCfg != NULL) {
        7.         AccelReleaseCfgData(drvData->sensorCfg);
        8.         drvData->sensorCfg = NULL;
        9.     }
        10.     OsalMemFree(drvData);
        11. }
        12. <strong>c</strong>
        复制代码
      • 加快率传感器差别化驱动内部接口实现。
        需要开发者实现的ReadMxc6655xaData接口函数,在 Mxc6655xaInitDriver函数里面注册此函数,详细实现如下:
        1. static int32_t ReadMxc6655xaRawData(struct SensorCfgData *data, struct AccelData *rawData, uint64_t *timestamp)
        2. {
        3.     uint8_t status = 0;
        4.     uint8_t reg[ACCEL_AXIS_BUTT];
        5.     OsalTimespec time;
        6.     int32_t x;
        7.     int32_t y;
        8.     int32_t z;
        9.     (void)memset_s(&time, sizeof(time), 0, sizeof(time));
        10.     (void)memset_s(reg, sizeof(reg), 0, sizeof(reg));
        11.     CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
        12.     if (OsalGetTime(&time) != HDF_SUCCESS) {
        13.         HDF_LOGE("%s: Get time failed", __func__);
        14.         return HDF_FAILURE;
        15.     }
        16.     *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */
        17.     int32_t ret = ReadSensor(&data->busCfg, MXC6655XA_STATUS_ADDR, &status, sizeof(uint8_t));
        18.     if (ret != HDF_SUCCESS) {
        19.         HDF_LOGE("%s: data status [%u] ret [%d]", __func__, status, ret);
        20.         return HDF_FAILURE;
        21.     }
        22.     ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_X_LSB_ADDR, &reg[ACCEL_X_AXIS_LSB], sizeof(uint8_t));
        23.     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
        24.     ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_X_MSB_ADDR, &reg[ACCEL_X_AXIS_MSB], sizeof(uint8_t));
        25.     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
        26.     ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_Y_LSB_ADDR, &reg[ACCEL_Y_AXIS_LSB], sizeof(uint8_t));
        27.     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
        28.     ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_Y_MSB_ADDR, &reg[ACCEL_Y_AXIS_MSB], sizeof(uint8_t));
        29.     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
        30.     ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_Z_LSB_ADDR, &reg[ACCEL_Z_AXIS_LSB], sizeof(uint8_t));
        31.     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
        32.     ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_Z_MSB_ADDR, &reg[ACCEL_Z_AXIS_MSB], sizeof(uint8_t));
        33.     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
        34.     x = SensorConvertData(reg[ACCEL_X_AXIS_MSB], reg[ACCEL_X_AXIS_LSB]);
        35.     y = SensorConvertData(reg[ACCEL_Y_AXIS_MSB], reg[ACCEL_Y_AXIS_LSB]);
        36.     z = SensorConvertData(reg[ACCEL_Z_AXIS_MSB], reg[ACCEL_Z_AXIS_LSB]);
        37.     rawData->x = x;
        38.     rawData->y = y;
        39.     rawData->z = z;
        40.     return HDF_SUCCESS;
        41. }
        42. /* 读取加速度的event数据,在 Mxc6655xaInitDriver函数里面注册此函数,将数据传给加速度抽象驱动 */
        43. int32_t ReadMxc6655xaData(struct SensorCfgData *cfg, struct SensorReportEvent *event)
        44. {
        45.     int32_t ret;
        46.     struct AccelData rawData = { 0, 0, 0 };
        47.     static int32_t tmp[ACCEL_AXIS_NUM];
        48.     CHECK_NULL_PTR_RETURN_VALUE(cfg, HDF_ERR_INVALID_PARAM);
        49.     CHECK_NULL_PTR_RETURN_VALUE(event, HDF_ERR_INVALID_PARAM);
        50.     ret = ReadMxc6655xaRawData(cfg, &rawData, &event->timestamp);
        51.     if (ret != HDF_SUCCESS) {
        52.         HDF_LOGE("%s: MXC6655XA read raw data failed", __func__);
        53.         return HDF_FAILURE;
        54.     }
        55.     event->sensorId = SENSOR_TAG_ACCELEROMETER;
        56.     event->option = 0;
        57.     event->mode = SENSOR_WORK_MODE_REALTIME;
        58.     rawData.x = rawData.x * MXC6655XA_ACC_SENSITIVITY_2G;
        59.     rawData.y = rawData.y * MXC6655XA_ACC_SENSITIVITY_2G;
        60.     rawData.z = rawData.z * MXC6655XA_ACC_SENSITIVITY_2G;
        61.     tmp[ACCEL_X_AXIS] = (rawData.x * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
        62.     tmp[ACCEL_Y_AXIS] = (rawData.y * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
        63.     tmp[ACCEL_Z_AXIS] = (rawData.z * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
        64.     ret = SensorRawDataToRemapData(cfg->direction, tmp, sizeof(tmp) / sizeof(tmp[0]));
        65.     if (ret != HDF_SUCCESS) {
        66.         HDF_LOGE("%s: MXC6655XA convert raw data failed", __func__);
        67.         return HDF_FAILURE;
        68.     }
        69.     event->dataLen = sizeof(tmp);
        70.     event->data = (uint8_t *)&tmp;
        71.     return ret;
        72. }
        73. <strong>c</strong>
        复制代码


调测验证

驱动开发完成后,在传感器单元测试里面开发自测试用例,验证驱动根本功能。测试环境采用开发者自测试平台。


  • 参考测试代码如下:
    1. #include <cmath>
    2. #include <cstdio>
    3. #include <unistd.h>
    4. #include <gtest/gtest.h>
    5. #include <securec.h>
    6. #include "hdf_base.h"
    7. #include "osal_mem.h"
    8. #include "osal_time.h"
    9. #include "sensor_if.h"
    10. #include "sensor_type.h"
    11. using namespace testing::ext;
    12. const struct SensorInterface *g_sensorDev = nullptr;
    13. /* 创建回调函数 */
    14. static int32_t SensorDataCallback(const struct SensorEvents *event)
    15. {
    16.     if (event == NULL) {
    17.         return HDF_FAILURE;
    18.     }
    19.     float *data = (float*)event->data;
    20.     printf("time [%lld] sensor id [%d] x-[%f] y-[%f] z-[%f]\n\r", event->timestamp,
    21.         event->sensorId, (*data), *(data + 1), *(data + 2));
    22.     return HDF_SUCCESS;
    23. }
    24. class HdfSensorTest : public testing::Test {
    25. public:
    26.     static void SetUpTestCase();
    27.     static void TearDownTestCase();
    28.     void SetUp();
    29.     void TearDown();
    30. };
    31. /* 用例执行前,初始化传感器接口实例 */
    32. void HdfSensorTest::SetUpTestCase()
    33. {
    34.     g_sensorDev = NewSensorInterfaceInstance();
    35.     if (g_sensorDev == nullptr) {
    36.         printf("test sensor get module instance failed\n\r");
    37.     }
    38. }
    39. /* 用例资源释放 */
    40. void HdfSensorTest::TearDownTestCase()
    41. {
    42.     if (g_sensorDev != nullptr) {
    43.         FreeSensorInterfaceInstance();
    44.         g_sensorDev = nullptr;
    45.     }
    46. }
    47. void HdfSensorTest::SetUp()
    48. {
    49. }
    50. void HdfSensorTest::TearDown()
    51. {
    52. }
    53. HWTEST_F(HdfSensorTest,TestAccelDriver_001, TestSize.Level0)
    54. {
    55.     int ret;
    56.     struct SensorInformation *sensorInfo = NULL;
    57.     int32_t count = 0;
    58.     int32_t sensorInterval = 200000000; /* 数据采样率设置200毫秒,单位纳秒 */
    59.     int32_t reportInterval = 400000000;
    60.     /* 2.订阅者注册传感器数据回调处理函数 */
    61.     ret = g_sensorDev->Register(TRADITIONAL_SENSOR_TYPE, SensorDataCallback);
    62.     if (ret != 0) {
    63.         return;
    64.     }
    65.     printf("Register success\n");
    66.     /* 3.获取设备支持的Sensor列表 */
    67.     ret = g_sensorDev->GetAllSensors(&sensorInfo, &count);
    68.     if (ret != 0) {
    69.         return;
    70.     }
    71.     printf("GetAllSensors count: %d\n", count);
    72.     for (int i = 0; i < count; i++)
    73.     {
    74.         printf("sensor [%d]: sensorName: %s, vendorName: %s, sensorTypeId: %d, sensorId: %d\n", i,
    75.                sensorInfo[i].sensorName, sensorInfo[i].vendorName, sensorInfo[i].sensorTypeId, sensorInfo[i].sensorId);
    76.     }
    77.     for (int i = 0; i < count; i++)
    78.     {
    79.         /* 4.设置传感器采样率 */
    80.         ret = g_sensorDev->SetBatch(sensorInfo[i].sensorId, sensorInterval, reportInterval);
    81.         if (ret != 0) {
    82.             printf("SetBatch failed\n ,ret: %d",ret);
    83.             continue;
    84.         }
    85.         printf("SetBatch success\n");
    86.         /* 5.使能传感器 */
    87.         ret = g_sensorDev->Enable(sensorInfo[i].sensorId);
    88.         if (ret != 0) {
    89.             continue;
    90.         }
    91.      printf("Enable success\n");
    92.      usleep(1000 * 1000);
    93.         /* 6.去使能传感器 */
    94.         ret = g_sensorDev->Disable(sensorInfo[i].sensorId);
    95.         if (ret != 0) {
    96.             continue;
    97.         }
    98.         printf("Disable success\n");
    99.     }
    100.     /* 7.取消传感器数据订阅函数 */
    101.     ret = g_sensorDev->Unregister(TRADITIONAL_SENSOR_TYPE, SensorDataCallback);
    102.     if (ret != 0) {
    103.         return;
    104.     }
    105.     printf("Unregister success\n");
    106. }
    107. <strong>c</strong>
    复制代码
  • 编译文件gn参考代码如下:
    1. import("//build/ohos.gni")
    2. import("//build/test.gni")
    3. import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni")
    4. module_output_path = "drivers_peripheral_sensor/sensor"
    5. ohos_unittest("sensor_test") {
    6.   module_out_path = module_output_path
    7.   sources = [ "sensor_test.cpp" ]
    8.   include_dirs = [
    9.     "//drivers/peripheral/sensor/interfaces/include",
    10.   ]
    11.   deps = [ "//drivers/peripheral/sensor/hal:hdi_sensor" ]
    12.   external_deps = [
    13.     "c_utils:utils",
    14.     "hdf_core:libhdf_utils",
    15.     "hiviewdfx_hilog_native:libhilog",
    16.   ]
    17.   cflags = [
    18.     "-Wall",
    19.     "-Wextra",
    20.     "-Werror",
    21.     "-Wno-format",
    22.     "-Wno-format-extra-args",
    23.   ]
    24.   install_enable = true
    25.   install_images = [ "vendor" ]
    26.   module_install_dir = "bin"
    27.   part_name = "unionman_products"
    28. }
    复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

海哥

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表