2、slpi 初始化

编程入门 行业动态 更新时间:2024-10-07 20:29:30

2、slpi <a href=https://www.elefans.com/category/jswz/34/1770206.html style=初始化"/>

2、slpi 初始化

一、slpi 入口

    slpi的入口在/AMSS/slpi_proc/ssc/utils/osa/中,我们先看下build/osa.scons

  env.AddRCInitFunc(['SSC_SLPI_USER','MODEM_MODEM','SSC_ADSP_USER'],{'sequence_group'             : 'RCINIT_GROUP_7',           # required'init_name'                  : 'sns',                      # required'init_function'              : 'sns_user_pd_init',         # required'dependencies'               : ['uTimetick','i2cbsp_init','adsppm_client','pram_mgr_clnt']})

    可以看到user部分初始化函数为sns_user_pd_init。再来看下sns_user_pd_init方法:

sns_rc sns_user_pd_init()
{if(false == sns_init_done){
/* If enabled, this will delay the framework initialization by 7 seconds.This is to easily capture init messages when SSC boots up */
#if defined(SNS_DELAY_INIT)const sns_time one_second_in_ticks = 19200000ULL;for(int i = 7; i > 0; i--){MSG_1(MSG_SSID_SNS, DBG_MED_PRIO, "init countdown %d ", i);/* sns_busy_wait is implemented as a sleep() */sns_busy_wait(one_second_in_ticks);}
#endif...sns_fw_init();...
}

特别说明:在sns_user_pd_init.c文件中添加

#define SNS_DELAY_INIT //当定义后,会delay 7s后再进行framework 初始化。一般在debug时会加上该宏,用来抓取SSC boots up时的log。

[ sns_fw_init.c 103] Init started

    这里对sensor初始化的入口即显露出来:sns_fw_init,下面开始进入sensor的framwork层。

二、framework

sns_fw_init.c文件中的sns_fw_init方法,该方法会初始化传感器的框架,包括状态、线程以及sensor驱动。

int
sns_fw_init(void)
{sns_rc rc;SNS_PRINTF(LOW, sns_fw_printf, "Init started");rc = sns_island_init();//初始化孤岛模式控制器信息SNS_ASSERT(SNS_RC_SUCCESS == rc);rc = sns_thread_manager_init();//初始化线程管理器,并开始所有工作线程。SNS_ASSERT(SNS_RC_SUCCESS == rc);rc = sns_sensor_init_fw();//sns_sensor_cb的回调函数SNS_ASSERT(SNS_RC_SUCCESS == rc);rc = sns_pwr_sleep_mgr_init();SNS_ASSERT(SNS_RC_SUCCESS == rc);rc = sns_pwr_scpm_mgr_init();SNS_ASSERT(SNS_RC_SUCCESS == rc);rc = sns_service_manager_init();SNS_ASSERT(SNS_RC_SUCCESS == rc);rc = sns_sensor_instance_init_fw();//sns_sensor_instance_cb的回到函数SNS_ASSERT(SNS_RC_SUCCESS == rc);/*register_static_sensors 所有sensor的静态注册函数。*为了方便添加和移除sensor,高通SDM845中将注册函数写到build文件中。*每次build image时,会动态的将build中注册函数写到特定的sensor注册文件中,以便register_static_sensors()使用。*/rc = register_static_sensors();SNS_ASSERT(SNS_RC_SUCCESS == rc);SNS_PRINTF(LOW, sns_fw_printf, "Init Finished");// Re-enable the thread manager; disabled by default in sns_thread_manager_initsns_thread_manager_disable(false);return 0;
}

    【register_static_sensors】我们重点来看下这个方法

1、首先看下该方法是如何添加sensor的。

    我们以高通提供的accel的driver icm206xx为例,查看icm206xx的编译脚本sns_icm206xx.scons (slpi_proc/ssc/sensors/icm206xx/build/)

if 'USES_SSC_STATIC_LIB_BUILDER' in env:if 'SSC_TARGET_HEXAGON' in env['CPPDEFINES']:env.AddSSCSU(inspect.getfile(inspect.currentframe()),flavor = ["hexagon"],register_func_name = "sns_register_icm206xx",binary_lib = False,add_island_files = icm206xx_island_enable)

     如上可知如果USES_SSC_STATIC_LIB_BUILDER有定义过,那么会往环境中添加对应下面的数据。

     特别说明register_func_name = "sns_register_icm206xx"中sns_register_icm206xx即accel传感器的入口函数。

     我们可能担心USES_SSC_STATIC_LIB_BUILDER是否有被定义,我们全局搜索下就可以发现在slpi_proc/ssc/build/ssc_static_lib_builder.py中有添加该flag

env.AddUsesFlags('USES_SSC_STATIC_LIB_BUILDER')
env.AddMethod(add_ssc_su, 'AddSSCSU')

    如上我们知道了该sensors的入口函数,但是我们如何使用呢?继续来看ssc_static_lib_builder.py,在该文件的最后有定义这样一个方法generate_static_sensor_list()

def generate_static_sensor_list(env, tags):global static_sensorsif env.IsKeyEnable(tags) is True:logger.info("generate_static_sensor_list() called with %d sensors" % len(static_sensors))#dest = os.path.join(env.subst('${SSC_ROOT}'), 'framework', 'src')#if not os.path.isdir(dest) or not os.listdir(dest):#  return Noneif len(static_sensors) == 0:logger.error("There are no static sensors?!!!")return Nonestatic_sensors_file = os.path.join(env.subst('${SSC_ROOT}'),'framework', 'src', 'sns_static_sensors.c')fo = open(static_sensors_file, "w")fo.write("/* Autogenerated file.  Manual modification is pointless. */\n\n")fo.write("#include \"sns_rc.h\"\n")fo.write("#include \"sns_register.h\"\n")fo.write("#include \"sns_types.h\"\n")fo.write("\n")for reg_func,reg_cnt in static_sensors:fo.write("sns_rc %s(sns_register_cb const *register_api);\n" % reg_func)fo.write("\nconst sns_register_entry sns_register_sensor_list[] =\n{\n")for reg_func,reg_cnt in static_sensors:fo.write(" { %s, %i},\n" % (reg_func, reg_cnt))fo.write("};\n\n")fo.write("const uint32_t sns_register_sensor_list_len = ARR_SIZE(sns_register_sensor_list);\n\n")fo.close()

    该方法的作用根据所有sensor build脚本中所有register_func_name的值,将对应的入口函数添加到sns_static_sensors.c中。

...
sns_rc sns_register_icm206xx(sns_register_cb const *register_api);
...
const sns_register_entry sns_register_sensor_list[] =
{...{ sns_register_icm206xx, 1},...
}

     至此,我们成功的将入口函数添加到sns_register_sensor_list中。

2、函数分析

static sns_rc
register_static_sensors(void)
{sns_register_cb reg_cb = (sns_register_cb){.struct_len = sizeof(reg_cb),.init_sensor = &sns_sensor_init};for(int i = 0; i < sns_register_sensor_list_len; i++){for(int j = 0; j < sns_register_sensor_list[i]t; j++){sns_isafe_list_iter iter;sns_sensor_library *library =sns_sensor_library_init(sns_register_sensor_list[i].func, j);sns_osa_lock_acquire(library->library_lock);sns_register_sensor_list[i].func(&reg_cb);library->removing = SNS_LIBRARY_ACTIVE;sns_sensor_library_start(library);sns_isafe_list_iter_init(&iter, &library->sensors, true);...}}return SNS_RC_SUCCESS;
}
  • sns_register_cb reg_cb = (sns_register_cb)

    sns_register_cb的回调函数,每个sensor driver入口函数都会调用该数据结构中.init_sensor函数。该函数的主要作用是,

    (1)判断是否是island mode

    (2)将相关数据结构加入到链表。比如library、sensors等等。

  • for(int j = 0; j < sns_register_sensor_list[i]t; j++)

    上面生成sns_static_sensors.c文件中的sns_register_sensor_list.func,即sensor注册的入口函数;然后执行。执行后就进入的sensor driver的世界。

  • sns_sensor_library_start(library);

    调用sensor_api->init函数和sensor_api->get_sensor_uid函数,分别进行初始化以及获取唯一识别ID——UID

    接下来将会进入到sensor driver中,我们继续来看。

三、sensor driver

     我们知道,sensor对应的driver文件目前均放在slpi_proc/ssc/sensors/目录下,以高通给出的demo来看下是怎样的流程。

1、build脚本

if 'SNS_ISLAND_INCLUDE_LSM6DSO' in env:lsm6dso_island_enable = True
if ('SSC_TARGET_HEXAGON' in env['CPPDEFINES']) and ('SENSORS_DD_DEV_FLAG' not in env):env.AddSSCSU(inspect.getfile(inspect.currentframe()),register_func_name = "sns_register_lsm6dso",binary_lib = False,add_island_files = lsm6dso_island_enable)if 'SENSORS_DD_DEV_FLAG' in env:ME = inspect.getfile(inspect.currentframe())MY_ROOT = os.path.dirname(os.path.dirname(ME))REMOVE_FILES = env.FindFiles(['*.*'], MY_ROOT)env.CleanPack(env['SSC_BUILD_TAGS'], REMOVE_FILES)
  • SNS_ISLAND_INCLUDE_LSM6DSO

    若存在flag=SNS_ISLAND_INCLUDE_LSM6DSO,则lsm6dso_island_enable=true,即lsm6dso被设置成island mode。Island mode有着很低的功耗。

    要想设置成Island mode,只需要在slpi_proc/ssc/build/ssc.scons中添加该flag即可

env.AddUsesFlags(['SNS_ISLAND_INCLUDE_LSM6DSO'])
  • SSC_TARGET_HEXAGON

    设置flag=SSC_TARGET_HEXAGON是动态注册,registry_func_name= ”sns_register_lsm6dso”为sensor driver的入口函数。binary_lib为是否是二进制lib,高通的一些虚拟sensor比如计步器、amd、smd等等都是以lib形式提供给customer的。customer只要调用API使用即可,不需要知道如何实现。

  • SENSORS_DD_DEV_FLAG

    flag=SENSORS_DD_DEV_FLAG是静态注册,在SDM845上使用的均为动态注册。

2、API实现文件

  • island模式下把sensor中这些API放到sns_< drv_name >_sensor_island.c中实现
//本例为sns_lsm6dso_sensor_island.c
sns_sensor_api 内容
get_sensor_uid()
set_client_request()  only for accel driver libraries
  • island模式下把sensor instance中这些API放到sns_< drv_name >_sensor_instance_island.c中实现
//本例为sns_lsm6dso_sensor_instance_island.c
sns_sensor_instance_api内容
notify_event()
set_client_config()   only for accel driver libraries
  • island模式下把所有sensor & sensor instance island中调用的函数放到sns_< drv_name >_hal_island.c中实现
//本例为sns_lsm6dso_hal_island.c
lsm6dso_com_write_wrapper()
lsm6dso_start_fifo_streaming()
and so on...
  • 把sensor中这些API放到sns_< drv_name >_sensor.c中实现
init()
deinit()
set_client_request() for non-accel driver libraries
notify_event()
  • 把sensor instance中这些API放到sns_< drv_name >_sensor_instance.c中实现
init()
deinit()
set_client_config() only for non-accel driver libraries
  • 所有sensor & sensor instance 非island中调用的函数放到sns_< drv_name >_hal.c中实现。

3、入口函数——sns_register_lsm6dso

sns_rc sns_register_lsm6dso(sns_register_cb const *register_api)
{int i = 0;/** Register Sensors */for(i = 0; i< ARR_SIZE(lsm6dso_supported_sensors) ; i++) {register_api->init_sensor(sizeof(lsm6dso_state), lsm6dso_supported_sensors[i].sensor_api,lsm6dso_supported_sensors[i].instance_api);}return SNS_RC_SUCCESS;
}

     此处可以看到init了lsm6dso_supported_sensors中的sensor和实例。对应的lsm6dso_supported_sensors中有四组api,每组包含对应的sensor和sensor instance

const lsm6dso_sensors lsm6dso_supported_sensors[ MAX_SUPPORTED_SENSORS ] = {{LSM6DSO_ACCEL, &lsm6dso_accel_sensor_api, &lsm6dso_sensor_instance_api},{LSM6DSO_GYRO, &lsm6dso_gyro_sensor_api, &lsm6dso_sensor_instance_api},{LSM6DSO_MOTION_DETECT , &lsm6dso_motion_detect_sensor_api, &lsm6dso_sensor_instance_api},{LSM6DSO_SENSOR_TEMP, &lsm6dso_sensor_temp_sensor_api, &lsm6dso_sensor_instance_api}
};

    sns_sensor_api数据结构放在sns_lsm6dso_sensor_island.c中;该部分主要是为了sensor的初始化。

    sns_sensor_instance_api数据结构放在sns_lsm6dso_sensor_instance_island.c中;该部分主要是为了sensor对应的操作。

    当前涉及到的sns_sensor_api和sns_sensor_instance_api,我们需要再关注下,这里的两个api是如何定义,定义其的文件是sns_sensor.h和sns_sensor_instance.h。

  • sns_sensor 结构定义以下内容:

    – sns_sensor_cb – SEE 框架中可由传感器访问的回调函数

        – 获取服务管理器句柄 (.get_service_manager())

        – 获取传感器的下一实例 (.get_sensor_instance())

        – 创建新实例 (.create_instance())

        – 移除既有实例 (.remove_instance())

        – 获取该传感器库支持的下一个传感器 (.get_library_sensor())

    – sns_sensor_api – 每个传感器必须实现并且仅由 SEE 框架调用的函数

        – 初始化传感器 (.init())

            – 在传感器注册过程中调用

        – 注销传感器 (.deinit())

            – 在传感器报告任意故障错误代码时调用

        – 获取唯一的传感器标识符 (.get_sensor_uid())

        – 将一个传感器的依赖传感器的有效事件通知到该传感器 (.notify_event())

        – 更新传感器的客户端请求 (.set_client_request())

    – sns_sensor_state – 传感器维护的私有状态

        – 传感器状态存储器在传感器注册过程中由 SEE 框架分配

  • sns_sensor_instance 结构定义了:

    – sns_sensor_instance_cb – SEE 框架中为可由传感器实例访问的回调函数

        – 获取服务管理器句柄 (.get_service_manager())

        – 获取与实例相关的下一客户端请求 (.get_client_request())

        – 删除实例处理过的客户端请求 (.remove_client_request())

        – 添加实例处理的客户端请求 (.add_client_request)

    – sns_sensor_instance_state – 传感器实例维护的私有状态

        – SEE 框架在创建传感器实例的过程中分配传感器实例状态存储器

    – sns_sensor_api – 每个传感器必须实现并由其传感器或 SEE 框架调用的函数

        – 初始化传感器实例 (.init())

                – 在实例创建时由 SEE 框架调用

        – 注销传感器实例 (.deinit())

                – 当传感器请求 remove_instance() 时,由 SEE 框架调用

        – 设置实例配置 (.set_client_config())

                – 由传感器调用,以设置实例配置

        – 将一个实例的依赖传感器的有效事件通知到该实例 (.notify_event())

                – 由 SEE 框架调用

    具体的,sns_sensor_api的实现放在了sns_lsm6dso_sensor_island.c

sns_sensor_api lsm6dso_accel_sensor_api =
{.struct_len         = sizeof(sns_sensor_api),.init               = &lsm6dso_accel_init,.deinit             = &lsm6dso_accel_deinit,.get_sensor_uid     = &lsm6dso_get_sensor_uid,.set_client_request = &lsm6dso_set_client_request,.notify_event       = &lsm6dso_sensor_notify_event,
};

    前面有提到sns_sensor_library_start主要是调用sensor_api->init函数和sensor_api->get_sensor_uid函数,对应的分别是:lsm6dso_accel_init,lsm6dso_get_sensor_uid

sns_rc lsm6dso_accel_init(sns_sensor *const this)
{lsm6dso_state *state = (lsm6dso_state*)this->state->state;lsm6dso_acc_publish_attributes(this);lsm6dso_init_sensor_info(this, &((sns_sensor_uid)ACCEL_SUID), LSM6DSO_ACCEL);DBG_PRINT(state->diag_service, this, LOW, __FILENAME__, __LINE__, "accel init");return SNS_RC_SUCCESS;
}
  • lsm6dso_state *state = (lsm6dso_state*)this->state->state

    此形式的应用在sensor代码中非常普遍,目的是在this指针中获取对应的state,这里即获取的lsm6dso_state。

    lsm6dso_state定义在sns_lsm6dso_sensor.h中,是sensor driver两个非常重要的数据结构之一,当然,另外一个是lsm6dso_instance_state。

    (注:虽然c语言不是面向对象语言,但底层开发处处用到面向对象的思想,this这很明显的说明sns_sensor类似于基类,不同的sensor都继承该基类,该基类数据形式都是common的,强制类型转换成每个sensor独有的数据;在C语言中只不过不叫基类而已,在这里叫做framework,在kernel中叫做core。)

  • lsm6dso_acc_publish_attributes(this)

    将accel的atrributes publish到attribute service中并保存起来。该方法中看起来涉及很多信息,但其实都是通过sns_publish_attribute方法设置一些属性。

    sns_publish_attribute参数分别代表:1,sns_sensor;2,attribute_id;3,value;4,value length;5,completed代表是否是最后一次设置的属性,若为true,后续不能修改该属性;若为false,后续可以修改该属性。

        ① sns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR,SNS_ATTR, SNS_ATTR};

        sns_std_attr_value_data是一个保存attr value的data,初始化元素为SNS_ATTR

#define SNS_ATTR sns_std_attr_value_data_init_default
#define sns_std_attr_value_data_init_default     {false, sns_std_attr_value_init_default, {{NULL}, NULL}, false, 0, false, 0, false, 0}
typedef struct _sns_std_attr_value_data {bool has_subtype;sns_std_attr_value subtype;pb_callback_t str;bool has_flt;float flt;bool has_sint;int64_t sint;bool has_boolean;bool boolean;
/* @@protoc_insertion_point(struct:sns_std_attr_value_data) */
} sns_std_attr_value_data;

    可以看到有6个SNS_ATTR,即后面有6个value[ 0 ~ 5 ],value的has_flt位均设为true,value的flt为LSM6DSO_ODR_13、LSM6DSO_ODR_26、LSM6DSO_ODR_52等。

    设置完后,通过sns_publish_attribute将attribute_id为SNS_STD_SENSOR_ATTRID_RATES publish到attribute service中。简略的介绍下sns_publish_attribute函数后续流程。

SNS_SECTION(".text.sns") void  //将函数放到.text.sns段。
sns_publish_attribute(sns_sensor *const sensor,uint32_t attribute_id, sns_std_attr_value_data const *values,uint32_t values_len, bool completed)
{size_t attribute_len = 0;sns_std_attr std_attr = (sns_std_attr)//根据前面的values填充pb_buffer_arg、填充sns_std_attr数据结构{ .attr_id = attribute_id, .value.values.funcs.encode = &sns_pb_encode_attr_cb,.value.values.arg = &((pb_buffer_arg){ .buf = values, .buf_len = values_len }) };if(pb_get_encoded_size(&attribute_len, sns_std_attr_fields, &std_attr))//获取sns_service_manager,然后通过get_service来获取attribute service{sns_service_manager *manager = sensor->cb->get_service_manager(sensor);sns_attribute_service *attribute_service =(sns_attribute_service*)manager->get_service(manager, SNS_ATTRIBUTE_SERVICE);uint8_t attribute[attribute_len];pb_ostream_t stream = pb_ostream_from_buffer(attribute, attribute_len);if(pb_encode(&stream, sns_std_attr_fields, &std_attr))//通过attribute service中api进行push_attributeattribute_service->api->publish_attribute(attribute_service, sensor,attribute, attribute_len, attribute_id, completed);// PEND: Print a message upon errors}
}

        主要根据attribute_id进行不同的处理,并将数据保存在fw_sensor->attr_info中

        ② sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_TYPE, &value, 1, false);

                publish attribute_id为SNS_STD_SENSOR_ATTRID_TYPE的value

        ③ sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_RESOLUTIONS,values, i, false);

                publish attribute_id为SNS_STD_SENSOR_ATTRID_RESOLUTIONS的value

        ④ sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT,values, i, false);

                publish attribute_id为SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT的value

        ⑤ sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT, &value, 1, false);

                publish attribute_id为SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT的value

        ⑥ sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_RANGES,values, ARR_SIZE(values), true);

                publish attribute_id为SNS_STD_SENSOR_ATTRID_RANGES的value

        ⑦ sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_API,values, ARR_SIZE(values), false);

                publish attribute_id为SNS_STD_SENSOR_ATTRID_API的value。API使用的是sns_accel.proto

  • lsm6dso_init_sensor_info(this, &((sns_sensor_uid)ACCEL_SUID), LSM6DSO_ACCEL);

        通过sns_sensor ->cb->get_service_manager来获取一个sns_service_manager的handle。sns_service_manager是可以管理所有service的数据结构。

4、发送suid request

static char def_dependency[][MAX_DEP_LENGTH] =  {"interrupt", "async_com_port", "timer", "data_acquisition_engine", "registry"
};static void init_dependencies(sns_sensor *const this)
{int i = 0;lsm6dso_state *state = (lsm6dso_state*)this->state->state;DBG_PRINT(state->diag_service, this, LOW, __FILENAME__, __LINE__, "init_dependencies sensor");for(i=0;i<ARR_SIZE(def_dependency);i++){send_suid_req(this, def_dependency[i], strlen(def_dependency[i]));}
}

    accel 所依赖的platform sensor。有interrupt、async_com_port、timer、registry等。

    再来看下send_suid_req是做什么的。

static void send_suid_req(sns_sensor *this, char *const data_type, uint32_t data_type_len)
{lsm6dsm_state *state = (lsm6dsm_state*)this->state->state;if(state->fw_stream == NULL){sns_service_manager *manager = this->cb->get_service_manager(this);sns_stream_service *stream_service =(sns_stream_service*)manager->get_service(manager, SNS_STREAM_SERVICE);stream_service->api->create_sensor_stream(stream_service, this, sns_get_suid_lookup(),&state->fw_stream);}if(state->fw_stream != NULL){size_t encoded_len;pb_buffer_arg data = (pb_buffer_arg){ .buf = data_type, .buf_len = data_type_len };uint8_t buffer[50];sns_suid_req suid_req = sns_suid_req_init_default;suid_req.has_register_updates = true;suid_req.register_updates = true;suid_req.data_type.funcs.encode = &pb_encode_string_cb;suid_req.data_type.arg = &data;sns_rc rc = SNS_RC_SUCCESS;encoded_len = pb_encode_request(buffer, sizeof(buffer), &suid_req, sns_suid_req_fields, NULL);if(0 < encoded_len){sns_request request = (sns_request){.request_len = encoded_len, .request = buffer, .message_id = SNS_SUID_MSGID_SNS_SUID_REQ };rc = state->fw_stream->api->send_request(state->fw_stream, &request);}if(0 >= encoded_len || SNS_RC_SUCCESS != rc){DBG_PRINT(state->diag_service, this, ERROR, __FILENAME__, __LINE__,"encoded_len=%d rc=%u", encoded_len, rc);}}
}

    第一次肯定进入state->fw_stream==NULL,通过获取sns_service_manager获取sns_service_type为SNS_STREAM_SERVICE的stream_service。并通过stream_service来创建一个新的sensor stream。

    接着会进入state->fw_stream != NULL,这里比较重要的是:会填充一个sns_suid_req,并通过pb_encode_request函数编码成buffer,然后继续填充sns_request,最后,通过state->fw_stream->api->send_request发送该message_id为SNS_SUID_MSGID_SNS_SUID_REQ的sns_request。后面不用说也可以知道,通过SNS_SUID_MSGID_SNS_SUID_EVENT接收的event,获取suid。可以看lsm6dso_sensor_notify_event中lsm6dso_process_suid_events函数。就是对SNS_SUID_MSGID_SNS_SUID_EVENT进行处理的。后面再详细介绍。

(注:这里为什么要详细介绍这部分,因为这部分是sensor driver 发送suid request的一个例子,所有sensor包括物理和虚拟sensor都会通过该种方式发送request的,并通过callback来解析event)

5、解析suid event

    发送完suid request后,通过.notify_event来对返回的suid event进行解码:

static sns_rc lsm6dso_sensor_notify_event(sns_sensor *const this)
{sns_rc rv = SNS_RC_SUCCESS;lsm6dso_state *state = (lsm6dso_state*)this->state->state;//获取lsm6dso_stateif((NULL != state->fw_stream &&0 != state->fw_stream->api->get_input_cnt(state->fw_stream)) ||(NULL != state->reg_data_stream &&0 != state->reg_data_stream->api->get_input_cnt(state->reg_data_stream))){lsm6dso_exit_island(this);lsm6dso_process_suid_events(this);rv = lsm6dso_process_registry_events(this);}if(rv == SNS_RC_SUCCESS){rv = lsm6dso_process_timer_events(this);}if(rv == SNS_RC_SUCCESS && LSM6DSO_ACCEL == state->sensor){if(!state->hw_is_present &&NULL != state->pwr_rail_service &&NULL != state->timer_stream &&state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_NONE){sns_time timeticks;state->rail_config.rail_vote = SNS_RAIL_ON_LPM;state->pwr_rail_service->api->sns_vote_power_rail_update(state->pwr_rail_service,this,&state->rail_config,&timeticks); /* ignored */timeticks = sns_convert_ns_to_ticks(LSM6DSO_OFF_TO_IDLE_MS * 1000 * 1000);lsm6dso_start_power_rail_timer(this, timeticks, LSM6DSO_POWER_RAIL_PENDING_INIT);}if(!state->available && state->hw_is_present && state->outstanding_reg_requests == 0){lsm6dso_exit_island(this);lsm6dso_update_siblings(this);}}return rv;
}
  • lsm6dso_exit_island先退出island,lsm6dso_process_suid_events来处理suid event.
void lsm6dso_process_suid_events(sns_sensor *const this)
{lsm6dso_state *state = (lsm6dso_state*)this->state->state;sns_data_stream *stream = state->fw_stream;sns_service_manager *service_mgr;sns_stream_service  *stream_svc;if(NULL == stream || 0 == stream->api->get_input_cnt(stream)){return;}service_mgr = this->cb->get_service_manager(this);stream_svc = (sns_stream_service*) service_mgr->get_service(service_mgr,SNS_STREAM_SERVICE);for(sns_sensor_event *event = stream->api->peek_input(stream);NULL != event;event = stream->api->get_next_input(stream)){if(SNS_SUID_MSGID_SNS_SUID_EVENT == event->message_id){sns_diag_service* diag = state->diag_service;pb_istream_t pbstream = pb_istream_from_buffer((void*)event->event, event->event_len);sns_suid_event suid_event = sns_suid_event_init_default;pb_buffer_arg data_type_arg = { .buf = NULL, .buf_len = 0 };sns_sensor_uid uid_list;sns_suid_search suid_search;suid_search.suid = &uid_list;suid_search.num_of_suids = 0;suid_event.data_type.funcs.decode = &pb_decode_string_cb;suid_event.data_type.arg = &data_type_arg;suid_event.suid.funcs.decode = &pb_decode_suid_event;suid_event.suid.arg = &suid_search;if(!pb_decode(&pbstream, sns_suid_event_fields, &suid_event)){DBG_PRINT(diag, this, ERROR, __FILENAME__, __LINE__, "pb_decode() failed");continue;}/* if no suids found, ignore the event */if(suid_search.num_of_suids == 0){continue;}/* save suid based on incoming data type name */if(0 == strncmp(data_type_arg.buf, "interrupt", data_type_arg.buf_len)){state->irq_suid = uid_list;}else if(0 == strncmp(data_type_arg.buf, "timer", data_type_arg.buf_len)){state->timer_suid = uid_list;stream_svc->api->create_sensor_stream(stream_svc, this, state->timer_suid,&state->timer_stream);if(NULL == state->timer_stream){DBG_PRINT(diag, this, ERROR, __FILENAME__, __LINE__,"process_suid_events:: Failed to create timer stream");}}else if (0 == strncmp(data_type_arg.buf, "async_com_port",data_type_arg.buf_len)){state->acp_suid = uid_list;}else if (0 == strncmp(data_type_arg.buf, "registry", data_type_arg.buf_len)){process_registry_suid(this, &uid_list);}else if (0 == strncmp(data_type_arg.buf, "data_acquisition_engine",data_type_arg.buf_len)){state->dae_suid = uid_list;}else{DBG_PRINT(diag, this, ERROR, __FILENAME__, __LINE__,"process_suid_events:: invalid datatype_name");}}}return;
}

    (1) 获取lsm6dso_state、sns_data_stream、sns_service_manager、sns_stream_service

    (2) for循环去获取sns_data_stream中的event

    (3) 针对event->message_id = SNS_SUID_MSGID_SNS_SUID_EVENT的处理。

    通过pb_istream_from_buffer函数从event中获取pb_istream_t,然后将pb_istream_t解码成suid_event形式。suid_event即为我们熟知的格式。suid_event有两个解码函数:pb_decode_string_cb用来解码data_type;pb_decode_suid_event用来解码suid。

typedef struct _sns_suid_event {pb_callback_t data_type;pb_callback_t suid;
/* @@protoc_insertion_point(struct:sns_suid_event) */
} sns_suid_event;

    (4) 解码后,根据data_type进行相应的处理,可以看到在该driver的.notify_event中只处理interrupt、timer、async_com_port、registry、data_acquisition_engine这几类sensor。

  • lsm6dso_process_timer_events

    处理message_id=lsm6dso_process_timer_events的event

static sns_rc lsm6dso_process_timer_events(sns_sensor *const this)
{...for(sns_sensor_event *event = stream->api->peek_input(stream);NULL != event;event = stream->api->get_next_input(stream)){...if(SNS_TIMER_MSGID_SNS_TIMER_SENSOR_EVENT != event->message_id){continue; /* not interested in other events */}...if(state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_INIT)   {/** Initial HW discovery is OK to run in normal mode. */lsm6dso_exit_island(this);lsm6dso_discover_hw(this);}else if(state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_SET_CLIENT_REQ)  {sns_sensor_instance *instance = sns_sensor_util_get_shared_instance(this);if(NULL != instance){...inst_state->instance_is_ready_to_configure = true;lsm6dso_reval_instance_config(this, instance, state->sensor);}}else if(state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_OFF)    {sns_sensor_instance *instance = sns_sensor_util_get_shared_instance(this);state->rail_config.rail_vote = SNS_RAIL_OFF;state->pwr_rail_service->api->sns_vote_power_rail_update(state->pwr_rail_service, this,&state->rail_config, NULL);if(NULL != instance){lsm6dso_instance_state *inst_state =  (lsm6dso_instance_state*) instance->state->state;inst_state->instance_is_ready_to_configure = false;}}sns_sensor_util_remove_sensor_stream(this, &state->reg_data_stream);state->power_rail_pend_state = LSM6DSO_POWER_RAIL_PENDING_NONE;}if(state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_NONE)   {sns_sensor_util_remove_sensor_stream(this, &state->timer_stream);}return rv;
}

    该函数中处理完timer event后,根据不同的state->power_rail_pend_state做不同的操作。

    (1) state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_INIT

    当state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_INIT时,执行退出island,discover_hw,discover_hw中,读芯片register来判断是哪颗芯片

void lsm6dso_discover_hw(sns_sensor *const this)
{sns_rc rv = SNS_RC_SUCCESS;.../**-------------------Read and Confirm WHO-AM-I------------------------*/buffer[0] = 0x0;...rv = lsm6dso_get_who_am_i(state->scp_service,state->com_port_info.port_handle, &buffer[0]);...if(rv == SNS_RC_SUCCESS&&buffer[0] == LSM6DSO_WHOAMI_VALUE){...sns_sensor_instance *instance = sns_sensor_util_get_shared_instance(this);if(instance){...// Reset Sensorrv = lsm6dso_reset_device(instance,LSM6DSO_ACCEL | LSM6DSO_GYRO | LSM6DSO_MOTION_DETECT | LSM6DSO_SENSOR_TEMP);if(rv == SNS_RC_SUCCESS){state->hw_is_present = true;}}...}...state->who_am_i = buffer[0];/**------------------Power Down and Close COM Port--------------------*/state->scp_service->api->sns_scp_update_bus_power(state->com_port_info.port_handle,false);state->scp_service->api->sns_scp_close(state->com_port_info.port_handle);state->scp_service->api->sns_scp_deregister_com_port(&state->com_port_info.port_handle);/**----------------------Turn Power Rail OFF--------------------------*/state->rail_config.rail_vote = SNS_RAIL_OFF;state->pwr_rail_service->api->sns_vote_power_rail_update(state->pwr_rail_service,this,&state->rail_config,NULL);
}

    可以看到通过lsm6dso_get_who_am_i来获取芯片信息后,再reset device,reset无论成功与否,都要close COM port,通过sns_vote_power_rail_update来关电。这部分code会在系统初始化的时候跑一遍。

    (2) state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_SET_CLIENT_REQ时,会通过函数lsm6dso_reval_instance_config发送配置信息。

    (3) state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_OFF,顾名思义——关电。并remove registry data sream。

    (4) state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_NONE时直接remove timer data stream。

  • lsm6dso_start_power_rail_timer

    发送timer的request,来控制power rail.先将state->rail_config.rail_vote 设为SNS_RAIL_ON_LPM(这种state只用在accel driver上),然后sns_vote_power_rail_update进入low power mode。然后通过lsm6dso_start_power_rail_timer发送timer的request,

    注意:pwr_rail_pend_state = LSM6DSO_POWER_RAIL_PENDING_INIT,这就与上面的No.a对应起来,会discover hw,然后再关电。

6、init对应的是deinit

sns_rc lsm6dso_accel_deinit(sns_sensor *const this)
{UNUSED_VAR(this);// Turn Sensor OFF.// Close COM port.// Turn Power Rails OFF.// No need to clear lsm6dso_state because it will get freed anyway.return SNS_RC_SUCCESS;
}

7、lsm6dso_get_sensor_uid函数,用来获取suid。

sns_sensor_uid const* lsm6dso_get_sensor_uid(sns_sensor const *const this)
{lsm6dso_state *state = (lsm6dso_state*)this->state->state;return &state->my_suid;
}

四、流程图

 

 

参考:

    高通80-p9361-3sc_d

    博客:

更多推荐

2、slpi 初始化

本文发布于:2024-02-28 01:12:39,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1767637.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:初始化   slpi

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!