高通SDM845平台Sensor学习——4.SLPI(SAM Sensor)

####三: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_sensors
if 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 None

if len(static_sensors) == 0:
logger.error("There are no static sensors?!!!")
return None

static_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,inspect

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

lsm6dso_island_enable = False

if 'SNS_ISLAND_INCLUDE_LSM6DSO' in env: #No.1
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()), #No.2
register_func_name = "sns_register_lsm6dso",
binary_lib = False,
add_island_files = lsm6dso_island_enable)

if 'SENSORS_DD_DEV_FLAG' in env: #No.3
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)

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.1
lsm6dso_acc_publish_attributes(this); //No.2
lsm6dso_init_sensor_info(this, &((sns_sensor_uid)ACCEL_SUID), LSM6DSO_ACCEL); //No.3
DBG_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}; //uA
const uint32_t sleep_current = 3; //uA

lsm6dso_publish_def_attributes(this);
{
sns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR, //No.a
SNS_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.b
sns_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.c
sns_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.d
sns_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.e
sns_std_attr_value_data value = sns_std_attr_value_data_init_default;
value.has_sint = true;
value.sint = sleep_current; //uA
sns_publish_attribute(
this, SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT, &value, 1, false);
}
{ //No.f
sns_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.g
sns_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.d
attribute_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.a
sns_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.b

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
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.1

if((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.4
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;
}
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.a
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); //No.b
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; //No.c
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)) //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 Sensor
rv = 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.1
sns_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.2
DBG_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.3
if(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->state
if(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 state
if(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 registry
inst_state->registry_reset.request = false;
lsm6dso_sensor_write_output_to_registry(this, instance);

// Set the flag to false indicating that the registry is updated
inst_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 ON
state->power_rail_pend_state = LSM6DSO_POWER_RAIL_PENDING_NONE;
reval_config = true;

}
/** create_instance() calls init() for the Sensor Instance */ //No.9
instance = 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 point
because FIFO flush is a transitory request for an on-going
stream 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 state
if(LSM6DSO_ACCEL == state->sensor)
{
inst_state->accel_info.sstvt = lsm6dso_accel_resolutions[state->resolution_idx]*1000; //convert to micro-g/LSB
inst_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.14
DBG_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 state
if(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 state
sns_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 event
DBG_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;
} else
inst_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 clientless
if(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.1

sns_lsm6dso_req *payload = (sns_lsm6dso_req*)client_request->request;
...
// Turn COM port ON
state->scp_service->api->sns_scp_update_bus_power(state->com_port_info.port_handle, //No.2
true);
// Register for interrupt
if(!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.4
desired_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_discard);
}

if(state->fifo_info.publish_sensors & LSM6DSO_SENSOR_TEMP) //No.7
{
rv = lsm6dso_validate_sensor_temp_odr(state);
}
state->common_info.desired_odr_idx = desired_rate_idx;

if(desired_report_rate > accel_chosen_sample_rate)
{
// bad request. Return error or default report_rate to sample_rate
desired_report_rate = accel_chosen_sample_rate;
}
if(desired_report_rate != 0)
{
// Round up watermark. Qcom tracker: 39. CR2060232
// There seems to be an issue in Qcom compiler where float division has issues
// This is a workaround for that.
desired_wmk = (uint16_t)((accel_chosen_sample_rate + 0.5*desired_report_rate) / desired_report_rate);
}
else
{
if(accel_chosen_sample_rate == LSM6DSO_ACCEL_ODR_OFF)
{
desired_wmk = 0;
}
else
{
desired_wmk = 1;
}
}
...
if(LSM6DSO_MAX_FIFO <= desired_wmk)
{
desired_wmk = LSM6DSO_MAX_FIFO;
}

lsm6dso_set_fifo_config(this, //No.8
desired_wmk,
accel_chosen_sample_rate_reg_value,
gyro_chosen_sample_rate_reg_value,
state->fifo_info.fifo_enabled);

state->fifo_info.max_requested_flush_ticks = payload->desired_flush_ticks;

if(!state->self_test_info.test_alive) //No.9
{
lsm6dso_send_config_event(this);
//reconfig at interrupt boundary if wmk=1
if((state->current_conf.wmk != 1) ||
!state->fifo_info.reconfig_req ||
(state->current_conf.md_enabled != state->desired_conf.md_enabled))
{
lsm6dso_reconfig_hw(this);
lsm6dso_dump_reg(this, state->fifo_info.fifo_enabled);
}
else if((state->sensor_temp_info.desired_sampling_rate_hz != state->sensor_temp_info.cur_sampling_rate_hz)
&& ((state->fifo_info.publish_sensors & LSM6DSO_SENSOR_TEMP) ||
(state->sensor_temp_info.timer_is_active)))
{
lsm6dso_set_polling_config(this);
}
}
else
{
//Postpone the reconfig till Self-test is over
state->fifo_info.reconfig_req = false;
state->self_test_info.reconfig_postpone = true;
}

// update registry configuration
if(LSM6DSO_ACCEL == payload->registry_cfg.sensor_type) //No.10
{
fac_cal_bias = state->accel_registry_cfg.fac_cal_bias;
fac_cal_corr_mat = &state->accel_registry_cfg.fac_cal_corr_mat;
registry_persist_version = &state->accel_registry_cfg.registry_instance_version;
}
else if(LSM6DSO_GYRO == payload->registry_cfg.sensor_type)
{
fac_cal_bias = state->gyro_registry_cfg.fac_cal_bias;
fac_cal_corr_mat = &state->gyro_registry_cfg.fac_cal_corr_mat;
registry_persist_version = &state->gyro_registry_cfg.registry_instance_version;
}
else if(LSM6DSO_SENSOR_TEMP == payload->registry_cfg.sensor_type)
{
fac_cal_bias = state->sensor_temp_registry_cfg.fac_cal_bias;
fac_cal_corr_mat = &state->sensor_temp_registry_cfg.fac_cal_corr_mat;
registry_persist_version = &state->sensor_temp_registry_cfg.registry_instance_version;
}

if((NULL!= fac_cal_bias && NULL != fac_cal_corr_mat)
&& !(*registry_persist_version > payload->registry_cfg.registry_persist_version))
{
sns_memscpy(fac_cal_bias, sizeof(payload->registry_cfg.fac_cal_bias),
payload->registry_cfg.fac_cal_bias,
sizeof(payload->registry_cfg.fac_cal_bias));

sns_memscpy(fac_cal_corr_mat, sizeof(payload->registry_cfg.fac_cal_corr_mat),
&payload->registry_cfg.fac_cal_corr_mat,
sizeof(payload->registry_cfg.fac_cal_corr_mat));

sns_memscpy(registry_persist_version, sizeof(payload->registry_cfg.registry_persist_version),
&payload->registry_cfg.registry_persist_version,
sizeof(payload->registry_cfg.registry_persist_version));
}
}
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
No.4中:从payload中解析出sample_rate和report_rate
No.5中:若fifo enable 并且是accel,通过lsm6dso_match_odr设置accel采样率。
No.6中:若fifo enable并且是gyro,通过lsm6dso_match_odr设置gyro的采样率。
No.7中:若publish_sensors为true,且时temp sensor,则通过lsm6dso_validate_sensor_temp_odr设置采样率,
然后,做些采样率的处理,比如获取的采样率和设置后采样率对比,设置蓄水池watermark等等。。
No.8中:设置fifo config
No.9中:若没处于self_test下,通过lsm6dso_send_config_event发送每个sensor的物理配置信息;若处于self_test,reconfig_req设为false,reconfig_postpone设为true。
No.10中:update registry configuration。

else if(client_request->message_id == SNS_STD_MSGID_SNS_STD_FLUSH_REQ)
{

DBG_INST_PRINT(this, HIGH, __FILENAME__, __LINE__,
"set_client_config:: std flush request fifo_enabled 0x%x cur_wmk %d", state->fifo_info.fifo_enabled, state->fifo_info.cur_wmk);
if(state->fifo_info.fifo_enabled) {
state->fifo_info.th_info.flush_client_present = true;
lsm6dso_flush_fifo(this);
}
}
else if(client_request->message_id == SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG)
{
/** All self-tests are handled in normal mode. */
inst_exit_island(this);
lsm6dso_set_client_test_config(this);
}
// Turn COM port OFF
state->scp_service->api->sns_scp_update_bus_power(state->com_port_info.port_handle,
false);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
接着处理接收message_id== SNS_STD_MSGID_SNS_STD_FLUSH_REQ 和 message_id == SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG的request,处理完后,调用sns_scp_update_bus_power关电。

总结,lsm6dso_inst_set_client_config与lsm6dso_set_client_config联系非常之大,基本上通过lsm6dso_set_client_config接收的request都会通过lsm6dso_inst_set_client_config来处理,不同的message_id处理的方法不同,这里我们需要注意的message_id为SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG比较常用,在message_id == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG中发送的request,我们需要注意lsm6dso_register_interrupt中message_id = SNS_INTERRUPT_MSGID_SNS_INTERRUPT_REQ的request比较重要。

lsm6dso_inst_set_client_config基本上分析完了,该函数中整个sensor driver中非常重要,在实际工作中要非常仔细认真的研究。

下面分析,sns_sensor_instance_api::notify_event函数

static sns_rc lsm6dso_inst_notify_event(sns_sensor_instance *const this)
{
sns_rc rv = SNS_RC_SUCCESS;
sns_rc com_rv = SNS_RC_SUCCESS;
lsm6dso_instance_state *state =
(lsm6dso_instance_state*)this->state->state;

// Turn COM port ON
com_rv = state->scp_service->api->sns_scp_update_bus_power(
state->com_port_info.port_handle, true);
if (SNS_RC_SUCCESS != com_rv)
{
SNS_INST_PRINTF(ERROR, this, "notify_event:: update_bus_power ON %d", com_rv);
}

lsm6dso_dae_if_process_events(this); //No.1

lsm6dso_handle_ascp_events(this); //No.2
lsm6dso_handle_hw_interrupts(this); //No.3
rv = lsm6dso_handle_timer_events(this);

// Turn COM port OFF
com_rv = state->scp_service->api->sns_scp_update_bus_power(
state->com_port_info.port_handle, false);
if (SNS_RC_SUCCESS != com_rv)
{
SNS_INST_PRINTF(ERROR, this, "notify_event:: update_bus_power OFF %d", com_rv);
}

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
看似很少,不要被表象所蒙骗,整个sensor driver几乎所有的数据处理都会在该函数中进行。
No.1:lsm6dso_dae_if_process_events。

void lsm6dso_dae_if_process_events(sns_sensor_instance *this)
{
lsm6dso_instance_state *state = (lsm6dso_instance_state*)this->state->state;
process_events(this, &state->dae_if.ag);
process_events(this, &state->dae_if.temp);

if(!stream_usable(&state->dae_if.ag) || !stream_usable(&state->dae_if.temp))
{
/* both streams are needed; if one was removed, remove the other one too */
lsm6dso_dae_if_deinit(this);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
可以看到主要的两个函数为process_events(),字面意思我们就可以得知,该函数是处理event的。
那么什么是dae呢?
dae又称Data Acquisition Engine,目前在sdm845上没有使用该功能,将会在sdm855(另称SM8150)上使用。

 

 

所以上述函数不会执行。

No.2:sm6dso_handle_ascp_events

ASCP是什么,Asynchronous COM Port(ASCP)Sensor,ASCP sensor属于platform sensor,ASCP sensor提供一个异步读/写 COM port的接口。

所有的sensor均需要该platform sensor,通过该ASCP sensor创建一个data stream,并通过该data stream 发送request请求。

当发送request完成后,data event会通过该data stream发送给requesting的sensor,并必须通过requesting sensor读取该data event。

如果一个sensor不再需要ASCP,必须通过ASCP sensor移除data stream。

ASCP的API存放在/slpi_proc/ssc/sensors/pb/sns_async_com_port.proto中。

根据上面的描述,我们可以知道ASCP的重要性,那么该函数在整个sensor driver中也非常重要。

static void lsm6dso_handle_ascp_events(sns_sensor_instance *const this)
{
lsm6dso_instance_state *state =
(lsm6dso_instance_state*)this->state->state;
sns_sensor_event *event = NULL;
uint32_t port_rw_events_rcvd = 0;

if(NULL == state->async_com_port_data_stream ||
NULL == (event = state->async_com_port_data_stream->api->peek_input(state->async_com_port_data_stream))) {
return;
}
1
2
3
4
5
6
7
8
9
10
11
我们分段解析该函数。
可以看到首先获取到lsm6dso_instance_state。并判断async_com_port_data_stream是否存在,peek_input是否有数据输入。否则,直接return。

有数据输入的话,下面就要解析输入的event了。

while(NULL != event)
{
if(SNS_ASYNC_COM_PORT_MSGID_SNS_ASYNC_COM_PORT_ERROR == event->message_id) //No.1
{
SNS_INST_PRINTF(ERROR, this, "Received ASCP error event id=%d",
event->message_id);
}
else if((SNS_ASYNC_COM_PORT_MSGID_SNS_ASYNC_COM_PORT_VECTOR_RW == event->message_id) && state->ascp_req_count) //No.2
{

if(state->fifo_info.reconfig_req)
DBG_INST_PRINT(this, HIGH, __FILENAME__, __LINE__,
"ascp req processing ascp_req_count %d", state->ascp_req_count);
state->ascp_req_count--;

//is this timestamp accurate to use?
state->fifo_info.ascp_event_timestamp = event->timestamp;
pb_istream_t stream = pb_istream_from_buffer((uint8_t *)event->event, event->event_len);
sns_ascp_for_each_vector_do(&stream, lsm6dso_process_com_port_vector, (void *)this);

if(state->fifo_info.bh_info.flush_client_present) {
if(state->fifo_info.publish_sensors & LSM6DSO_ACCEL)
{
lsm6dso_send_fifo_flush_done(this, &state->accel_info.suid);
}
if(state->fifo_info.publish_sensors & LSM6DSO_GYRO)
{
lsm6dso_send_fifo_flush_done(this, &state->gyro_info.suid);
}
state->fifo_info.bh_info.flush_client_present = false;
state->fifo_info.th_info.flush_client_present = false;
}
else if(state->irq_info.irq_config.interrupt_trigger_type == SNS_INTERRUPT_TRIGGER_TYPE_HIGH
|| state->irq_info.irq_config.interrupt_trigger_type == SNS_INTERRUPT_TRIGGER_TYPE_LOW)
{
// Send is_cleared message only for level triggered interrupt
lsm6dso_send_interrupt_is_cleared_msg(this);
}
port_rw_events_rcvd++;
}
event = state->async_com_port_data_stream->api->get_next_input(state->async_com_port_data_stream);
}

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
该while循环,我们都非常熟悉。用来解析event信息。
No.1:错误的event。
No.2:message_id = SNS_ASYNC_COM_PORT_MSGID_SNS_ASYNC_COM_PORT_VECTOR_RW,该message_id是我们常用到的message_id。处理COM port中的event data。
主要处理函数是:lsm6dso_process_com_port_vector()
最后通过get_next_input获取下一笔event input。

找重介绍下:lsm6dso_process_com_port_vector

void lsm6dso_process_com_port_vector(sns_port_vector *vector, void *user_arg)
{
...
lsm6dso_process_fifo_data_buffer(instance,
gyro_enabled,
first_timestamp,
sampling_intvl,
vector->buffer,
vector->bytes);
...
}

1
2
3
4
5
6
7
8
9
10
11
12
void lsm6dso_process_fifo_data_buffer(
sns_sensor_instance *instance,
bool gyro_enabled,
sns_time first_timestamp,
sns_time sample_interval_ticks,
const uint8_t *fifo_start,
size_t num_bytes
)
{
if((gyro_enabled) && (STM_LSM6DSO_GYRO_TAG == tag)) {
if(!gyro_sample_sets)
lsm6dso_log_sensor_state_raw_alloc(&log_gyro_state_raw_info, 0);

gyro_timestamp = first_timestamp + (gyro_sample_sets * sample_interval_ticks);
//This sample belongs to Gyro
if(!(gyro_timestamp < timestamp))
timestamp = gyro_timestamp;
lsm6dso_handle_gyro_sample(&fifo_start[i+1], //NO.1
timestamp,
sample_interval_ticks,
instance,
event_service,
state,
&log_gyro_state_raw_info);
gyro_sample_sets++;
state->fifo_info.last_timestamp = timestamp;
}
else if(STM_LSM6DSO_ACC_TAG == tag) {
if(!acc_sample_sets)
lsm6dso_log_sensor_state_raw_alloc(&log_accel_state_raw_info, 0);

acc_timestamp = first_timestamp + (acc_sample_sets * sample_interval_ticks);
if(!(acc_timestamp < timestamp))
timestamp = acc_timestamp;
lsm6dso_handle_accel_sample(&fifo_start[i+1], //No.2
timestamp,
sample_interval_ticks / 2,
instance,
event_service,
state,
&log_accel_state_raw_info);
acc_sample_sets++;
state->fifo_info.last_timestamp = timestamp;
}
else
{
DBG_INST_PRINT(instance, HIGH, __FILENAME__, __LINE__,
"Unknown TAG: %u", tag);
}
}
}
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
No.1:lsm6dso_handle_gyro_sample处理gyro的数据。
No.2:lsm6dso_handle_accel_sample处理accel的数据。
在此不再解析,主要是根据vector->buffer和vector->bytes生成gyro or accel的数据。

pb_send_sensor_stream_event(instance,
&state->gyro_info.suid,
timestamp - filter_delay,
SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT,
status,
opdata_cal.data,
ARR_SIZE(opdata_cal.data),
state->encoded_imu_event_len);
1
2
3
4
5
6
7
8
并通过pd_send_sensor_stream_event发送出去。主要,发送的message_id为SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT,就是我们client中接收到的message_id。

至此,client便收到了slpi侧传回来的accel or gyro event。

再回到lsm6dso_inst_notify_event()函数中:

No.3:lsm6dso_handle_hw_interrupts()

static void lsm6dso_handle_hw_interrupts(sns_sensor_instance *const this)
{
lsm6dso_instance_state *state =
(lsm6dso_instance_state*)this->state->state;
sns_interrupt_event irq_event = sns_interrupt_event_init_zero;
sns_sensor_event *event;

// Handle interrupts
if(NULL != state->interrupt_data_stream)
{
event = state->interrupt_data_stream->api->peek_input(state->interrupt_data_stream);
while(NULL != event)
{
if (SNS_INTERRUPT_MSGID_SNS_INTERRUPT_REG_EVENT == event->message_id) //No.1
{
DBG_INST_PRINT(this, MED, __FILENAME__, __LINE__,
"interrupt reg event received");

state->irq_info.irq_ready = true;
if(state->md_info.enable_md_int)
{
lsm6dso_update_md_intr(this, true, false);
}
if((state->fifo_info.publish_sensors & (LSM6DSO_ACCEL | LSM6DSO_GYRO)) ||
(state->accel_info.gated_client_present && !state->md_info.enable_md_int)) {
lsm6dso_enable_fifo_intr(this, state->fifo_info.fifo_enabled);
}
}
else if(SNS_INTERRUPT_MSGID_SNS_INTERRUPT_EVENT == event->message_id) //No.2
{
//set this once entered in irq handle
state->fifo_info.recheck_int = false;

pb_istream_t stream = pb_istream_from_buffer((pb_byte_t*)event->event, event->event_len);
if(pb_decode(&stream, sns_interrupt_event_fields, &irq_event))
{
if(state->fifo_info.reconfig_req)
DBG_INST_PRINT(this, MED, __FILENAME__, __LINE__,
"HW interrupt event received");

//set heart_attack false
state->health.heart_attack = false;
state->health.heart_attack_cnt = 0;
//reset the timer
// QC: Should be done after handling the event so as not to add any delay to async com port request.
if(NULL != state->timer_heart_beat_data_stream)
{
lsm6dso_inst_create_timer(this, &state->timer_heart_beat_data_stream, state->heart_beat_timeout, true);
}


if((state->md_info.enable_md_int) && (state->md_info.is_filter_settled))
{
lsm6dso_handle_md_interrupt(this, irq_event.timestamp, NULL);
}

if(state->fifo_info.cur_wmk > 0
&& state->fifo_info.fifo_rate > LSM6DSO_ACCEL_ODR_OFF)
{
LSM6DSO_INST_DEBUG_TS(MED, this,
"DSO int received irq_timestamp %u",(uint32_t)(irq_event.timestamp));
state->fifo_info.th_info.interrupt_fired = true;
state->fifo_info.th_info.interrupt_ts = irq_event.timestamp;
lsm6dso_read_fifo_data(this, irq_event.timestamp, false); //No.3
}
}
}
else
{
SNS_INST_PRINTF(ERROR, this, "Received invalid event id=%d",
event->message_id);
}
event = state->interrupt_data_stream->api->get_next_input(state->interrupt_data_stream);
}
}
}
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
该函数主要是接收hw interrupts信息,我们知道interrupt 也是一颗platform sensor,该interrupt sensor为interrupts register 提供接口。

所有的sensor使用interrupts时必须通过interrupt sensror创建一个data stream,并通过该data stream发送request。

当中断触发后,data events会通过data stream发送给requesting sensor。

如果sensor不再需要interrupts,可以通过interrupt sensor移除对应的data stream。
No.1,处理message_id = SNS_INTERRUPT_MSGID_SNS_INTERRUPT_REG_EVENT的event。

No.2:处理message_id = SNS_INTERRUPT_MSGID_SNS_INTERRUPT_EVENT的event。

No.3:lsm6dso_read_fifo_data()函数中,通过读fifo 状态寄存器,查看fifo数据长度是否满足条件,若满足,通过lsm6dso_send_fifo_flush_done将fifo中数据flush到client中。
其中message_id = SNS_STD_MSGID_SNS_STD_FLUSH_EVENT。可见该函数是主要针对fifo的,若不采用fifo
,则不会调到该函数。

Ok,.notify_event = lsm6dso_inst_notify_event 在此介绍完了。
总结一下,在notify_event主要是处理一系列的event,比如dae、ascp、interrupts、timer等等。
在每个platform sensor处理函数中,会publish相应的message_id给发送request的sensor client。
最终完成,所有event的publish。

下面我们用一张关系图,总结整个Activation的过程

 

---------------------
作者:汉克233
来源:CSDN
原文:https://blog.csdn.net/liuei633/article/details/80935511
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-05-10 14:25  zzzxzzz  阅读(3306)  评论(0)    收藏  举报