QCOM Sensor SEE 分析--初始化

写在前面

17年到23年这么多年了只有几篇文章,看了几篇博客和高通文档后还是对SEE一脸懵逼,只能自己瞎JB乱看一通代码,然后再瞎JB记录一下,也不知道对不对。目标是把注册驱动时要填充的那两个结构体的东西大概是个什么鬼弄明白一下。

以基线自带的hall sensor driver为例分析

// 驱动的入口函数sns_register_bu52053nvx
sns_rc sns_register_bu52053nvx(sns_register_cb const *register_api)
{
    // 将sensor注册到sensor framework中
    //  @param1:各个sensor驱动自定义数据需要的长度,不超过1k, framework会额外分配该大小内存空间并存其首地址到state指针
    //  @param2:这里引入sensor的概念,后面介绍
    //  @param3:这里引入sensor_instance的概念,后面介绍
     register_api->init_sensor(sizeof(BU52053NVX_STATE), &bu52053nvx_sensor_api, &bu52053nvx_sensor_instance_api);

    return (SNS_RC_SUCCESS);
}

以hall sensor注册入口为切入点找到的初始化流程:sensor framework的初始化流程 

 QCOM Sensor SEE 分析--初始化_第1张图片

// step 2 的 sns_sensor_init_fw() 代码片段
// 初始化全局变量sensor_cb,在第9步hall sensor注册时赋值给它的cb,这样hall sensor驱动就可以使用这些callback函数了
sns_sensor_cb sensor_cb SNS_SECTION(".data.sns");
sns_rc sns_sensor_init_fw(void)
{
    sensor_cb = (sns_sensor_cb)
    {
        .struct_len = sizeof(sensor_cb),
        .get_service_manager = &get_service_manager,
        .get_sensor_instance = &get_sensor_instance,
        .create_instance = &sns_sensor_instance_init,
        .remove_instance = &sns_sensor_instance_deinit,
        .get_library_sensor = &get_library_sensor,
        .get_registration_index = &get_registration_index,
        .create_instance_v2 = &sns_sensor_instance_init_v2,
    };
}

// step 3 sns_sensor_instance_init_fw() 代码片段
// 和2一样只是初始化一个全局变量instance_cb,在创建相应sensor的instance时赋值给它的cb
sns_rc sns_sensor_instance_init_fw(void)
{
  instance_cb = (sns_sensor_instance_cb)
  {
    .struct_len = sizeof(instance_cb),
    .get_service_manager = &get_service_manager,
    .get_client_request = &get_client_request,
    .remove_client_request = &remove_client_request,
    .add_client_request = &add_client_request
  };

  return SNS_RC_SUCCESS;
}

// step 4 sensor_list对于driver来说是python根据编译脚本生成的,即在por.py中配置要编译的sensor
register_sensors(const sns_register_entry *sensor_list, uint32_t list_len)
{
  sns_register_cb reg_cb = (sns_register_cb)
  {
    .struct_len = sizeof(reg_cb),
    .init_sensor = &sns_sensor_init
  };

  for(int i = 0; i < list_len; i++)
  {
    for(int j = 0; j < sensor_list[i].cnt; j++)
    {
      sns_sensor_library *library = sns_sensor_library_init(sensor_list[i].func, j, sensor_list[i].is_islandLib); // 5
      sensor_list[i].func(®_cb); // 6
      sns_sensor_library_start(library);  // 10
    }
  }

}

// 调用时序图的第9步
sns_sensor_init(uint32_t state_len, struct sns_sensor_api const *sensor_api,
    struct sns_sensor_instance_api const *instance_api)
{
  sns_rc rv = SNS_RC_SUCCESS;

    sns_isafe_list_iter iter;
    sns_fw_sensor *sensor = NULL;
    sns_sensor_library *library;
    bool island_sensor = is_island_sensor(sensor_api, instance_api);
    
    // 需要为attr和state分配空间这里计算大小
    // hall驱动中经常见到的state就是这东西BU52053NVX_STATE    *state       = (BU52053NVX_STATE *)this->state->state;
    // hall驱动中bu52053nvx_publish_attributes(sns_sensor *const this)中attr
    uint8_t attr_idx = 0;
    uint8_t state_idx = 0;
    size_t alloc_size = sns_cstruct_extn_compute_total_size(sizeof(*sensor),2,
      ALIGN_8(sizeof(struct sns_sensor_state) + state_len) + ALIGN_8(sizeof(struct sns_attribute_info)));

    // 根据sns_bu52053nvx.scons中是否配置add_island_files = bu52053nvx_island_enable
    // 来分配内存,如以下高通文档描述的6225平台island的空间大小
    // ADSP subsystem《SM6225 Sensors Overview》Total Island memory - 1 MB, 
    // PoR configuration:512 KB for sensors, CoreBSP, and existing dependencies
    // 512 KB for audio and relevant CoreBSP dependencies
    // 非island的内存位于DDR,之前有项目添加过一个功能,在开启该功能时,把添加的这个驱动
    // 配置到island会额外增加0.3mA的电流,非island增加5mA,而机器在飞行模式待机时的电流4mA
    if(island_sensor)
    {
      sensor = sns_malloc(SNS_HEAP_ISLAND, alloc_size);
    }
    if(NULL == sensor)
    {
      sensor = sns_malloc(SNS_HEAP_MAIN, alloc_size);
      island_sensor = false;
    }

    sns_cstruct_extn_init(&sensor->extn, sensor, sizeof(*sensor), 2);
    attr_idx = sns_cstruct_extn_setup_buffer(&sensor->extn, sizeof(struct sns_attribute_info));
    state_idx = sns_cstruct_extn_setup_buffer(&sensor->extn, sizeof(struct sns_sensor_state) + state_len);

    sensor->sensor.cb = &sensor_cb;
    sensor->sensor.sensor_api = sensor_api;
    sensor->sensor.instance_api = instance_api;

   // 通过cstruct获取分配的state空间地址
    sensor->sensor.state = (struct sns_sensor_state*)
      sns_cstruct_extn_get_buffer(&sensor->extn, state_idx);
    sensor->sensor.state->state_len = state_len;

    // 通过cstruct获取分配的attr空间地址
    sensor->attr_info = sns_cstruct_extn_get_buffer(&sensor->extn, attr_idx);

   // 调用sns_attr_svc_sensor_init(sns_fw_sensor *sensor)
    for(uint8_t i = 0; i < ARR_SIZE(state_init); i++)
      if(NULL != state_init[i].init)
        state_init[i].init(sensor);

    sensor->island_operation = island_sensor ?
      SNS_ISLAND_STATE_IN_ISLAND : SNS_ISLAND_STATE_NOT_IN_ISLAND;

    sensor->removing = false;
    sensor->library = library;
    sensor->diag_config.config = default_datatype;

    // data_stream这个后续分析
    sns_isafe_list_init(&sensor->data_streams);
    sns_isafe_list_init(&sensor->sensor_instances);
    sns_isafe_list_item_init(&sensor->list_entry, sensor);

    sns_osa_lock_acquire(library->library_lock);
    sns_isafe_list_iter_init(&iter, &library->sensors, false);
    sns_isafe_list_iter_insert(&iter, &sensor->list_entry, true);
    sns_osa_lock_release(library->library_lock);
  
  return rv;
}

类图

代码一通看下来SEE是按面向对象写的,但是用的C语言实现,既然这样那按照C++去理解,那在这里就瞎JB画个类图。

sns_sensor           sns_fw_sensor            sns_fw_sensor              sns_fw_sensor_instance

QCOM Sensor SEE 分析--初始化_第2张图片

// sns_sensor 的定义
typedef struct sns_sensor {
    /* Functions which call back into the framework; provided by the Framework */
    struct sns_sensor_cb const *cb;
    
    /* API implementation provided for and by this Sensor */
    struct sns_sensor_api const *sensor_api;
    
    /* The associated API for a Sensor Instance created for and by this Sensor. */
    struct sns_sensor_instance_api const *instance_api;
    
    /* State space allocated by the Framework for the sole use of the Sensor developer. */
    struct sns_sensor_state *state;
} sns_sensor;

// 驱动中可以看到参数的传递都是sns_sensor 而不是 sns_fw_sensor
static sns_rc bu52053nvx_hall_init(sns_sensor *const this)
{
    BU52053NVX_STATE *state = (BU52053NVX_STATE *)this->state->state;
}

// sns_fw_sensor 的定义
typedef struct sns_fw_sensor
{
   sns_sensor sensor;
   ...
}

// 在framework中使用sns_fw_sensor 而不是 sns_sensor
get_sensor_instance(sns_sensor const *this, bool first)
{
   sns_fw_sensor *sensor = (sns_fw_sensor*)this;
   ...
}

1. sns_sensor是基类,sns_fw_sensor 继承自 sns_sensor,和C++中继承的内存布局一致

2. 在hall驱动中定义的私有数据通过sns_sensor成员state访问

3. sns_fw_sensor分为两部分,开放给dirver用的放在sns_sensor中,不想被driver知晓的部分放在sns_fw_sensor,

framework调用driver的函数时把参数sns_fw_sensor强制转换为sns_sensor,driver拿到的只有sns_sensor部分的内存,无法访问framework部分

4. sns_sensor_cb为framework开放给driver调用的接口

5. sns_sensor_api中的init() 和 deinit() 是sns_sensor这个构造和析构函数

理解 sns_sensor 和 sns_sensor_instance 的关系

以下为高通文档中对 sensor 和 sensor instance 的说明

  • sensor是异步数据的生产者和/或消费者。
  • 每个sensor可以实例化一次或多次sensor instance。

                    每个sensor instance都使用特定的配置进行操作。

                    对instance的任何数据请求可能会导致创建sensor instance实例或共享现有实例。

  • sensor instance实例是按需创建的,由sensor决定。

                    sensor完全管理其对应sensor instance的生命周期和配置,并负责向客户端发送配置更新和初始状态事件。

                   强烈建议供应商以尽可能少的sensor instance来处理所有客户请求。

                   sensor instance生成的data stream将发送给所有活动client。

  • 单个sensor instance实例可以由多个sensor共享和配置。

                  这种操作模式通常用于硬件传感器的组合驱动程序,其中sensor代表支持的数据类型,而sensor instance是唯一与硬件通信和配置的模块。

想想当时学C++的时候,老是听到这样一句话:类是对一类事物的抽象,比如说小汽车抽象为Car这个类,一台奔驰车就是具体实例。

所以我认为这是高通设计sns_sensor 和 sns_sensor_instance 的初衷。get_sensor_uid放在sensor中,说明不依赖于instance,属于sensor的static 方法。

遗留

sensor instance, data stream, event service

你可能感兴趣的:(c语言)