三:Sensor SLPI层代码分析

在学习SLPI侧代码前我们先了解下SEE的registry&config。
registry 放在/persist/sensors/registry/registry中,它是通过config生成的,是给SLPI解析的文件。
config 放在/persist/sensors/registry/config中,它需要RD修改更新,用来生成register以便SLPI使用。每次config update后,即会更新registry。每次reboot后,会重新加载registry。

config都是以.json为后缀的文件,每个物理sensor会有两个json文件,一个是包含所有平台的特殊配置文件,另一个是sensor driver的特殊配置文件。

如果config文件不存在并且sensor driver支持默认参数,则sensor library会将默认参数填充到registry中。

sensor driver可以通过发送request给registry sensor来随时更新registry。

下面来详细介绍下json文件:以高通给的demo文件为例。
/persist/sensors/registry/config/sdm845_lsm6dsm_0.json

{"config":{"hw_platform": ["HDK"],"soc_id": ["341"]},"lsm6dso_0_platform":{"owner": "lsm6dso",".config":{"owner": "lsm6dso","bus_type":{ "type": "int", "ver": "0","data": "1"},"bus_instance":{ "type": "int", "ver": "0","data": "2"},"slave_config":{ "type": "int", "ver": "0","data": "0"},"min_bus_speed_khz":{ "type": "int", "ver": "0","data": "0"},"max_bus_speed_khz":{ "type": "int", "ver": "0","data": "3300"},...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

上面config为platform-specific configuration, 格式为:target _ sensor_name _ hadware_id


上图说明了platform-specific config中每个元素的含义。


上图为可以用作SPI or I2C的GPIO,这些GPIO是可以复用的,
举个栗子:
bus_type:1,bus_instance:2,slave_config:1
意思为:使用SPI bus,QUP为2,即使用SSC_6、SSC_7、SSC_8、SSC_9、SSC_10、SSC_11这6组GPIO。slave_config为0,即设备连在SSC_6(QUP2 lane4)上。

若bus_type :0 ,其他不变的话。
意思为:使用I2C bus,QUP为2,即使用SSC_2、SSC_3,I2C2这组I2C。slave address为0x01。


上图为sensor中断GPIO。高通强烈建议用户使用中断GPIO时与上图一一对应,所以accel的中断pin为117,mag的中断pin为119。

//sdm845_icm206xx_0.json
"dri_irq_num":{ "type": "int", "ver": "0","data": "117"},//sdm845_ak0991x_0.json
"dri_irq_num":{ "type": "int", "ver": "0","data": "119"},
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

下面说下driver-specific configuration
/persist/sensors/registry/config/lsm6dsm_0.json

{"config":{"hw_platform": ["QRD", "MTP", "Dragon", "Surf", "HDK"],"soc_id": ["336", "341"]},"lsm6dso_0":{"owner": "lsm6dso",".accel":{"owner": "lsm6dso",".config":{"owner": "lsm6dso","is_dri":{ "type": "int", "ver": "0","data": "1"},"hw_id":{ "type": "int", "ver": "0","data": "0"},"res_idx":{ "type": "int", "ver": "0","data": "2"},"sync_stream":{ "type": "int", "ver": "0","data": "0"}}},".gyro":{"owner": "lsm6dso",".config":{"owner": "lsm6dso","is_dri":{ "type": "int", "ver": "0","data": "1"},"hw_id":{ "type": "int", "ver": "0","data": "0"},"res_idx":{ "type": "int", "ver": "0","data": "4"},"sync_stream":{ "type": "int", "ver": "0","data": "0"}}},...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

格式为: sensor_name_hadware_id


上图说明了driver-specific config中每个元素的含义。

了解完registry & config,下面开始学习SLPI层Sensor。

/slpi/ssc/utils/osa/中为整个slpi的入口函数,分析build下osa.scons。可以看到user部分初始化函数为sns_user_pd_init。

 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']})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

该init函数为高通开放给custormer的入口函数,可以理解为main函数。

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();...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

这里我们不关心其他init,只研究sns_fw_init。我们开始进入SEE的framework层。
1.framework层
code放在/slpi/ssc/framework/中。

另外还要注意一下,SNS_DELAY_INIT这个宏,当定义后,会delay 7s后再进行framework 初始化。一般在debug时会加上该宏,用来抓取SSC boots up时的log。

//sns_fw_init.c
int sns_fw_init(void)
{...rc = sns_sensor_init_fw();                      //No.1...rc = sns_sensor_instance_init_fw();             //No.2...rc = register_static_sensors();                 //No.3...return 0;
}//sns_sensor.c
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,};return SNS_RC_SUCCESS;
}//sns_sensor_instance.c
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

在sns_fw_init函数中我们着重分析上面三个函数,
No.1中是sns_sensor_cb的回调函数,这里需要注意下,后面分析sensor driver时会非常频繁的用到这些回调函数。
No.2中是sns_sensor_instance_cb的回到函数,同样需要注意下,后面使用也很频繁。
No.3中是所有sensor的静态注册函数。需要说明下,这个静态注册非常有意思。为了方便添加和移除sensor,高通SDM845中将注册函数写到build文件中,每次build image时,会动态的将build中注册函数写到特定的sensor注册文件中,以便register_static_sensors()使用。

举个例子,以accel的driver icm206xx为例,进入/slpi/ssc/sensors/icm206xx/中,看下build脚本sns_icm206xx.scons。

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

上面的含义是,若USES_SSC_STATIC_LIB_BUILDER在环境中,则往环境中添加如下数据。。。。可以看到register_func_name = “sns_register_icm206xx”,后面解析可以知道sns_register_icm206xx为accel sensor的入口函数,这里仅说明一下。

那么build环境中是否有USES_SSC_STATIC_LIB_BUILDER呢?
在SLPI build脚本ssc_static_lib_builder.py中中可以看到有加入该flag。

  env.AddUsesFlags('USES_SSC_STATIC_LIB_BUILDER')env.AddMethod(add_ssc_su, 'AddSSCSU')
  • 1
  • 2

那如何使用sensor入口函数sns_register_icm206xx呢?
还是在ssc_static_lib_builder.py中,有个函数generate_static_sensor_list()

if "sns_register_suid_sensor" == register_func_name:static_sensors.insert(0, (register_func_name, registration_cnt))else:static_sensors.append((register_func_name, registration_cnt))#==============================================================================
# Generates sns_static_sensors.c
#==============================================================================
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

这个函数的作用是根据所有sensor的build脚本xxx.scons中入口函数,生成一个新的文件sns_static_sensors.c。
ok,编译完后git diff下,看到了生成的sns_static_sensors.c中新加了sns_register_icm206xx。

 sns_rc sns_gyro_cal_register(sns_register_cb const *register_api);sns_rc sns_gyro_rot_matrix_register(sns_register_cb const *register_api);
+sns_rc sns_register_icm206xx(sns_register_cb const *register_api);sns_rc sns_register_interrupt(sns_register_cb const *register_api);const sns_register_entry sns_register_sensor_list[] ={{ sns_gyro_rot_matrix_register, 1},
+ { sns_register_icm206xx, 1},{ sns_register_interrupt, 1},}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

我想大家应该都了解了吧,这样做的目的就是很快捷的添加或删除driver。

回到No.3,register_static_sensors函数中,

static sns_rc register_static_sensors(void)
{sns_register_cb reg_cb = (sns_register_cb)             //No.1{.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].cnt; j++)      //No.2{...sns_register_sensor_list[i].func(&reg_cb);sns_sensor_library_start(library);                        //No.3...}}return SNS_RC_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

No.1中,sns_register_cb的回调函数,每个sensor driver入口函数都会调用该数据结构中.init_sensor函数。该函数的主要作用是,(1)判断是否是island mode,后面会将什么是island mode。(2)将相关数据结构加入到链表。比如library、sensors等等。
No.2中,上面生成sns_static_sensors.c文件中的sns_register_sensor_list.func,即sensor注册的入口函数;然后执行。执行后就进入的sensor driver的世界。
No.3中,sns_sensor_library_start,主要调用sensor_api->init函数和sensor_api->get_sensor_uid函数,至于sensor_api是什么,后面会讲,这里不懂先略过。

Ok,framework层初始化流程部分讲了一部分,下面开始讲sensor driver层,在sensor driver层讲解中顺带会说下相关的framework层,这样可以更深入的了解SEE框架。

2.sensor driver层
code放在/slpi/ssc/sensors/中
我们研究高通提供的demo sensor driver code:lsm6dso。

进入qcom_firware->slpi_proc->ssc->sensors->lsm6dso目录后,首先下看下build脚本。

####lsm6dso.scons######
Import('env')
import os,inspectif ('SSC_TARGET_HEXAGON_MDSP' in env['CPPDEFINES']):Return()lsm6dso_island_enable = Falseif 'SNS_ISLAND_INCLUDE_LSM6DSO' in env:                                      #No.1lsm6dso_island_enable = True
if ('SSC_TARGET_HEXAGON' in env['CPPDEFINES']) and ('SENSORS_DD_DEV_FLAG' not in env):env.AddSSCSU(inspect.getfile(inspect.currentframe()),                      #No.2register_func_name = "sns_register_lsm6dso",binary_lib = False,add_island_files = lsm6dso_island_enable)if 'SENSORS_DD_DEV_FLAG' in env:                                                   #No.3ME = 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

No.1中若存在flag=SNS_ISLAND_INCLUDE_LSM6DSO,则lsm6dso_island_enable=true,即lsm6dso被设置成island mode。何为Island mode,高通解释island有着很低的功耗。

如何设置成为island mode呢?

在build脚本上,我们需要设置flag,在build/ssc.scons中加入。

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

在sensor driver code上,我们我要
(1) 把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
  • 1
  • 2
  • 3
  • 4

(2)把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
  • 1
  • 2
  • 3
  • 4

(3)把所有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...
  • 1
  • 2
  • 3
  • 4

Normal情况哪些API放在哪些文件中呢?
(1) 把sensor中这些API放到sns_< drv_name >_sensor.c中实现

init()
deinit()
set_client_request() for non-accel driver libraries
notify_event()
  • 1
  • 2
  • 3
  • 4

(2) 把sensor instance中这些API放到sns_< drv_name >_sensor_instance.c中实现

init()
deinit()
set_client_config() only for non-accel driver libraries
  • 1
  • 2
  • 3

(3)所有sensor & sensor instance 非island中调用的函数放到sns_< drv_name >_hal.c中实现。

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

No.3中设置flag=SENSORS_DD_DEV_FLAG是静态注册,在SDM845上使用的均为动态注册。

接着来到入口函数中:

//sns_lsm6dso.c
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;
}//sns_lsm6dso_sensor_island.c
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}
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

上面入口函数中注册四组api,每组api包含sns_sensor_api 和 sns_sensor_instance_api。
sns_sensor_api数据结构放在sns_lsm6dso_sensor_island.c中;该部分主要是为了sensor的初始化
sns_sensor_instance_api数据结构放在sns_lsm6dso_sensor_instance_island.c中;该部分主要是为了sensor对应的操作

以LSM6DSO_ACCEL为例:
1: sns_sensor_api定义在sns_sensor.h中,结构如下:

typedef struct sns_sensor_api
{uint32_t struct_len;/*** Initialize a Sensor to its hard-coded/default state.  Generate* requests for any other necessary data (e.g. Registry data).  A call to* sns_sensor_api::deinit will precede any subsequent calls to this function.** @param[i] this Sensor reference** @return* SNS_RC_INVALID_STATE - Requisite hardware not available* SNS_RC_POLICY - Required services not available* SNS_RC_SUCCESS*/sns_rc (*init)(sns_sensor *const this);/*** Release all hardware and software resources associated with this Sensor** @param[i] this Sensor reference** @return* SNS_RC_INVALID_STATE - Error occurred: some resource could not be released* SNS_RC_SUCCESS*/sns_rc (*deinit)(sns_sensor *const this);/*** Each Sensor must have a globally unique identifier; each algorithm* and driver will define their own. If a Sensor may be loaded twice on the* system, it is responsible for returning two unique values.  These must* not change across device reboots.** @param[i] this Sensor reference** @return The unique identifier for this Sensor*/sns_sensor_uid const* (*get_sensor_uid)(sns_sensor const *const this);/*** Notification to the client that some data has been received.** The client must use the sns_event_service to obtain this data* for processing.** @return* SNS_RC_INVALID_STATE - A client error occurred; Framework shall destroy*                        client* SNS_RC_NOT_AVAILABLE - A transitory error occurred; Framework shall*                        remove all outstanding input* SNS_RC_INVALID_LIBRARY_STATE - A permanent error occurred; Framework shall*                        destroy all sensors present in the client library* SNS_RC_SUCCESS*/sns_rc (*notify_event)(sns_sensor *const this);/*** Add, remove, or update a client's request to this Sensor.** For each new request sent by a client, the Sensor (via this function)* will receive the new_request.  If the client has an active request* (which is to be replaced), it will be specified in exist_request.** If 'remove' is false:* A client has sent a new request to this Sensor.  Determine if any* active Sensor Instance in sns_sensor_cb::get_sensor_instance()* will handle this request.  If yes, use add_client_request to associate* this new request with that existing Instance.** If not, instantiate and initialize a new Sensor Instance with the* appropriate configuration, and similarly use add_client_request.** In either case, if exist_request is provided and new_request provides* a superceding configuration, exist_request must be removed via* remove_client_request.** If 'remove' is true:* Remove this client request by sns_sensor_instance_cb::remove_client_request;* re-arrange any remaining client requests/sensor instances.** In all cases, if the result of the operation is a Sensor Instance with* zero clients, sns_sensor_cb::remove_instance must be called.** @param[i] this Sensor reference* @param[i] exist_request If this request comes-in over an existing stream,*                       this is the existing request.* @param[i] new_request New request just received* @param[i] remove If the client no longer requires this data** @return* The Sensor Instance chosen to handle this new client.  NULL if an error* occurred during processing; or if "remove" was true.* Or sns_instance_no_error (see above).*/struct sns_sensor_instance* (*set_client_request)(sns_sensor *const this,struct sns_request const *exist_request,struct sns_request const *new_request,bool remove);
} sns_sensor_api;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

上面每个函数都有注释,这里不再解释。

//sns_lsm6dso_sensor_island.c , sns_sensor_api放在island文件中,上面island介绍中有解释。
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,
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Initialization
上面说到sns_sensor_library_start,主要调用sensor_api->init函数和sensor_api->get_sensor_uid函数,下面分别介绍.init和.get_sensor_uid函数。
(1)lsm6dso_accel_init

//sns_lsm6dso_accel_sensor.c
sns_rc lsm6dso_accel_init(sns_sensor *const this)
{lsm6dso_state *state = (lsm6dso_state*)this->state->state;                   //No.1lsm6dso_acc_publish_attributes(this);                                                    //No.2lsm6dso_init_sensor_info(this, &((sns_sensor_uid)ACCEL_SUID), LSM6DSO_ACCEL); //No.3DBG_PRINT(state->diag_service, this, LOW, __FILENAME__, __LINE__, "accel init");return SNS_RC_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

No.1中:此形式应用非常广泛,同this指针中获取lsm6dso_state。
lsm6dso_state定义在sns_lsm6dso_sensor.h中,是sensor driver两个非常重要的数据结构之一,当然,另外一个是lsm6dso_instance_state。

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

No.2中:比较重要,将accel的atrributes publish到attribute service中并保存起来。

void lsm6dso_acc_publish_attributes(sns_sensor *const this)
{const char type[] = "accel";const uint32_t active_current[3] = {25, 85, 150}; //uAconst uint32_t sleep_current = 3; //uAlsm6dso_publish_def_attributes(this);{sns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR,     //No.aSNS_ATTR, SNS_ATTR/*, SNS_ATTR, SNS_ATTR,SNS_ATTR*/};values[0].has_flt = true;values[0].flt = LSM6DSO_ODR_13;values[1].has_flt = true;values[1].flt = LSM6DSO_ODR_26;values[2].has_flt = true;values[2].flt = LSM6DSO_ODR_52;values[3].has_flt = true;values[3].flt = LSM6DSO_ODR_104;values[4].has_flt = true;values[4].flt = LSM6DSO_ODR_208;values[5].has_flt = true;values[5].flt = LSM6DSO_ODR_416;//QC currently we are limiting to 416/*values[6].has_flt = true;values[6].flt = LSM6DSO_ODR_833;values[7].has_flt = true;values[7].flt = LSM6DSO_ODR_1660;values[8].has_flt = true;values[8].flt = LSM6DSO_ODR_3330;values[9].has_flt = true;values[9].flt = LSM6DSO_ODR_6660;*/sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_RATES,values, ARR_SIZE(values), false);}{                                                                                                      //No.bsns_std_attr_value_data value = sns_std_attr_value_data_init_default;value.str.funcs.encode = pb_encode_string_cb;value.str.arg = &((pb_buffer_arg){ .buf = type, .buf_len = sizeof(type) });sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_TYPE, &value, 1, false);}{                                                                                                 //No.csns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR};int i;for(i = 0; i < ARR_SIZE(values); i++){values[i].has_flt = true;values[i].flt = lsm6dso_accel_resolutions[i];}sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_RESOLUTIONS,values, i, false);}{                                                                                                 //No.dsns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR};int i;for(i = 0; i < ARR_SIZE(active_current); i++){values[i].has_sint = true;values[i].sint = active_current[i];}sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT,values, i, false);}{                                                                                            //No.esns_std_attr_value_data value = sns_std_attr_value_data_init_default;value.has_sint = true;value.sint = sleep_current; //uAsns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT, &value, 1, false);}{                                                                                          //No.fsns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR};sns_std_attr_value_data range1[] = {SNS_ATTR, SNS_ATTR};range1[0].has_flt = true;range1[0].flt = LSM6DSO_ACCEL_RANGE_2G_MIN;range1[1].has_flt = true;range1[1].flt = LSM6DSO_ACCEL_RANGE_2G_MAX;values[0].has_subtype = true;values[0].subtype.values.funcs.encode = sns_pb_encode_attr_cb;values[0].subtype.values.arg =&((pb_buffer_arg){ .buf = range1, .buf_len = ARR_SIZE(range1) });sns_std_attr_value_data range2[] = {SNS_ATTR, SNS_ATTR};range2[0].has_flt = true;range2[0].flt = LSM6DSO_ACCEL_RANGE_4G_MIN;range2[1].has_flt = true;range2[1].flt = LSM6DSO_ACCEL_RANGE_4G_MAX;values[1].has_subtype = true;values[1].subtype.values.funcs.encode = sns_pb_encode_attr_cb;values[1].subtype.values.arg =&((pb_buffer_arg){ .buf = range2, .buf_len = ARR_SIZE(range2) });sns_std_attr_value_data range3[] = {SNS_ATTR, SNS_ATTR};range3[0].has_flt = true;range3[0].flt = LSM6DSO_ACCEL_RANGE_8G_MIN;range3[1].has_flt = true;range3[1].flt = LSM6DSO_ACCEL_RANGE_8G_MIN;values[2].has_subtype = true;values[2].subtype.values.funcs.encode = sns_pb_encode_attr_cb;values[2].subtype.values.arg =&((pb_buffer_arg){ .buf = range3, .buf_len = ARR_SIZE(range3) });sns_std_attr_value_data range4[] = {SNS_ATTR, SNS_ATTR};range4[0].has_flt = true;range4[0].flt = LSM6DSO_ACCEL_RANGE_16G_MIN;range4[1].has_flt = true;range4[1].flt = LSM6DSO_ACCEL_RANGE_16G_MAX;values[3].has_subtype = true;values[3].subtype.values.funcs.encode = sns_pb_encode_attr_cb;values[3].subtype.values.arg =&((pb_buffer_arg){ .buf = range4, .buf_len = ARR_SIZE(range4) });sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_RANGES,values, ARR_SIZE(values), true);}{                                                                                                  //No.gsns_std_attr_value_data values[] = {SNS_ATTR};char const proto1[] = "sns_accel.proto";values[0].str.funcs.encode = pb_encode_string_cb;values[0].str.arg = &((pb_buffer_arg){ .buf = proto1, .buf_len = sizeof(proto1) });sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_API,values, ARR_SIZE(values), false);}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128

看似好多东西啊,其实这些东西都是简单的参数。就是lsm6dso driver中accel的一些属性。
sns_publish_attribute参数分别代表:1,sns_sensor;2,attribute_id;3,value;4,value length;5,completed代表是否是最后一被设置的属性,若为true,后续不能修改该属性;若为false,后续可以修改该属性。

No.a中,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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

可以看到有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_attribute_util.c
SNS_SECTION(".text.sns") void                                                      //No.a
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)                          //No.b{ .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))              //No.c{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))                          //No.dattribute_service->api->publish_attribute(attribute_service, sensor,attribute, attribute_len, attribute_id, completed);// PEND: Print a message upon errors}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

No.a 中 SNS_SECTION(“.text.sns”),将函数放到.text.sns段。
No.b 中根据前面的values填充pb_buffer_arg、填充sns_std_attr数据结构。

typedef struct _sns_std_attr {int32_t attr_id;sns_std_attr_value value;
/* @@protoc_insertion_point(struct:sns_std_attr) */
} sns_std_attr;
  • 1
  • 2
  • 3
  • 4
  • 5

No.c 中获取sns_service_manager,然后通过get_service来获取attribute service。
No.d 中通过attribute service中api进行push_attribute。

SNS_SECTION(".text.sns") static sns_rc
publish_attribute(sns_attribute_service *this, struct sns_sensor *sensor,void const *attribute, uint32_t attribute_len, sns_attribute_id attribute_id,bool completed)
{UNUSED_VAR(this);UNUSED_VAR(completed);sns_list_iter iter;sns_fw_sensor *fw_sensor = (sns_fw_sensor*)sensor;                      //No.asns_attribute *new_attr;sns_mem_heap_id heap =(SNS_STD_SENSOR_ATTRID_TYPE == attribute_id ||SNS_STD_SENSOR_ATTRID_VENDOR == attribute_id)? SNS_HEAP_ISLAND : SNS_HEAP_MAIN;SNS_ISLAND_EXIT();new_attr = sns_malloc(heap, sizeof(*new_attr) + attribute_len);if(SNS_HEAP_ISLAND == heap && NULL == new_attr){new_attr = sns_malloc(SNS_HEAP_MAIN, sizeof(*new_attr) + attribute_len);fw_sensor->island_operation = SNS_ISLAND_STATE_ISLAND_DISABLED;}SNS_ASSERT(NULL != new_attr);sns_list_item_init(&new_attr->list_entry, new_attr);new_attr->id = attribute_id;new_attr->value_len = attribute_len;sns_memscpy(&new_attr->value, attribute_len, attribute, attribute_len);for(sns_list_iter_init(&iter, &fw_sensor->attr_info->attributes, true);NULL != sns_list_iter_curr(&iter);sns_list_iter_advance(&iter)){sns_attribute *attr =(sns_attribute*)sns_list_item_get_data(sns_list_iter_curr(&iter));if(attr->id == attribute_id){sns_list_iter_remove(&iter);sns_free(attr);break;}}sns_list_iter_insert(&iter, &new_attr->list_entry, false);process_special_attributes(new_attr, fw_sensor);          //No.breturn SNS_RC_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

No.a中有个重要的数据结构sns_fw_sensor,该数据结构定义在sns_fw_sensor.h,每个sensor都有自己的sns_fw_sensor。将sns_sensor地址赋给sns_fw_sensor,所以sns_fw_sensor第一个成员为sns_sensor,而且sns_fw_sensor只用在framework层,不开放给sensor开发者使用。

No.b中process_special_attributes继续:

SNS_SECTION(".text.sns") static void
process_special_attributes(sns_attribute *new_attr, sns_fw_sensor *fw_sensor)
{if(SNS_STD_SENSOR_ATTRID_AVAILABLE == new_attr->id)   {bool available = (bool)decode_attribute(new_attr, &pb_decode_attr_value_cb);if(available != sns_attr_info_get_available(fw_sensor->attr_info)){char data_type[32];sns_attr_info_get_data_type(fw_sensor->attr_info, data_type, sizeof(data_type));sns_attr_info_set_available(fw_sensor->attr_info, available);sns_suid_sensor_apprise(data_type);}sns_diag_register_sensor(fw_sensor);}else if(SNS_STD_SENSOR_ATTRID_TYPE == new_attr->id){sns_attr_priority priority = { false, false };char const *data_type =(char*)decode_attribute(new_attr, &pb_decode_attr_value_cb);SNS_ASSERT(NULL != data_type);sns_attr_info_set_data_type(fw_sensor->attr_info, data_type);for(uint8_t i = 0; i < ARR_SIZE(event_priority_datatypes); i++){if(0 == strcmp(data_type, event_priority_datatypes[i])){priority.event_priority = true;break;}}for(uint8_t i = 0; i < ARR_SIZE(req_priority_datatypes); i++){if(0 == strcmp(data_type, req_priority_datatypes[i])){priority.req_priority = true;break;}}sns_attr_info_set_priority(fw_sensor->attr_info, priority);}else if(SNS_STD_SENSOR_ATTRID_VENDOR == new_attr->id){char const *vendor = (char*)decode_attribute(new_attr, &pb_decode_attr_value_cb);sns_attr_info_set_vendor(fw_sensor->attr_info, vendor);}else if(SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR == new_attr->id &&!sns_attr_info_get_is_physical_sensor(fw_sensor->attr_info)){bool physical_sensor = (bool)decode_attribute(new_attr, &pb_decode_attr_value_cb);sns_attr_info_set_is_physical_sensor(fw_sensor->attr_info, physical_sensor);}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

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

Ok,上面关于sns_publish_attribute大概介绍完毕,有兴趣的童鞋可以仔细研究,没有兴趣的话不影响大局,可以略过不看,只需记得attribte参数放进sns_fw_sensor->attr_info中,以便后续使用!

回到lsm6dso_acc_publish_attributes中。
No.b中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_TYPE的value。
No.c中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_RESOLUTIONS的value。
No.d中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT的value。
No.e中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT的value。
No.f中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_RANGES的value。
No.g中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_API的value。API使用的是sns_accel.proto。

回到lsm6dso_accel_init的函数lsm6dso_init_sensor_info中,
首先介绍几个数据结构。之前我们知道有个struct sns_sensor,sns_sensor有个成员为struct sns_sensor_cb const*cb我们没有介绍过。

//sns_sensor.h
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 an Sensor Instances 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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
//sns_sensor.h
typedef struct sns_sensor_cb
{uint32_t struct_len;/*** Get a reference to the Service Manager.  With this object, a reference* to any other utility service can be obtained.*  * @param[i] this Sensor reference*  * @return Service Manager reference*/struct sns_service_manager* (*get_service_manager)(sns_sensor const *this);/*** Return the next Sensor Instance associated with this Sensor.*  * Each Sensor has a list of associated Sensor Instances; entries are added* to that list within calls to 'create_instance', and removed from the* list when it services no client requests.*  * Each call to this function iterates over the list, and returns the next* entry.  NULL is returned at the end of the list, or if the list is empty.*  * @param[i] this Sensor reference* @param[i] first Return the first instance; reset the internal iterator*                 Must be called first to initialize iteration*  * @return Next Sensor Instance associated with this Sensor*/struct sns_sensor_instance* (*get_sensor_instance)(sns_sensor const *this,bool first);/*** Allocate and initialize a new Sensor Instance to be associated with this* Sensor.  Will call sns_sensor_instance::init.*  * @note Direct pointers to the returned value should not be saved.*  * @param[i] this Sensor reference* @param[i] stateLen Allocation size for sns_sensor_instance::state*  * @return Newly created Sensor Instance*/struct sns_sensor_instance* (*create_instance)(sns_sensor *this,uint32_t state_len);/*** Remove and deallocate a Sensor Instance.  Will call* sns_sensor_instance::deinit.*  * @param[i] instance Instance received within set_client_request*/void (*remove_instance)(struct sns_sensor_instance *instance);/*** Return the next Sensor associated with this library.*  * Each Sensor is a member of a library; each library may contain several* Sensors.  Sensors may be removed from a library upon errors, but no* entries are added after Framework initialization has completed.*  * Each call to this function iterates over the list, and returns the next* entry.  NULL is returned at the end of the list, or if the list is empty.*  * This function is intended to be used by Sensors which share physical* hardware with another sensor, and hence must share state/instances.*  * @param[i] this Sensor reference* @param[i] first Return the first sensor; reset the internal iterator;*                 Must be called first to initialize iteration*  * @return Next Sensor associated with this library.*/struct sns_sensor* (*get_library_sensor)(sns_sensor const *this,bool first);/*** If multiple copies of this Sensor Library have been registered with SEE,* this returns the index (starting at '0') of this particular copy.  See* parameter registration_cnt of env.AddSSCSU.*  * @param[i] this Sensor reference*  * @return Library registration index*/uint32_t (*get_registration_index)(sns_sensor const *this);
} sns_sensor_cb;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

sns_sensor_cb是通过SEE framework 提供来给sensor使用的callback。其中包含5个函数,分别是

  • .get_service_manager():用来获取service manager handle。
  • .get_sensor_instance():用来获取sensor的下一个instance。
  • .create_instance():创建新的instance。
  • .remove_instance():移除存在的instance。
  • .get_library_sensor():通过sensor library 获取另一个sensor的support。

No.3中:填充lsm6dso_state,
通过sns_sensor ->cb->get_service_manager来获取一个sns_service_manager的handle。sns_service_manager是可以管理所有service的数据结构。

然后在介绍下init_dependencies比较重要:

//sns_lsm6dso_sensor.c
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]));}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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)
{lsm6dso_state *state = (lsm6dso_state*)this->state->state;if(state->fw_stream == NULL)          //No.a{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)               //No.b{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);}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

No.a中:首先介绍个数据结构sns_data_stream

//sns_data_stream.h
typedef struct sns_data_stream
{struct sns_data_stream_api *api;
} sns_data_stream;typedef struct sns_data_stream_api
{uint32_t struct_len;/*** Send a request to some other service/Sensor.  This request may* update or replace the existing stream, depending on the Sensor* specification.** @param[io] data_stream Data stream on which to send the request* @param[i] Request to be sent; Framework will copy request** @return* SNS_RC_INVALID_TYPE - Request ID not valid* SNS_RC_INVALID_STATE - Stream is no longer available; create again* SNS_RC_SUCCESS*/sns_rc (*send_request)(sns_data_stream *data_stream,sns_request *request);/*** Initiate a flush on the connection associated with sensorUID.** @note This is a helper function; clients may also initiate a flush* by generating a flush request message, and sending it via send_request.** @param[io] data_stream Data stream on which to initiate the flush** @return* SNS_RC_INVALID_STATE - Stream is no longer available; create again* SNS_RC_SUCCESS*/sns_rc (*initiate_flush)(sns_data_stream *data_stream);/*** Retrieve a pointer to the oldest unprocessed input sample associated with* this data stream from the event queue.  This event is a single, logical* sample, as produced and published by the source Sensor.** @note Multiple sequential calls to this function will return the same* pointer.** @param[io] data_stream Data stream from which to get an event** @return Next unprocessed event on the queue; NULL if no events remain*/sns_sensor_event* (*peek_input)(sns_data_stream *data_stream);/*** Remove the current event from the input queue (the event that would* be returned via peek_input).  Return the next unprocessed event from the* event queue.** Once this function returns, there is no means to retrieve the removed* Event again; the data has been freed, and its memory should not be* accessed.** @param[io] data_stream Data stream from which to get an event** @return The next unprocessed event on the queue (after the removal occurs)*         NULL if no further events remain*/sns_sensor_event* (*get_next_input)(sns_data_stream *data_stream);/*** Lookup the current number of input pending on this data stream.  This* value may change at any time, and should not be treated as precise.** @note Do no rely on this value to assume valid input from peek_input.** @param[io] data_stream Data stream from which to get the input count** @return Number of input events (aka samples) available for processing*/uint32_t (*get_input_cnt)(sns_data_stream *data_stream);
} sns_data_stream_api;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88

上面注释很清楚了,不再解释。
第一次很定进入state->fw_stream==NULL,通过获取sns_service_manager获取sns_service_type为SNS_STREAM_SERVICE的stream_service。并通过stream_service来创建一个新的sensor stream。

No.b中:接着会进入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进行处理的。后面再详细介绍。

Ok,lsm6dso_accel_init解析完毕。
(注:这里为什么要详细介绍这部分,因为这部分是sensor driver 发送suid request的一个例子,所有sensor包括物理和虚拟sensor都会通过该种方式发送request的,并通过callback来解析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;              //No.1if((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))) //No.2{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);                   //No.3}if(rv == SNS_RC_SUCCESS && LSM6DSO_ACCEL == state->sensor){                                                           //No.4if(!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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

No.1中获取lsm6dso_state
No.2中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;  //No.asns_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);   //No.bNULL != 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;     //No.cpb_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))   //No.d{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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

上面为lsm6dso_process_suid_events函数,所有处理event的函数都与此类似。
No.a中:获取lsm6dso_state、sns_data_stream、sns_service_manager、sns_stream_service。
No.b中:比较重要,for循环去获取sns_data_stream中的event。
另一种写法:

sns_sensor_event *event = stream->api->peek_input(stream);
while(NULL != event)
{if(SNS_SUID_MSGID_SNS_SUID_EVENT == event->message_id){..............}...........
}
event = stream->api->get_next_input(stream);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

No.c中:针对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;
  • 1
  • 2
  • 3
  • 4
  • 5

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

回到lsm6dso_sensor_notify_event函数中:
No.3: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)   //No.a{/** 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)  //No.b{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)    //No.c{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)   //No.d{sns_sensor_util_remove_sensor_stream(this, &state->timer_stream);}return rv;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

该函数中处理完timer event后,根据不同的state->power_rail_pend_state做不同的操作,
No.a是:当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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

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

No.b:state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_SET_CLIENT_REQ时,会通过函数lsm6dso_reval_instance_config发送配置信息。

No.c:state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_OFF,顾名思义——关电。并remove registry data sream。
No.d:state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_NONE时直接remove timer data stream。

回到lsm6dso_sensor_notify_event中:
No.4:主要是在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,然后再关电。

(2)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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

(3)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;
}
  • 1
  • 2
  • 3
  • 4
  • 5

sensor driver初始化流程如下图:

Ok,初始化是每个sensor driver一开跑的code,通过初始化可以获取hardware信息,初始化系统资源,解析registry config等等,为sensor driver 下一步Activation提供了可靠的保障。

Activation
(4)lsm6dso_set_client_request函数,用来设置来自client的request。并创建sensor instance。
set_client_request函数的解释如下:
该函数是用来add、remove、update来自client的request。

如果remove为true:通过sns_sensor_instance_cb::remove_client_request来删除这个client,并重排来自client的request和sensor_instances。

如果remove设为false:分为两种处理方式:i,若是一个new request ; ii,若是一个已经存在的request。

可以看到在sns_stream_service.c的handle_req中,set_client_request的remove参数为false的。在handle_stream_destroy中,set_client_request的remove参数为true。

下面分步解析lsm6dso_set_client_request的code。

sns_sensor_instance* lsm6dso_set_client_request(sns_sensor *const this,struct sns_request const *exist_request,struct sns_request const *new_request,bool remove)
{lsm6dso_state *state = (lsm6dso_state*)this->state->state;sns_sensor_instance *instance = sns_sensor_util_get_shared_instance(this);   //No.1sns_diag_service* diag = state->diag_service;  sns_time on_timestamp;sns_time delta;bool reval_config = false;...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

No.1中通过sns_sensor_util_get_shared_instance来查找sensor共享的instance。许多物理sensor共享一个单独instance,通过该函数查找该instance,若存在,则返回该instance;若不存在,则返回NULL。

if(remove){if(NULL == instance) {                           //No.2DBG_PRINT(diag, this, ERROR, __FILENAME__, __LINE__,"lsm6dso_set_client_request:: Instance not available! Returning!");return instance;}...lsm6dso_instance_state *inst_state =(lsm6dso_instance_state*)instance->state->state;inst_state->config_sensors |= state->sensor;instance->cb->remove_client_request(instance, exist_request);    //No.3if(exist_request->message_id != SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG)  //No.4{lsm6dso_reval_instance_config(this, instance, state->sensor);}else    //No.5{lsm6dso_instance_state *inst_state =(lsm6dso_instance_state*)instance->state->state;...//If a factory self test was run, update the registry & sensor->stateif(inst_state->self_test_info.update_registry){DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,"Updating registry and sensor state with new calibration values");//copy to sensor stateif(LSM6DSO_ACCEL == inst_state->self_test_info.sensor){sns_memscpy(state->fac_cal_bias, sizeof(state->fac_cal_bias),inst_state->accel_registry_cfg.fac_cal_bias, sizeof(inst_state->accel_registry_cfg.fac_cal_bias));}else if(LSM6DSO_GYRO == inst_state->self_test_info.sensor){sns_memscpy(state->fac_cal_bias, sizeof(state->fac_cal_bias),inst_state->gyro_registry_cfg.fac_cal_bias, sizeof(inst_state->gyro_registry_cfg.fac_cal_bias));}//Update flag in sensor_state to indicate which registry is to be updated//write registryinst_state->registry_reset.request = false;lsm6dso_sensor_write_output_to_registry(this, instance);// Set the flag to false indicating that the registry is updatedinst_state->self_test_info.update_registry = false;}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

在分析remove这路前,先了解下sns_sensor_instance中的sns_sensor_instance_cb的callback函数吧,下面我们介绍了sns_sensor中的sns_sensor_cb callback函数。

//sns_sensor_instance.h
typedef struct sns_sensor_instance
{/* Functions which call back into the framework; provided by the Framework */struct sns_sensor_instance_cb const *cb;/* State space allocated by the Framework for the sole use of the Sensor* Instance developer. */struct sns_sensor_instance_state *state;
} sns_sensor_instance;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
//sns_sensor_instance.h
typedef struct sns_sensor_instance_cb
{uint32_t struct_len;/*** Get a reference to the Service Manager.  With this object, a reference* to any other utility service can be obtained.** @param[i] this Sensor Instance reference** @return Service Manager reference*/struct sns_service_manager* (*get_service_manager)(sns_sensor_instance *this);/*** Return the next client request associated with this Sensor Instance and* SUID.** Each Sensor Instance has a list of client requests per SUID which it is* servicing.  Entries are added via calls to add_client_request; removed* via remove_client_request.** Each call to this function iterates over the list, and returns the next* entry.  NULL is returned at the end of the list, or if the list is empty.** @note An Instance may be handling client requests for multiple* (related) Sensors; must use SUID parameter to filter.** @param[i] this Sensor Instance reference* @param[i] suid Sensor associated with this Instance* @param[i] first Return the first request; reset the internal iterator*                 Must be called first to initialize iteration** SNS_RC_NOT_AVAILABLE - The Framework is not aware of SUID* SNS_RC_SUCCESS*/struct sns_request const* (*get_client_request)(sns_sensor_instance *this,sns_sensor_uid const *suid,bool first);/*** Remove a client request from this Sensor Instance.** @param[i] this Sensor Instance reference* @param[i] request Client request to be removed*/void (*remove_client_request)(sns_sensor_instance *this,struct sns_request const *request);/*** Assign this Sensor Instance to service the client request.** @note This function may only be given sns_request objects received* from sns_sensor_api::set_client_request.** @note The SUID of the recepient Sensor will be noted upon addition;* this SUID must be used within get_client_request.** @param[i] this Sensor Instance reference* @param[i] request Client request to be added*/void (*add_client_request)(sns_sensor_instance *this,struct sns_request const *request);
} sns_sensor_instance_cb;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

四个函数分别如下:

  • .get_service_manager():获取service manger的handle
  • .get_client_request():获取与instance相关联的下一次client request。
  • .remove_client_request():通过instance移除一个client的request handle。
  • .add_client_request():通过instance添加一个client request handle。

然后就可以继续分析remove这路的代码了。
No.2:在remove instance时,若instance为NULL,instance都为NULL了还remove什么呀,直接return NULL。
No.3:当instance不为NULL时,执行instance->cb->remove_client_request(instance, exist_request),remove一个client request,当然这个client request是exist_requset是旧的request。
No.4:然后判断旧的request的message_id即exist_request->message_id是否为SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG;若不为,则会通过lsm6dso_reval_instance_config函数发送所有的HW Resources给instance,做最后的处理。因为,一旦走到remove分支,framework将调用instance中的deinit()来摧毁该instance,在调deinit()前需要将所有的Hw资源发送给instance,以便让deinit()摧毁。这样摧毁的才更彻底。

No.5:走为SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG这路,说明正在做self-test,首先判断是否reconfig_postpone是否为true,若为true,说明在self-test时有延缓重新配置configure的需求(reconfigure),那不用说了,都要摧毁instance了,现在还不做,什么时候做呀,于是Do it now。即执行lsm6dso_reval_instance_config函数。

接着,就开始写registry了,若update_registry为true,说明factory self test在运行,Ok,不要运行了,可以结束了,赶紧写registry。于是通过lsm6dso_sensor_write_output_to_registry函数将accel calibration的数据accel_registry_cfg.fac_cal_bias、gyro calibration的数据gyro_registry_cfg.fac_cal_bias写入/persisit/sensors/registry/registry/lsm6dso_0_platform.accel.fac_cal和lsm6dso_0_platform.gyro.fac_cal中以便以后使用。

#define LSM6DSO_REG_PLATFORM_FAC_CAL_ACCEL  "lsm6dso_0_platform.accel.fac_cal"
#define LSM6DSO_REG_PLATFORM_FAC_CAL_GYRO   "lsm6dso_0_platform.gyro.fac_cal"
bool lsm6dso_sensor_write_output_to_registry(sns_sensor *const this,sns_sensor_instance *const instance)
{...char accel_name[] = LSM6DSO_REG_PLATFORM_FAC_CAL_ACCEL;char gyro_name[] = LSM6DSO_REG_PLATFORM_FAC_CAL_GYRO;sns_registry_write_req write_req = sns_registry_write_req_init_default;...if(((inst_state->self_test_info.sensor == LSM6DSO_ACCEL) && !(inst_state->registry_reset.request)) || ((inst_state->registry_reset.sensor_type == LSM6DSO_ACCEL) && (inst_state->registry_reset.request))){name_data = (pb_buffer_arg){ .buf = accel_name, .buf_len = strlen(accel_name) + 1 };}...write_req.name.funcs.encode = &pb_encode_string_cb;write_req.name.arg = &name_data;write_req.data.items.funcs.encode = &sns_send_to_registry_persist_cb;write_req.data.items.arg = instance;...encoded_len = pb_encode_request(buffer, sizeof(buffer),&write_req, sns_registry_write_req_fields, NULL);if(0 < encoded_len){sns_request request = (sns_request){.request_len = encoded_len, .request = buffer,.message_id = SNS_REGISTRY_MSGID_SNS_REGISTRY_WRITE_REQ };state->reg_data_stream->api->send_request(state->reg_data_stream, &request);}return true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

因为这是demo code,所以写的比较复杂,在正常情况下没有那么繁琐,如下即可。

if(remove){if(NULL != instance)          {instance->cb->remove_client_request(instance, exist_request);xxxx_reval_instance_config(this, instance, state->sensor);if(exist_request->message_id == SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG){/** Write bias into registry when client was removed */if(inst_state->update_fac_cal_in_registry){...xxxxx_update_registry(this, instance, sensor_type);inst_state->update_fac_cal_in_registry = false;}}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

remove分析完了,下面分析else分支:else分支分为两个一个是instance != NULL、另一个是instance == NULL。下面code可以说目前不属于任何分支,只是一个小小的过滤。

else
{if(NULL != instance)      //No.6{lsm6dso_instance_state *inst_state =(lsm6dso_instance_state*)instance->state->state;if(inst_state->self_test_info.test_alive){DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,"Self test is running. Ignoring new request! ");return NULL;  // Return without honouring any request for any sensor streaming}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

No.6中:若instance != NULL,并且self_test_info.test_alive == true,说明目前正处于self-test,Ok,任何request都忽略。即return NULL。该段code过滤掉所有在self-test中的请求,这样不会打断factory calibration。

下面开始正式处理两个分支了。先分析instance == NULL的情况。

 if(NULL == instance){if(state->sensor == LSM6DSO_GYRO)                 //No.7{state->rail_config.rail_vote = SNS_RAIL_ON_NPM;}else{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,&on_timestamp);delta = sns_get_system_time() - on_timestamp;                //No.8// Use on_timestamp to determine correct Timer value.if(delta < sns_convert_ns_to_ticks(LSM6DSO_OFF_TO_IDLE_MS*1000*1000)) {DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,"lsm6dso_set_client_request:: start power rail timer");lsm6dso_start_power_rail_timer(this,sns_convert_ns_to_ticks(LSM6DSO_OFF_TO_IDLE_MS*1000*1000) - delta,LSM6DSO_POWER_RAIL_PENDING_SET_CLIENT_REQ);} else {// rail is already ONstate->power_rail_pend_state = LSM6DSO_POWER_RAIL_PENDING_NONE;reval_config = true;}/** create_instance() calls init() for the Sensor Instance */ //No.9instance = this->cb->create_instance(this,sizeof(lsm6dso_instance_state));/* If rail is already ON then flag instance OK to configure */   if(reval_config){lsm6dso_instance_state *inst_state =(lsm6dso_instance_state*)instance->state->state;inst_state->instance_is_ready_to_configure = true;}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

这路比较简单,
因为instance == NULL,所有要创建一个新的instance。
No.7:因为accel可以工作在low power mode下,所有和gyro有区分。然后通过sns_vote_power_rail_update 改变上电状态。
No.8:sns_get_system_time获取系统的滴答时间,获取系统时间戳和上电时的时间戳的差值delta。若差值小于100ms,说明没有上电,于是通过lsm6dso_start_power_rail_timer上电。若差值大于100ms,说明已经上电,设置state->power_rail_pend_state为LSM6DSO_POWER_RAIL_PENDING_NONE。

值得一提的是:lsm6dso_start_power_rail_timer会发送request,可以通过lsm6dso_sensor_notify_event中的lsm6dso_process_timer_events函数接收(前面已经介绍过该函数)。lsm6dso_process_timer_events中进入state->power_rail_pend_state == LSM6DSO_POWER_RAIL_PENDING_SET_CLIENT_REQ的分支进行reconfig操作

No.9:上电后,开始创建新的instance。reval_config被设为true时(即rail is already ON的情况),设置inst_state->instance_is_ready_to_configure = true;若不是rail is already ON的情况呢,不用担心,会走上面斜体标记的lsm6dso_process_timer_events部分,在if中,instance_is_ready_to_configure还是被设成true的。

再分析instance != NULL的情况,在不为NULL的情况下,还分为两部分:一部分是exist_requst & new_request均不为NULL,即新旧request均不为NULL 和new_requset ->message_id == SNS_STD_MSGID_SNS_STD_FLUSH_REQ。另一部分,则为else。分为No.10 和 No.11来讲。

  else{...if(NULL != exist_request               //No.10&&NULL != new_request&&new_request->message_id == SNS_STD_MSGID_SNS_STD_FLUSH_REQ){lsm6dso_instance_state *inst_state =(lsm6dso_instance_state*)instance->state->state;if(inst_state->fifo_info.fifo_enabled &&((state->sensor == LSM6DSO_ACCEL) || (state->sensor == LSM6DSO_GYRO))){lsm6dso_send_flush_config(this, instance);/** Do not update instance client request list at this pointbecause FIFO flush is a transitory request for an on-goingstream request. */return instance;}else{/** There aren't any FIFO sensors enabled to support flush.*  Send flush complete event anyway. */lsm6dso_send_fifo_flush_done(instance, &state->my_suid);return instance;}}else         //No.11{reval_config = true;/** An existing client is changing request*/if((NULL != exist_request) && (NULL != new_request)){instance->cb->remove_client_request(instance, exist_request);}/** A new client sent new_request*/else if(NULL != new_request){// No-op. new_request will be added to requests list below.}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

No.10:处理new_request->message_id == SNS_STD_MSGID_SNS_STD_FLUSH_REQ,若fifo_enable为true。则通过lsm6dso_send_flush_config,通过this->instance_api->set_client_config发送message_id = SNS_STD_MSGID_SNS_STD_FLUSH_REQ的request。若else:则说明fifo 不是enable的,则通过lsm6dso_send_fifo_flush_done直接flush。通过event_service->api->publish_event
发送message_id = SNS_STD_MSGID_SNS_STD_FLUSH_EVENT的flush event。

No.11:若不满足上面的任意一种的情况下,if exist_request & new_request均不为NULL,即只有message_id != SNS_STD_MSGID_SNS_STD_FLUSH_REQ,通过instance->cb->remove_client_request函数remove掉exist_requset,即remove掉存在的request。 else if 没有进行操作。下面再进行操作。

接着在分析instance != NULL的情况。为甚么用写一遍instance != NULL呢?因为上面若instance == NULL时,创建instance后,instance就不为NULL了,这时就要处理instance != NULL的情况。当前,实际写code时,可以省略不少步骤。

{lsm6dso_instance_state *inst_state =(lsm6dso_instance_state*)instance->state->state;if(NULL != new_request)                 //No.12{instance->cb->add_client_request(instance, new_request);if(LSM6DSO_MOTION_DETECT == state->sensor) {sns_memscpy(&inst_state->md_info.md_config, sizeof(inst_state->md_info.md_config),&state->md_config, sizeof(state->md_config));DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,"lsm6dso_set_client_request:: copying md config");}if(new_request->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG   //No.13||new_request->message_id == SNS_STD_EVENT_GATED_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG) {inst_state->config_sensors |= state->sensor;//copy range/resolution to inst stateif(LSM6DSO_ACCEL == state->sensor){inst_state->accel_info.sstvt = lsm6dso_accel_resolutions[state->resolution_idx]*1000;  //convert to micro-g/LSBinst_state->accel_info.range = lsm6dso_accel_ranges[state->resolution_idx];inst_state->accel_info.range_idx = state->resolution_idx;}else if(LSM6DSO_GYRO == state->sensor){inst_state->gyro_info.sstvt = lsm6dso_gyro_resolutions[state->resolution_idx];inst_state->gyro_info.range = lsm6dso_gyro_ranges[state->resolution_idx];inst_state->gyro_info.range_idx = state->resolution_idx;}}if(new_request->message_id == SNS_CAL_MSGID_SNS_CAL_RESET) {    //No.14DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,"Received event: SNS_CAL_MSGID_SNS_CAL_RESET");inst_state->registry_reset.request = true;inst_state->registry_reset.sensor_type = state->sensor;lsm6dso_sensor_write_output_to_registry(this, instance);//copy to sensor stateif(LSM6DSO_ACCEL == state->sensor){sns_memscpy(state->fac_cal_bias, sizeof(state->fac_cal_bias),inst_state->accel_registry_cfg.fac_cal_bias, sizeof(inst_state->accel_registry_cfg.fac_cal_bias));sns_memscpy(&state->fac_cal_corr_mat, sizeof(state->fac_cal_corr_mat),&inst_state->accel_registry_cfg.fac_cal_corr_mat, sizeof(inst_state->accel_registry_cfg.fac_cal_corr_mat));}else if(LSM6DSO_GYRO == state->sensor){sns_memscpy(state->fac_cal_bias, sizeof(state->fac_cal_bias),inst_state->gyro_registry_cfg.fac_cal_bias, sizeof(inst_state->gyro_registry_cfg.fac_cal_bias));sns_memscpy(&state->fac_cal_corr_mat, sizeof(state->fac_cal_corr_mat),&inst_state->gyro_registry_cfg.fac_cal_corr_mat, sizeof(inst_state->gyro_registry_cfg.fac_cal_corr_mat));}lsm6dso_send_cal_event(instance, state->sensor);}if(new_request->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG   //No.15&&state->sensor == LSM6DSO_MOTION_DETECT){if(inst_state->fifo_info.publish_sensors & LSM6DSO_ACCEL) {//send event as MD disabled since non-gated client is active//no need of this as we alreay set md_info statesns_motion_detect_event md_state;md_state.motion_detect_event_type = SNS_MOTION_DETECT_EVENT_TYPE_DISABLED;DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,"send MD_event =%d",md_state.motion_detect_event_type);pb_send_event(instance,sns_motion_detect_event_fields,&md_state,sns_get_system_time(),SNS_MOTION_DETECT_MSGID_SNS_MOTION_DETECT_EVENT,&inst_state->md_info.suid);reval_config = false;} else if (inst_state->md_info.enable_md_int) {//there is exsisting md client already present, just send eventDBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,"send MD_event =%d",inst_state->md_info.cur_md_state.motion_detect_event_type);pb_send_event(instance,sns_motion_detect_event_fields,&inst_state->md_info.cur_md_state,sns_get_system_time(),SNS_MOTION_DETECT_MSGID_SNS_MOTION_DETECT_EVENT,&inst_state->md_info.suid);reval_config = false;} elseinst_state->md_info.md_new_req = true;}}if(reval_config && inst_state->instance_is_ready_to_configure)     //No.16{lsm6dso_reval_instance_config(this, instance, state->sensor);}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98

这部分code才是关键
No.12:new_requset != NULL为前提条件,通过add_client_request添加一个request client,以后新的request都会通过该client进行处理。
No.13:message_id = SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG 或SNS_STD_EVENT_GATED_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG进行处理,设置相应的参数。
No.14:message_id == SNS_CAL_MSGID_SNS_CAL_RESET进行处理,写registry。
No.15:message_id == SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG进行处理,on change只有motion_detect才是,所以只处理motion_detect。
No.16:跳出if(new_requset != NULL)循环,若reval_config 和 instance_is_ready_to_configure均为true,则reconfig instance参数。
Ok,到这里remove 为false的分支解析完毕,总结一下:
若instance == NULL,则创建新的instance;若instance != NULL并且新的request的messge_id为SNS_STD_MSGID_SNS_STD_FLUSH_REQ则进行flush,直接return instance;若instance != NULL并且messge_id不为SNS_STD_MSGID_SNS_STD_FLUSH_REQ,先remove旧的client_request,再创建新的client_request,再跟进新的request的message_id进行相应的处理。

lsm6dso_set_client_request最后一部分:异常处理

// Sensors are required to call remove_instance when clientlessif(NULL != instance &&NULL == instance->cb->get_client_request(instance,&(sns_sensor_uid)ACCEL_SUID, true) &&NULL == instance->cb->get_client_request(instance,&(sns_sensor_uid)MOTION_DETECT_SUID, true) &&NULL == instance->cb->get_client_request(instance,&(sns_sensor_uid)GYRO_SUID, true) &&NULL == instance->cb->get_client_request(instance,&(sns_sensor_uid)SENSOR_TEMPERATURE_SUID, true)){this->cb->remove_instance(instance);}return instance;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

若出现instance !=NULL的同时,获取不同accel、motion_detect、gyro、temp的client request,则remove instance。
因为我们前进都已经add_client_request过client request了,若现在有获取不到client request了,说明中间某步出了问题,不能继续进行了,则需要remove instance。

Ok,lsm6dso_set_client_request分析完毕。

这里面需要注意下:与后续sns_sensor_instance_api有关系的地方。

  • this->cb->create_instance 通过cb函数来创建instance时,会调到sns_sensor_instance_api->init。this->cb->remove_instance通过cb函数来移除instance时,会调到sns_sensor_instance_api->deinit
sns_rc
sns_sensor_init_fw(void)
{sensor_cb = (sns_sensor_cb){....create_instance = &sns_sensor_instance_init,.remove_instance = &sns_sensor_instance_deinit,...};return SNS_RC_SUCCESS;
}SNS_SECTION(".text.sns") sns_sensor_instance*
sns_sensor_instance_init(sns_sensor *sensor, uint32_t state_len)
{sns_fw_sensor *fw_sensor = (sns_fw_sensor*)sensor;...rv = sensor->instance_api->init((sns_sensor_instance*)instance, sensor->state);...}return (sns_sensor_instance*)instance;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • this->instance_api->set_client_config调用sns_sensor_instance_api中set_client_config。
  • sns_sensor_instance_api中发送的request,会在sns_sensor_instance_api.notify_event中处理,同样sns_sensor_api中发送的request会在sns_sensor_api.notify_event中处理。

下面开始介绍sns_sensor_instance_api
2: sns_sensor_instance_api定义在sns_sensor_instance.h中,结构如下:

//sns_sensor_instance.h
typedef struct sns_sensor_instance_api
{uint32_t struct_len;/*** Initialize a Sensor Instance to its default state.  A call to* sns_sensor_instance_api::deinit will precede any subsequent calls* to this function.** @note Persistent configuration can be made available using the* sensor_state.** @param[i] this Sensor Instance reference* @param[i] sensor_state State of the Sensor which created this Instance** @return* SNS_RC_NOT_AVAILABLE - Sensor state does not allow for this operation* SNS_RC_SUCCESS*/sns_rc (*init)(sns_sensor_instance *const this,sns_sensor_state const *sensor_state);/*** Release all hardware and software resources associated with this Sensor* Instance.** @param[i] this Sensor Instance reference** @return* SNS_RC_INVALID_STATE - Error occurred: some resource could not be released* SNS_RC_SUCCESS*/sns_rc (*deinit)(sns_sensor_instance *const this);/*** Update a Sensor Instance configuration to this sensorRequest.** The Sensor Instance is expected to start all dependent streams, timers, etc..** @note* A Sensor may define any number of unique request types they support.* However, a client may only have a single active stream; an enable* request can inherently serve as a "reconfiguration" request.** @param[i] this Sensor Instance reference** @return* SNS_RC_INVALID_VALUE - Invalid client request* SNS_RC_SUCCESS*/sns_rc (*set_client_config)(sns_sensor_instance *const this,struct sns_request const *client_request);/*** Notification to the client that some data has been received.** The client must use the sns_manager_event to obtain this data* for processing.** @return* SNS_RC_INVALID_STATE - A client error occurred; Framework shall destroy client* SNS_RC_NOT_AVAILABLE - A transitory error occurred; Framework shall remove*    all outstanding input* SNS_RC_SUCCESS*/sns_rc (*notify_event)(sns_sensor_instance *const this);
} sns_sensor_instance_api;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

上面每个函数都有注释,这里不再解释。

sns_rc lsm6dso_inst_init(sns_sensor_instance *const this,sns_sensor_state const *sstate)
{state->scp_service = (sns_sync_com_port_service*)service_mgr->get_service(service_mgr, SNS_SYNC_COM_PORT_SERVICE);/**---------Setup stream connections with dependent Sensors---------*/stream_mgr->api->create_sensor_instance_stream(stream_mgr,this,sensor_state->irq_suid,&state->interrupt_data_stream);stream_mgr->api->create_sensor_instance_stream(stream_mgr,this,sensor_state->acp_suid,&state->async_com_port_data_stream);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在lsm6dso_inst_init中多数为初始化设置,包含获取sync_com_port service和创建async_com_port&interrupt data stream。

state->scp_service->api->sns_scp_register_com_port(&state->com_port_info.com_config,&state->com_port_info.port_handle);
  • 1
  • 2

通过instance注册com port。
在instance state复制所有sensor uids,初始化FIFO状态,初始Accel状态,初始Gyro状态等等,初始化中断数据,初始化com config,enable async com port:

/** Configure the Async Com Port */{sns_data_stream* data_stream = state->async_com_port_data_stream;uint8_t pb_encode_buffer[100];sns_request async_com_port_request ={.message_id  = SNS_ASYNC_COM_PORT_MSGID_SNS_ASYNC_COM_PORT_CONFIG,.request     = &pb_encode_buffer};async_com_port_request.request_len =pb_encode_request(pb_encode_buffer,sizeof(pb_encode_buffer),&state->ascp_config,sns_async_com_port_config_fields,NULL);data_stream->api->send_request(data_stream, &async_com_port_request);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

等等。。。

对应的是lsm6dso_inst_deinit

sns_rc lsm6dso_inst_deinit(sns_sensor_instance *const this)
{lsm6dso_instance_state *state =(lsm6dso_instance_state*)this->state->state;inst_cleanup(this, state);return SNS_RC_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
static void inst_cleanup(sns_sensor_instance *const this,lsm6dso_instance_state *state)
{...if(NULL != state->com_port_info.port_handle){state->scp_service->api->sns_scp_update_bus_power(state->com_port_info.port_handle, true);}lsm6dso_set_fifo_config(this, 0, 0, 0, 0 );lsm6dso_reconfig_hw(this);if(NULL != state->com_port_info.port_handle){state->scp_service->api->sns_scp_update_bus_power(state->com_port_info.port_handle, false);}sns_sensor_util_remove_sensor_instance_stream(this, &state->interrupt_data_stream);sns_sensor_util_remove_sensor_instance_stream(this, &state->async_com_port_data_stream);sns_sensor_util_remove_sensor_instance_stream(this, &state->timer_sensor_temp_data_stream);sns_sensor_util_remove_sensor_instance_stream(this, &state->timer_md_data_stream);sns_sensor_util_remove_sensor_instance_stream(this, &state->timer_self_test_data_stream);sns_sensor_util_remove_sensor_instance_stream(this, &state->timer_heart_beat_data_stream);if(NULL != state->scp_service){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);state->scp_service = NULL;}lsm6dso_dae_if_deinit(this);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

inst_cleanup中:

  • 判断port_handle是否存在,存在则关电。
  • 通过sns_sensor_util_remove_sensor_instance_stream,remove掉所有在instance中创建的data_stream。
  • scp_service设成NULL
  • lsm6dso_dae_if_deinit

下面解析sns_sensor_instance_api::set_client_config

static sns_rc lsm6dso_inst_set_client_config(sns_sensor_instance *const this,sns_request const *client_request)
{lsm6dso_instance_state *state =(lsm6dso_instance_state*)this->state->state;...sns_service_manager *mgr = this->cb->get_service_manager(this);sns_event_service *e_service = (sns_event_service*)mgr->get_service(mgr, SNS_EVENT_SERVICE); //No.1sns_lsm6dso_req *payload = (sns_lsm6dso_req*)client_request->request;...// Turn COM port ONstate->scp_service->api->sns_scp_update_bus_power(state->com_port_info.port_handle, //No.2true);// Register for interruptif(!lsm6dso_dae_if_available(this))                //No.3{lsm6dso_register_interrupt(this);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

该段code中首先
No.1:获取sns_service_manager ,并通过sns_service_manager 获取sns_event_service。
No.2:通过sns_scp_update_bus_power给COM port上电。
No.3:先判断sensor dae_if是否enable,若enable,则可以使用中断采集数据。接着,注册interrupt,在lsm6dso_register_interrupt函数中,发送message_id = SNS_INTERRUPT_MSGID_SNS_INTERRUPT_REQ的request来请求interrupt。

下面针对不同message_id进行处理。

  if(client_request->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG){desired_sample_rate = payload->desired_sample_rate;    //No.4desired_report_rate = payload->desired_report_rate;uint8_t desired_rate_idx = 0;if(state->fifo_info.fifo_enabled & LSM6DSO_ACCEL)     //No.5{rv = lsm6dso_match_odr(LSM6DSO_ACCEL, desired_sample_rate,   &desired_rate_idx, &accel_chosen_sample_rate,&accel_chosen_sample_rate_reg_value,&accel_num_samples_to_discard);}if(state->fifo_info.fifo_enabled & LSM6DSO_GYRO)     //No.6{rv = lsm6dso_match_odr(LSM6DSO_GYRO, desired_sample_rate,&desired_rate_idx,&gyro_chosen_sample_rate,&gyro_chosen_sample_rate_reg_value,&gyro_num_samples_to_disca

三:Sensor SLPI层代码分析---相关推荐

  1. BLOCK层代码分析(9)IO下发之IO下发

    看着题目是不是很奇怪,想不出好的名字,就这样将就吧. 前面bio bounce过程,bio的切分和合并,request的获取是为IO请求下发做准备工作.当这些准备工作完成后,才进入到真正的IO下发过程 ...

  2. BLOCK层代码分析(10)IO下发之IO下发函数总结

    BLOCK层IO下发涉及直接下发,调度器,没有设置调度类型以及plug/unplug等,因此下发函数纷繁复杂,这里做介绍几个主要的函数. 前面介绍了函数blk_mq_try_issue_directl ...

  3. perf-perf stat用户层代码分析

    perf_event 源码分析 前言 简单来说,perf是一种性能监测工具,它首先对通用处理器提供的performance counter进行编程,设定计数器阈值和事件,然后性能计数器就会在设定事件发 ...

  4. FreeModbus开源协议栈的移植和详解(三)- RTU协议代码分析

    FreeModbus开源协议栈的移植和详解(三) 目录 概述 一.RTU文件夹的文件 二.mbrtu.c文件 2.1数据类型说明 2.2函数说明 2.1eMBRTUInit()函数 2.2eMBRTU ...

  5. 四--RIL层代码分析--整个电话来访过程

    最近公司开发一个几百万的项目,要求重写系统RIL层,看了几个招聘信息,只要你会RIL层开发的,工资上w每个月不是梦,这是几天研究的成果,希望对大家有所帮助,兄弟们加油吧! 先来一个总的流程图: 拨出电 ...

  6. RIL层代码分析--拨号整个流程

    拨出电话流程: 1 在系统源码这个路径下/packages/apps/Phone/src/com/android/phone/DialtactsActivity.java contacts的andro ...

  7. 后缀数组的学习(三):SA数组实现代码分析

    在前面的博文里面分析了SA数组和rank数组的实现过程,实际上也就是倍增算法的思想分析!虽然思想上面懂了,但是代码实现还是很难理解的!因为代码里面做了太多的优化. 整个代码的实现可以分成两部分:1.对 ...

  8. 一--RIL层代码分析-RIL_RadioFunctions *RIL_Init(funcs =rilInit()-mainloop()

     ril/rild/rild.c->main()为函数入口 ------------------------------------------------------------------- ...

  9. 微型项目实践(6):Business层代码分析——实体类的生成策略

    上一篇中,我们分析了实体类的基类Entity,这一篇中,我们就分析一下基于该类的实体类. 每一个实体类都会有两个文件组成,我们以BlogClass为例,该类包含两个文件:BlogClass.cs和Bl ...

最新文章

  1. Google搜索技巧-从入门到精通(从此学习进步、工作顺心)
  2. Linux下安装nginx (tar解压版安装) nginx1.16.1
  3. 3c技能和背包需要改建吗?_认为您需要仪表板? 您应该改建一个笔记本。
  4. Chrome浏览器报错:Origin null is not allowed by Access-Control-Allow-Origin.
  5. 计算机应用基础山东省,2019年山东省中等职业学校对口升学考试:计算机文化基础+计算机应用基础模拟试卷...
  6. MyBatis Plus 批量数据插入功能,yyds!
  7. ci持续集成工程师前景_『中级篇』docker之CI/CD持续集成-项目生成镜像(76)
  8. DPDK官方中文文档
  9. [一句秒懂]小马的单例
  10. 第四章 MyBatis-SQL映射文件
  11. 单片机c语言编程烧录软件,STC-ISP单片机烧录软件下载|好用的单片机编程器烧录软件_最火软件站...
  12. 图灵5月书讯※特别制作【MongoDB将在5月中旬隆重上市】
  13. 手机上将mp4转换成amv_如何在智能手机上将图像转换为黑白图像
  14. 装黑苹果卡在苹果图标_虚拟机装MAC系统一直卡在苹果标志
  15. Eclipse使用Log4j2的详细教程
  16. unix系统病毒概述(转)
  17. 深度学习算法中卷积神经网络的应用
  18. pdf的base64转成jpg的base64
  19. postgresql: pg_ctl -D data start 出现 postgres aaaaaaaaaaaaaaaaaaaaaaaaa C:/Users/huang zhen yang/dat
  20. 安超云生态 | 安超云与百信完成产品兼容互认证 携手打造协同生态

热门文章

  1. android 使用iphone线控耳机,耳机 篇一:关于安卓手机怎么用苹果专用耳机的问题...
  2. LruCache的深入解析
  3. 使用PyG (PyTorch Geometric) 实现同质图transductive链路预测任务
  4. #include<>和#include“”的区别
  5. 亚信科技中国有限公司实习面试(长春)
  6. java Locale介绍
  7. jQuery过滤、遍历同级元素、向上遍历、向下遍历
  8. 自动投注c语言,yy七周年自动挂机
  9. 语音对话控制智能家居系统
  10. Wormhole for mac(在Mac上控制iOS和Android设备)