高通骁龙SM6225 sensor驱动架构(2)以ICM4X6XX为例

目录

  • Build
  • Src
    • sns_icm4x6xx.c
    • sns_icm4x6xx_sensor_island.c
      • init
      • deinit
      • get_sensor_uid
      • set_client_request
      • notify_event

驱动的文件目录包括build和src,build用于编译和链接驱动入口,src存储着sensor、instance的API。

Build

Import('env')
import inspect

if 'SSC_TARGET_HEXAGON_MDSP' in env['CPPDEFINES']:
  Return()
  
icm4x6xx_island_enable = False

if 'SNS_ISLAND_INCLUDE_ICM4X6XX' in env:
  icm4x6xx_island_enable = True

if 'ICM4X6XX_ENABLE_DUAL_SENSOR' in env:
  env.Append( CPPDEFINES = ['ICM4X6XX_ENABLE_DUAL_SENSOR'])
  icm4x6xx_sensor_cnt = 2
else:
  icm4x6xx_sensor_cnt = 1

if 'USES_SSC_STATIC_LIB_BUILDER' in env:
    env.AddSSCSU(inspect.getfile(inspect.currentframe()),
		 #ext_ssc_sensor = True,
		 register_func_name = "sns_register_icm4x6xx",
		 binary_lib = False,
		 cflags = ['-Wno-sign-compare', '-Wno-enum-compare'],
		 add_island_files = icm4x6xx_island_enable,
		 registration_cnt = icm4x6xx_sensor_cnt)

#------------------------------------------------------------------------------
# Scan subdirectories to find more /build folders
#------------------------------------------------------------------------------
env.LoadSoftwareUnits()

这是一个ICM4X6XX传感器的构建脚本。它用于设置构建环境和条件,并加载相关的软件单元。

在这个脚本中,首先检查是否定义了SSC_TARGET_HEXAGON_MDSP,如果是,则返回(不执行后续操作)。

接下来,根据定义的SNS_ISLAND_INCLUDE_ICM4X6XX变量,判断是否启用ICM4X6XX传感器的island模式(低功耗)。如果启用,则将icm4x6xx_island_enable设置为True。

然后,根据定义的ICM4X6XX_ENABLE_DUAL_SENSOR变量,判断是否启用双传感器模式。如果是,则将icm4x6xx_sensor_cnt设置为2,否则设置为1。

如果定义了USES_SSC_STATIC_LIB_BUILDER变量,则通过调用AddSSCSU函数来添加静态库构建选项。该函数会传递一些参数,如源文件路径、注册函数名称sns_register_icm4x6xx这个很重要,是接下来驱动的入口。

最后,通过调用LoadSoftwareUnits函数,扫描子目录以找到更多的构建文件夹。

该脚本的目的是为ICM4X6XX传感器配置构建环境,并加载相关的软件单元。

Src

由上面的注册函数sns_register_icm4x6xx,我们在src中寻找他。

sns_icm4x6xx.c

#sns_icm4x6xx.c
sns_rc sns_register_icm4x6xx(sns_register_cb const *register_api)
{
  /** Register Accel Sensor. */
  register_api->init_sensor(
    sizeof(icm4x6xx_state), &icm4x6xx_accel_sensor_api, &icm4x6xx_sensor_instance_api);

  /** Register Gyro Sensor. */
  register_api->init_sensor(
    sizeof(icm4x6xx_state), &icm4x6xx_gyro_sensor_api, &icm4x6xx_sensor_instance_api);

  /** Register Motion Accel Sensor. */
  register_api->init_sensor(
    sizeof(icm4x6xx_state), &icm4x6xx_motion_detect_sensor_api, &icm4x6xx_sensor_instance_api);

#ifdef ICM4X6XX_ENABLE_SENSOR_TEMPERATURE
  /** Register Sensor Temperature Sensor. */
  register_api->init_sensor(
    sizeof(icm4x6xx_state), &icm4x6xx_sensor_temp_sensor_api, &icm4x6xx_sensor_instance_api);
#endif

#ifdef ICM4X6XX_ENABLE_LOWG
  /** Register Free Fall Sensor. */
  register_api->init_sensor(
    sizeof(icm4x6xx_state), &icm4x6xx_free_fall_sensor_api, &icm4x6xx_sensor_instance_api);
#endif

  return SNS_RC_SUCCESS;
}

可以看到注册函数创建了5个API:

注册加速度传感器,调用register_api->init_sensor函数,并传递icm4x6xx_state结构体的大小、icm4x6xx_accel_sensor_api和icm4x6xx_sensor_instance_api作为参数。
注册陀螺仪传感器,同样调用register_api->init_sensor函数,并传递相应的参数。
注册运动加速度传感器,同样调用register_api->init_sensor函数,并传递相应的参数。
如果定义了ICM4X6XX_ENABLE_SENSOR_TEMPERATURE,则注册传感器温度传感器,同样调用register_api->init_sensor函数,并传递相应的参数。
如果定义了ICM4X6XX_ENABLE_LOWG,则注册自由落体传感器,同样调用register_api->init_sensor函数,并传递相应的参数。
返回SNS_RC_SUCCESS表示注册成功。

该函数的目的是使用提供的注册回调函数来注册ICM4X6XX传感器的各个子传感器。每个子传感器都通过调用init_sensor函数进行初始化,并传递相应的API结构体和实例结构体。

就以icm4x6xx_accel_sensor_api为例,接着往下找:

sns_icm4x6xx_sensor_island.c

在sns_icm4x6xx_sensor_island.c中找到了他的定义的结构体,类似字符驱动的ops:

sns_sensor_api icm4x6xx_accel_sensor_api = {
  .struct_len         = sizeof(sns_sensor_api),
  .init               = &icm4x6xx_accel_init,
  .deinit             = &icm4x6xx_accel_deinit,
  .get_sensor_uid     = &icm4x6xx_get_sensor_uid,
  .set_client_request = &icm4x6xx_set_client_request,
  .notify_event       = &icm4x6xx_sensor_notify_event,
};
struct_len:结构体的大小,设置为sns_sensor_api的大小。
init:指向函数icm4x6xx_accel_init的指针,用于初始化加速度传感器。
deinit:指向函数icm4x6xx_accel_deinit的指针,用于释放加速度传感器的资源。
get_sensor_uid:指向函数icm4x6xx_get_sensor_uid的指针,用于获取加速度传感器的唯一标识符。
set_client_request:指向函数icm4x6xx_set_client_request的指针,用于设置客户端请求。
notify_event:指向函数icm4x6xx_sensor_notify_event的指针,用于通知传感器事件。

该结构体变量的目的是定义和配置加速度传感器的API函数指针,以便在注册传感器时使用。

init

sns_icm4x6xx_accel_sensor.c中

sns_rc icm4x6xx_accel_init(sns_sensor *const this)
{
  icm4x6xx_state *state = (icm4x6xx_state *)this->state->state;
  sns_sensor_uid  suid  = (sns_sensor_uid)ICM_ACCEL_SUID;

#ifdef ICM4X6XX_ENABLE_DUAL_SENSOR
  state->registration_idx = this->cb->get_registration_index(this);
  INVN_LOGD(LOW, this, "accel_init reg_idx=%d", state->registration_idx);
  if (state->registration_idx)
    suid = (sns_sensor_uid)ICM_ACCEL_SUID_1;
#endif

  state->sensor = ICM4X6XX_ACCEL;
  sns_memscpy(&state->my_suid, sizeof(state->my_suid), &suid, sizeof(sns_sensor_uid));
  icm4x6xx_common_init(this);
  icm4x6xx_accel_publish_attributes(this);

  INVN_LOGD(LOW, this, "icm4x6xx_accel_init finish");

  return SNS_RC_SUCCESS;
}
通过将sns_sensor结构体的state成员转换为icm4x6xx_state类型,获取传感器的状态信息。
获取加速度传感器的唯一标识符(suid),并存储在sns_sensor结构体的my_suid成员中。如果定义了ICM4X6XX_ENABLE_DUAL_SENSOR,则根据注册索引选择不同的suid。
将传感器类型设置为ICM4X6XX_ACCEL。
调用icm4x6xx_common_init函数进行通用初始化。
调用icm4x6xx_accel_publish_attributes函数发布加速度传感器的属性。
返回SNS_RC_SUCCESS表示初始化成功。

该函数的目的是在加速度传感器上执行特定的初始化步骤,如设置传感器类型、存储传感器唯一标识符等。

看一下里面的icm4x6xx_common_init

void icm4x6xx_common_init(sns_sensor *const this)
{
  icm4x6xx_state *state = (icm4x6xx_state *)this->state->state;
  uint8_t         i     = 0;

  struct sns_service_manager *smgr = this->cb->get_service_manager(this);
#ifndef ICM4X6XX_DISABLE_DIAG_LOG
  state->diag_service = (sns_diag_service *)smgr->get_service(smgr, SNS_DIAG_SERVICE);
#endif
  state->scp_service =
    (sns_sync_com_port_service *)smgr->get_service(smgr, SNS_SYNC_COM_PORT_SERVICE);
#ifndef ICM4X6XX_DISABLE_ISLAND_MODE
  state->island_service = (sns_island_service *)smgr->get_service(smgr, SNS_ISLAND_SERVICE);
#endif

  state->sensor_client_present = false;

  if (state->sensor == ICM4X6XX_ACCEL || state->sensor == ICM4X6XX_GYRO)
  {
    // initialize axis conversion settings
    for (i = 0; i < TRIAXIS_NUM; i++)
    {
      state->common.axis_map[i].opaxis = i;
      state->common.axis_map[i].ipaxis = i;
      state->common.axis_map[i].invert = false;
    }
  }

  // initialize fac cal correction matrix to identity
  state->fac_cal_corr_mat.e00 = 1.0;
  state->fac_cal_corr_mat.e11 = 1.0;
  state->fac_cal_corr_mat.e22 = 1.0;

  SNS_SUID_LOOKUP_INIT(state->common.suid_lookup_data, NULL);

  if (state->sensor == ICM4X6XX_ACCEL)
  {
#ifndef ICM4X6XX_DISABLE_DAE
    sns_suid_lookup_add(this, &state->common.suid_lookup_data, "data_acquisition_engine");
#endif
    sns_suid_lookup_add(this, &state->common.suid_lookup_data, "interrupt");
    sns_suid_lookup_add(this, &state->common.suid_lookup_data, "async_com_port");
    sns_suid_lookup_add(this, &state->common.suid_lookup_data, "timer");
  }
#ifndef ICM4X6XX_DISABLE_REGISTRY
  sns_suid_lookup_add(this, &state->common.suid_lookup_data, "registry");
#endif

  INVN_LOGD(MED, this, "icm4x6xx common init");
}

通过将sns_sensor结构体的state成员转换为icm4x6xx_state类型,获取传感器的状态信息。
使用sns_service_manager结构体的get_service函数,获取诊断服务(sns_diag_service)、同步串口服务(sns_sync_com_port_service)和岛屿服务(sns_island_service)的指针,并存储在状态结构体中的相应成员变量中。
将传感器客户端存在标志位设置为false。
如果传感器类型是加速度传感器(ICM4X6XX_ACCEL)或陀螺仪传感器(ICM4X6XX_GYRO),则初始化轴转换设置为默认值。
初始化校准修正矩阵为单位矩阵。
初始化SUID查找表。
如果传感器类型是加速度传感器(ICM4X6XX_ACCEL),则添加数据采集引擎、中断、异步串口和定时器的SUID到SUID查找表中。
添加注册表的SUID到SUID查找表中。

该函数的目的是进行ICM4X6XX传感器的通用初始化,包括获取服务指针、设置默认参数和初始化SUID查找表等。

初始化就看到这里

deinit

sns_rc icm4x6xx_accel_deinit(sns_sensor *const this)
{
  UNUSED_VAR(this);
  return SNS_RC_SUCCESS;
}
使用UNUSED_VAR宏来标记未使用的变量this。
返回SNS_RC_SUCCESS表示释放资源成功。

关于UNUSED_VAR
笔者查阅了项目源码发现都是以下定义的

#define UNUSED_VAR(x) (void)x 

查了资料发现
UNUSED_VAR(x)宏将变量x强制转换为void类型,以避免编译器产生未使用变量的警告。这通常在函数参数中存在未使用变量时使用。通过使用该宏,可以明确地告诉编译器该变量是有意未使用的,并且不需要进行任何操作。

get_sensor_uid

static sns_sensor_uid const *icm4x6xx_get_sensor_uid(sns_sensor const *const this)
{
  icm4x6xx_state *state = (icm4x6xx_state *)this->state->state;

  return &state->my_suid;
}

这个就比较简单了根据前文**高通骁龙SM6225 sensor驱动架构(1)**中的描述拿到uid

set_client_request

struct sns_sensor_instance *icm4x6xx_set_client_request(sns_sensor *const this,
                                                        struct sns_request const *exist_request,
                                                        struct sns_request const *new_request,
                                                        bool                      remove)
{
#if (LOG_LEVEL >= LOG_LEVEL_VERBOSE)
  icm4x6xx_debug_all_request(this, exist_request, new_request, remove);
#elif (LOG_LEVEL >= LOG_LEVEL_INFO)
/* Add for disable the G sensor log print by shifu begin */
#ifdef ONTIM_ENABLE_LOG
  icm4x6xx_state *state = (icm4x6xx_state *)this->state->state;
#endif
/* Add for disable the G sensor log print by shifu end */
  INVN_LOGI(MED, this, "(0x%x)set_client_req 0x%X(%d) 0x%X(%d) rm=%d",
                  state->sensor,
                  exist_request,
                  exist_request == NULL ? 0 : exist_request->message_id,
                  new_request,
                  new_request == NULL ? 0 : new_request->message_id,
                  remove);
#endif

  icm4x6xx_update_request_queue(this, exist_request, new_request, remove);

  return icm4x6xx_handle_client_request(this, exist_request, new_request, remove);
}
如果日志级别大于等于VERBOSE级别,则调用icm4x6xx_debug_all_request函数打印详细请求信息。
否则,如果日志级别大于等于INFO级别,并且在编译时定义了ONTIM_ENABLE_LOG宏,则打印简要请求信息。
调用icm4x6xx_update_request_queue函数更新请求队列。
调用icm4x6xx_handle_client_request函数处理客户端请求,并返回sns_sensor_instance结构体的指针。

该函数的目的是根据客户端的请求来设置传感器的状态,并处理相应的请求操作。

notify_event

sns_rc icm4x6xx_sensor_notify_event(sns_sensor *const this)
{
  icm4x6xx_state *state = (icm4x6xx_state *)this->state->state;
  sns_rc          rv    = SNS_RC_SUCCESS;

#ifndef ICM4X6XX_DISABLE_ISLAND_MODE
  state->island_service->api->sensor_island_exit(state->island_service, this);
#endif

  if (!sns_suid_lookup_complete(&state->common.suid_lookup_data))
  {
#ifndef ICM4X6XX_DISABLE_ISLAND_MODE
    state->island_service->api->sensor_island_exit(state->island_service, this);
#endif
    sns_suid_lookup_handle(this, &state->common.suid_lookup_data);

#ifndef ICM4X6XX_DISABLE_REGISTRY
    if (sns_suid_lookup_get(&state->common.suid_lookup_data, "registry", NULL))
      icm4x6xx_request_registry(this);
#endif

    if (sns_suid_lookup_complete(&state->common.suid_lookup_data))
      sns_suid_lookup_deinit(this, &state->common.suid_lookup_data);
  }

#ifndef ICM4X6XX_DISABLE_POWER_RAIL
  icm4x6xx_process_timer_events(this);
#endif

#ifndef ICM4X6XX_DISABLE_DAE
  icm4x6xx_dae_if_process_sensor_events(this);
#endif

#ifndef ICM4X6XX_DISABLE_REGISTRY
  if (NULL != state->reg_data_stream)
  {
    sns_sensor_event *event;
    event = state->reg_data_stream->api->peek_input(state->reg_data_stream);
    while (NULL != event)
    {
  #ifndef ICM4X6XX_DISABLE_ISLAND_MODE
      /** All registry events can be handled in normal mode. */
      state->island_service->api->sensor_island_exit(state->island_service, this);
  #endif
      icm4x6xx_sensor_process_registry_event(this, event);

      event = state->reg_data_stream->api->get_next_input(state->reg_data_stream);
    }
  }
#endif /*ICM4X6XX_DISABLE_REGISTRY*/

  if (state->common.registry_pf_cfg_received && state->common.registry_cfg_received &&
      state->common.registry_orient_received && state->common.registry_placement_received &&
      state->common.registry_fac_cal_received)
  {
#ifndef ICM4X6XX_DISABLE_ISLAND_MODE
    /** Initial HW detection sequence is OK to run in normal mode. */
    state->island_service->api->sensor_island_exit(state->island_service, this);
#endif
    if (sns_suid_lookup_get(&state->common.suid_lookup_data, "timer", NULL))
    {
      icm4x6xx_start_hw_detect_sequence(this);
    }
  }

  return rv;
}
将传感器的状态信息存储在名为state的变量中。
如果未禁用岛屿模式(ISLAND MODE),则调用岛屿服务的API函数sensor_island_exit来退出岛屿模式。
如果SUID查找表的查询尚未完成,则继续进行查询,并在查询完成后调用sns_suid_lookup_deinit函数释放资源。
如果未禁用电源线(POWER RAIL),则调用icm4x6xx_process_timer_events函数处理定时器事件。
如果未禁用数据采集引擎(DAE),则调用icm4x6xx_dae_if_process_sensor_events函数处理传感器事件。
如果未禁用注册表(REGISTRY)并且注册表数据流(reg_data_stream)不为空,则处理注册表事件:
    通过调用数据流的API函数获取输入事件。
    循环处理所有输入事件,并调用icm4x6xx_sensor_process_registry_event函数处理每个事件。
如果已接收到注册表的配置信息(pf_cfg_received、cfg_received、orient_received、placement_received和fac_cal_received),则根据SUID查找表是否存在定时器的SUID来启动硬件检测序列。
返回rv变量的值。

该函数的目的是处理传感器的事件通知,包括处理SUID查找、定时器事件、数据采集引擎事件和注册表事件等

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