前面的博文中,我们已经接触并分析了Sensors HAL Library,sensor1 remoting layer(libsensor1)以及SensorDaemon的相关流程,这里先串一下各个部分的主要功能。

Sensor HAL Library: android的通用HAL接口,高通实现了自己的部分,相关文件为sensors_hal.cpp

sensor1 remoting layer(libsensor1): 这是一个通信库,通过该库函数提供的API可以允许客户端向SensorDaemon服务端请求消息或者接收来自服务端的消息。

SensorDaemon:用户空间的一个后台守护进程,用于监听sensor客户端的请求以及通过共享内存与DSPS通信。

这三部分的代码结构如下:

dsp架构 dsp架构图_客户端

那么DSPS是什么呢? 今天我们主要了解下DSPS架构和重要组成部分,有些知识点会涉及QMI的相关技术QCCI以及QCSI,之前的博客我们也讲解了相关的接口定义,请点击复习:

Qualcomm messaging Interface(QMI)消息定义概述

Dedicated Sensors Processor Subsystem(DSPS)

如标题所述,DSPS即Dedicated Sensors Processor Subsystem,专用传感器处理器子系统。

下面这张图完整的展示了整个Sensor模块DSPS相关的架构图,包括我们的DSPS部分。

dsp架构 dsp架构图_数据_02

我们重点从图中标注的6部分来看,各个部分主要功能是什么。

Device Driver Framework(DDF)

首先第一部分即Device Driver Framework板块。

这部分即高通的设备驱动框架,而sensor相关的代码则在adsp_proc/Sensors/ddf/下,而驱动代码则在dd路径下,DDF的主要功能如下:

    1 完成所有的环境配置

    2 支持一个驱动控制多个设备

    3 支持同一设备或类似设备的同一驱动程序的多个实例

    4同步异步数据检索

    5 支持NV参数设定

    6 驱动属性的运行时配置,如分辨率,范围及功率状态

    7 访问系统时间以便对于延时代码的执行

    8 抽象的通信接口以便于扩展

    9 memhandler,内存管理对象,用于分配释放内存

在DDF中有一个非常重要的接口我们已经在之前的相关文章中见过,即sns_ddf_driver_if_s:

typedef struct
{
    /** 
     * 初始化驱动并且开启sensor设备
     * 主要工作: 1. 分配一个驱动实例句柄 2. 打开相关设备的通信端口
     *           3. 配置驱动和设备,将设备设到默认的电源状态
     */
    sns_ddf_status_e (*init)(
        sns_ddf_handle_t*        dd_handle_ptr,
        sns_ddf_handle_t         smgr_handle,
        sns_ddf_nv_params_s*     nv_params,
        sns_ddf_device_access_s  device_info[],
        uint32_t                 num_devices,
        sns_ddf_memhandler_s*    memhandler,
        sns_ddf_sensor_e**       sensors,
        uint32_t*                num_sensors);
        
    /** 
     * 向每一个特定的sensor请求单个数据样本
     * 数据有如下两种方式返回:
     *    (1) 当读到数据的序号相匹配后立即返回
     *    (2) 在sensor需要读取几个步骤的情形下,
     *        以SNS_DDF_PENDING状态通过sns_ddf_smgr_data_notify携带数据异步返回
     */
    sns_ddf_status_e (*get_data)(
        sns_ddf_handle_t         dd_handle,
        sns_ddf_sensor_e         sensors[],
        uint32_t                 num_sensors,
        sns_ddf_memhandler_s*    memhandler,
        sns_ddf_sensor_data_s**  data);

    /**
     * 设置sensor指定的属性值
     */
    sns_ddf_status_e (*set_attrib)(
        sns_ddf_handle_t     dd_handle,
        sns_ddf_sensor_e     sensor,
        sns_ddf_attribute_e  attrib,
        void*                value);

    /**
     * 获取sensor指定的属性值
     */
    sns_ddf_status_e (*get_attrib)(
        sns_ddf_handle_t       dd_handle,
        sns_ddf_sensor_e       sensor,
        sns_ddf_attribute_e    attrib,
        sns_ddf_memhandler_s*  memhandler,
        void**                 value,
        uint32_t*              num_elems);
      
   /**
    * timer回调,初始化timer时要指定回调方法
    */
    void (*handle_timer)(sns_ddf_handle_t dd_handle, void* arg);

   /** 
    * 处理驱动中断
    */
    void (*handle_irq)(
        sns_ddf_handle_t  dd_handle,
        uint32_t          gpio_num,
        sns_ddf_time_t    timestamp);

   /**
    * 重置驱动及设备回到init状态
    */
    sns_ddf_status_e (*reset)(sns_ddf_handle_t dd_handle);

    /**
     * 运行一个指定的工厂测试,流式数据不能调用该方法
     */
    sns_ddf_status_e (*run_test)(
        sns_ddf_handle_t  dd_handle,
        sns_ddf_sensor_e  sensor,
        sns_ddf_test_e    test,
        uint32_t*         err);

    /**
     * 启动设备调度采样,通过DRI使能通知功能
     * 数据就绪后,handle_irq被调用
     */
    sns_ddf_status_e (*enable_sched_data)(
        sns_ddf_handle_t  handle,
        sns_ddf_sensor_e  sensor,
        bool              enable);

    /**
     * 根据给定的配置探测设备
     */
    sns_ddf_status_e(*probe)(
        sns_ddf_device_access_s* device_info,
        sns_ddf_memhandler_s*    memhandler,
        uint32_t*                num_sensors,
        sns_ddf_sensor_e**       sensors );
        
    /**
     * 从指定的sensor中检索一组传感器数据,异步API
     * 使用sns_ddf_data_notify_data上报数据
     */
    sns_ddf_status_e (*trigger_fifo_data)(
        sns_ddf_handle_t         dd_handle,
        sns_ddf_sensor_e         sensor,
        uint16_t                 num_samples,
        bool                     trigger_now);

    /**
     * 发送一个DAF消息到驱动,异步/同步API
     */
     sns_ddf_status_e (*process_daf_req)(
         sns_ddf_handle_t       dd_handle,
         uint32_t               req_id,
         const void*            req_msg,
         uint32_t               req_size,
         sns_ddf_memhandler_s*  memhandler,
         void**                 resp_msg,
         uint32_t*              resp_size,
         const uint8_t*         trans_id_ptr,
         void*                  conn_handle);

    /**
     * 为提供的connect handle取消所有驱动当前的DAF异步事务
     */
     void (*cancel_daf_trans)(
         sns_ddf_handle_t       dd_handle,
         void*                  conn_handle);
} sns_ddf_driver_if_s;

所有的传感器驱动程序都要实现上面的接口,并将其对应的结构体在sns_dd.h中进行声明,如:

extern sns_ddf_driver_if_s sns_dd_mpu6515_if;
extern sns_ddf_driver_if_s sns_accel_driver_fn_list;
extern sns_ddf_driver_if_s sns_accel_adxl350_driver_fn_list;
extern sns_ddf_driver_if_s sns_gyro_driver_fn_list;
extern sns_ddf_driver_if_s sns_mag_driver_fn_list;
   ………………

举例mpu6515陀螺仪传感器的驱动实现:

// Function driver API
sns_ddf_driver_if_s sns_dd_mpu6515_if =
{
  .init         = &mpu6515_init,
  .get_data     = &mpu6515_get_data,
  .set_attrib   = &mpu6515_set_attr,
  .get_attrib   = &mpu6515_get_attr,
  .handle_timer = &mpu6515_handle_timer,
  .handle_irq   = &mpu6515_handle_irq,
  .reset        = &mpu6515_reset,
  .run_test     = &mpu6515_run_test,
  .enable_sched_data = &mpu6515_enable_sched_data,
  .probe             = &mpu6515_probe,
  .trigger_fifo_data = &mpu6515_trigger_fifo_data
};
Sensor Manager(SMGR)

第二部分则是Sensor的管理器服务SMGR,其主要功能如下:

1 首先它在自己的DSPS线程中运行

2 可移植到其他目标并可扩展到其他传感器类型

3 传感器原始值使用SI单位,二进制缩放Q16,(例外:磁感应器MAG使用高斯(不是SI单位))

4 跟踪多个自主客户端请求的所有传感器需求

5 维护所有传感器设备驱动程序

  •   列出所有可用的传感器
  •   列出每个传感器的属性

6 支持客户端自定义的report可操作选择

  •   每个客户端可以指定不同的报告速率(在传感器支持的最小值和最大值以内)。
  •   每个报告可以组合任何可用传感器的组合。
  •   利用硬件滤波实现报告率和数据处理
Sensors Algorithm Manager (SAM)

第三部分则是sensor algorithm manager,sensor算法管理器,其主要功能如下:

1 提供客户端和算法之间的抽象

  • 只要算法符合简单的SAM接口集,就提供可移植性和重用性
  • 被许可者可以通过做极小的修改将自己的算法插入-使用到SAM架构中

2 是一个控制模块,管理由算法提供的服务

  • 管理算法和提供算法服务的外部客户端之间的所有交互

3 管理所有算法间的交互,例如算法X请求算法Y的数据

4 可以服务运行在不同的处理器上的客户机

  •  AP
  •  DSPS
  •  CP(modem)

5 管理算法实例的实例化和销毁

  通过下列方式进行最小内存分配:

  • 允许多个客户端共享相同的算法实例
  • 允许多个算法实例共享相同的传感器数据批处理
Sensor Message Router(SMR)

第四部分则是Sensor Message Router,光从名字就能知道他是负责消息传递用的。事实上也是这样的,SMR是一个集中在应用程序处理器(ap)、调制解调器处理器(cp/modem)上的消息传递实用程序,其主要的功能如下:

1 支持一个互操作协议,通过该协议将编码的QMI消息打包并发送到接收处理器上的对等实体。

2 支持处理器内部的软件协议,其中处理器内部的软件模块在没有QMI编码的情况下进行通信。

3 在处理器和模块分区中提供模块位置透明性

  • 模块可以在与其他模块透明的处理器之间迁移,例如保持相同的接口

4 通过部署两个优先级级别来支持消息优先级排序(现在禁用,但是当需要消息优先级时可以启用)

5 提供流量控制——SMR保证将消息传递到目的队列,或通知源模块失败。

Qualcomm Messaging Interface(QMI)

第五部分就是我们已经提到的QMI了。之所以选择QMI作为AP与BP侧的通信协议,高通给出的理由如下:

    1 QMI提供了标准的消息编解码机制

    2 QMI提供的版本支持机制,sensor框架层可以更新消息,添加新的服务且提供向后兼容

    3 QMI不会编码参数块中无用的可选部分,节约IPC通信共享内存

    4 同一个处理器间的通信不需要进行QMI编解码

    5 Sensors的接口消息都定义在IDL,这遵循命名和转换规则,并将其转换成C类型数据

Client Manager(CM)

客户端管理器主要用于向客户端提供请求接口,其内部有一个Receive thread,当有消息从SMR发过来,receive thread查找回调函数,并将该消息通过对应的cb分发至对应的客户端。其架构图如下:

dsp架构 dsp架构图_API_03

特性如下:    

    1 API设计是模块化的,引入新特性时不需要做太多修改;

    2 API依赖于高层操作系统;

    3 允许内部及外部客户端;

    4 支持模块化框架设计,用以实现路由消息到当地服务以及DSPS中的服务器;

    5 提供灵活的线程模型;

    6 为客户端提供不同优先级服务;

在上面的DSPS架构图中,我们还看到一个模块,叫Sensor Calibration Manager,这个模块主要用于sensor数据校验等,比如出厂设置时的校验等,后面分析数据校验的时候再重点关注这部分。

好了,介绍完DSPS的架构及相关的重要模块,后续的文章我们将重点分析SensoDaemon是怎样通过QCCI, QCSI通信API与DSPS端通信的,欢迎关注。