应用与Sensor通信¶
Solution 框架下的 Sensor 驱动的启动/停止、参数配置等关键操作均由应用层发起,驱动层仅提供标准接口实现。所有跨层、跨核通信均通过 IPC 框架统一封装,确保跨平台、跨核场景下的可移植性与一致性。

原则:应用层与 Sensor 之间的所有通信必须经由 IPC 框架进行。
1.核心概念¶
Solution 提供了一套简化的 IPC 通信注册框架(代码位于 ipc_service.c),封装了底层数据交互细节。通过该框架,用户无需关注复杂的跨核通信实现,仅需调用注册接口并实现回调函数,即可快速搭建通信链路
详细参见:IPC(核间)通信
IPC 框架初始化¶
Solution 通过宏区分 HCPU 与 LCPU 角色,分别注册为 IPC 通信的客户端与服务端。
初始化函数¶
int lcpu_service_init(void)
{
#if defined(BF0_LCPU) || defined(SENSOR_IN_HCPU) || defined(BSP_USING_PC_SIMULATOR)
lcpu_srv_handle = ipc_server_register("LCPU_APP", NULL,
lcpu_service_est_cb,
lcpu_service_sleep_cb,
lcpu_service_comm_cb);
RT_ASSERT(lcpu_srv_handle);
#endif
#if defined(BF0_HCPU) || defined(BSP_USING_PC_SIMULATOR)
ipc_client_register(&lcpu_app_srv_handle, lcpu_srv_handle, "LCPU_APP",
app_service_filter_cb, app_service_est_cb, app_service_comm_cb);
RT_ASSERT(lcpu_app_srv_handle);
#endif
LOG_I("%s: server %p client %p", __func__, lcpu_srv_handle, lcpu_app_srv_handle);
return 0;
}
#if defined(BF0_LCPU)
INIT_COMPONENT_EXPORT(lcpu_service_init);
#else
INIT_APP_EXPORT(lcpu_service_init);
#endif
HCPU 端(客户端)
ipc_client_register(&lcpu_app_srv_handle,
lcpu_srv_handle,
"LCPU_APP",
app_service_filter_cb,
app_service_est_cb,
app_service_comm_cb);
主动发起服务连接请求
通过回调函数接收 LCPU 上报的数据
LCPU 端(服务端)
lcpu_srv_handle = ipc_server_register("LCPU_APP", NULL,
lcpu_service_est_cb,
lcpu_service_sleep_cb,
lcpu_service_comm_cb);
注册命名服务
"LCPU_APP",等待客户端连接通过回调函数接收HCPU下发的事件与消息
详细参见:solution\components\lcpu\lcpu_service.c
2. 传感器启动流程¶
2.1 运动传感器启动¶
运动传感器在系统上电阶段由应用层触发自动启用,其完整工作流程如下:
步骤 1:应用层发起上电通知(HCPU端)¶
HCPU的电源管理模块 app_pm 通过IPC接口向LCPU发送 LCPU_PWR_ON 事件:
void app_lcpu_pwr_on(void)
{
ipc_send_event_to_lcpu(LCPU_PWR_ON);
}
步骤 2:IPC框架消息中转(HCPU → LCPU)¶
lcpu_service 组件的通信回调函数 lcpu_service_comm_cb 接收到该事件后,根据消息类型将其转发至 sensor_service 的对应处理函数:
case LCPU_PWR_ON:
{
send_msg_to_lcpu_thread(NULL, 0, power_on_cb, 0);
send_msg_id = msg_id;
break;
}
#if defined(RT_USING_SENSOR) && (!defined(BSP_USING_PC_SIMULATOR) || defined(SENSOR_ALGO_SIMULATOR))
if (send_msg_id)
send_msg_to_lcpu_thread(data, len, sensors_msg_process_in_lcpu_thread_cb, msg_id);
#endif
步骤 3:Sensor Service解析与指令下发(LCPU端)¶
sensor_service 的 sensors_msg_process_in_lcpu_thread_cb 函数根据消息ID进行分支处理。
针对开机事件,执行以下操作:
配置运动传感器参数并调用配置接口
创建传感器轮询的软件定时器并启动
case LCPU_PWR_ON:
{
#if defined (SENSOR_USING_6D) &&!defined (BSP_USING_PC_SIMULATOR)
rt_kprintf("lcpu power on gsensor!\n");
gsensor_setting_t gs_setting = {SENSOR_ON, 0, 0, 0};
gsensor_config_req(APP_SENSOR_GSENSOR_SETTING_REQ, (void *)&gs_setting);
#endif
#if defined(SENSOR_USING_GPS) || defined(SENSOR_USING_6D) || defined(SENSOR_USING_HR) || defined(SENSOR_USING_MAG) || defined(SENSOR_USING_ASL)
sensor_timer_create();
sensor_timer_start();
#endif
break;
}
步骤 4:驱动层执行初始化(LCPU端)¶
驱动程序接收到配置请求后,执行设备初始化并打开传感器:
if (SENSOR_ON == gsensor_state->state && SENSOR_OFF == gsensor_is_opened())
{
if (RT_EOK == gsensor_init())
{
gsensor_enable_set(SENSOR_ON);
}
}
步骤 5:周期性轮询传感器(LCPU端)¶
gsensor_algo_scheduler() 由软件定时器周期性调用,实现运动传感器的持续轮询与数据处理:
1. 状态检查 首先验证传感器是否已正常打开,若未打开则立即终止执行:
if (!gsensor_is_opened())
return;
2. 数据采集与处理 当累计达到指定采样周期时,执行以下操作:
从驱动层读取传感器数据
进行算法处理
保存数据供其他传感器使用
将处理后的数据发送至应用层
#ifndef SENSOR_IN_HCPU
gsensor_data_fetch(0, (void *)&gsensor_data);
#if defined (USING_GSENSOR_DATA_STORE_LIST)
gsensor_data_store(&gsensor_data);
#endif
#endif
RT_ASSERT(gsensor_data.num <= gsensor_fifo_len);
factory_send_gsensor_data_to_app((int16_t)(gsensor_data.buf[0].acce_data[0] * 100.0f), (int16_t)(gsensor_data.buf[0].acce_data[1] * 100.0f), (int16_t)(gsensor_data.buf[0].acce_data[2] * 100.0f));
if ((gsensor_data.num > 0) && (sensor_info.gs_algo_ops))
{
sensor_info.gs_algo_ops(period, &gsensor_data);
}
2.2 心率传感器启动¶
心率传感器的启动依据应用层的具体业务场景动态配置。以下以 Sport Action 应用退出时切换为自动测量模式 为例进行说明:
步骤 1:应用层切换测量模式(HCPU)¶
当 Sport Action 应用退出并切换至停止状态时,on_stop() 会释放资源,同时将心率传感器由“手动测量”切为“自动测量”。
HCPU 通过IPC框架把配置参数一次性下发到 LCPU:先填充hr_auto_meas_t结构体(使能=1、间隔=5 min),再以APP_SENSOR_SETTING_HR_AUTO_MEAS为消息 ID:
void sport_set_hr_auto_measure(void)
{
#if defined(RT_USING_SENSOR) && defined(BSP_BLE_SIBLES)
setting_hr_auto_meas_t hr_itrv = {0};
hr_itrv.enable = 1;
hr_itrv.interval_time_min = 5;
hr_itrv.start_hour = 0;
hr_itrv.start_min = 0;
hr_itrv.end_hour = 0;
hr_itrv.end_min = 0;
ipc_send_msg_to_lcpu(APP_SENSOR_SETTING_HR_AUTO_MEAS, &hr_itrv, sizeof(hr_itrv));
#endif
}
步骤 2:IPC 框架消息中转(HCPU → LCPU)¶
lcpu_service 组件的通信回调函数 lcpu_service_comm_cb 接收该事件,并依据消息类型将其转发至 sensor_service 的处理函数:
case APP_SENSOR_SETTING_HR_AUTO_MEAS:
{
send_msg_id = msg_id;
break;
}
#if defined(RT_USING_SENSOR) && (!defined(BSP_USING_PC_SIMULATOR) || defined(SENSOR_ALGO_SIMULATOR))
if (send_msg_id)
send_msg_to_lcpu_thread(data, len, sensors_msg_process_in_lcpu_thread_cb, msg_id);
#endif
步骤 3:Sensor Service 解析与指令下发(LCPU)¶
sensor_service 的 sensors_msg_process_in_lcpu_thread_cb 识别为心率传感器相关命令(如 APP_SENSOR_SETTING_HR_AUTO_MEAS),统一调用 hr_config_req 进行配置:
#ifdef SENSOR_USING_HR
case APP_SENSOR_SETTING_HR_AUTO_MEAS:
case APP_SENSOR_SETTING_SPO2_AUTO_MEAS:
case APP_SENSOR_SETTING_HR_REMIND:
case APP_SENSOR_HR_SETTING_REQ:
case APP_SENSOR_TODAY_HR_REQ:
{
hr_config_req(msg_id, msg->data);
break;
}
#endif
步骤 4:驱动层配置生效(LCPU)¶
驱动层接收配置参数,完成传感器工作模式的配置:
1. 参数分发
hr_config_req() 根据消息 ID 传递至具体设置函数:
void hr_config_req(uint16_t msg_id, uint8_t *data)
{
switch (msg_id)
{
case APP_SENSOR_SETTING_HR_AUTO_MEAS:
hr_set_auto_meas(data);
break;
}
}
2. 参数校验与设置
hr_set_auto_meas() 将配置写入全局变量hr_auto_meas,其中hr_auto_meas.enable被设为 1(启用自动测量),并强制保证最小测量间隔不低于 5 分钟:
static void hr_set_auto_meas(void *meas)
{
#ifndef HR_HOURLY_MEASURE
hr_auto_meas = *((hr_auto_meas_t *)meas);
if (hr_auto_meas.interval_time_min < 5)
hr_auto_meas.interval_time_min = 5;
#endif
}
步骤 5:心率传感器自动测量策略(LCPU)¶
hr_algo_scheduler() 由软件定时器周期性调用,实现心率测量的自动化调度。整个流程分为状态检查、分钟触发、测量启动、数据采集与停止四个阶段。
1. 状态检查
系统首先检查所有心率/血氧测量模式是否处于关闭状态。若均未激活,则重置相关计时器并跳过算法处理,仅保留每分钟计数功能:
if ((SENSOR_OFF == hr_get_state(HR_MANU_MEAS | HR_AUTO_MEAS))
&& (SENSOR_OFF == spo2_get_state(HR_MANU_MEAS | HR_AUTO_MEAS)))
{
hr_peroid_time = hr_algo_time = hr_auto_time = spo2_auto_time = 0;
goto end;
}
2. 分钟触发
每当累计时间达到 60 秒时,执行 hr_auto_meas_process(false) 以递增测量间隔计数:
end:
if (one_minu >= 60 * 1000)
{
one_minu = 0;
#ifndef HR_HOURLY_MEASURE
hr_auto_meas_process(false);
#endif
hr_send_curday_history_to_app();
}
3. 测量启动
hr_auto_meas_process() 根据预设间隔和使能状态控制传感器上电。当满足以下条件时触发测量:
自动测量功能已启用(
hr_auto_meas.enable)到达设定的分钟间隔(或首次启动)
static void hr_auto_meas_process(bool enable)
{
static uint8_t meas_interval = 0;
static uint8_t first = 1;
if (!hr_auto_meas.enable) return;
if (!enable)
{
meas_interval++;
if (first || meas_interval >= meas->interval_time_min)
{
first = 0;
meas_interval = 0;
goto out;
}
return;
}
out:
if (SENSOR_OFF == hr_get_state(HR_MANU_MEAS) &&
(start_time_stamp == end_time_stamp ||
(cur_time_stamp >= start_time_stamp && cur_time_stamp <= end_time_stamp)))
{
hr_setting_t hr_state = {SENSOR_ON, HR_AUTO_MEAS, SENSOR_HR, 0};
send_msg_to_lcpu_thread(&hr_state, sizeof(hr_state), hr_setting_req_cb, 0);
LOG_I("hr_auto_meas start!");
}
}
4. 数据采集与自动停止
传感器上电后,hr_algo_scheduler()持续执行数据采集与算法运算。测量成功时,数据保存至历史记录后关闭传感器;测量超时则直接关闭传感器。
if ((SENSOR_ON == hr_get_state(HR_AUTO_MEAS)) &&
(HR_MEAS_SUCC == meas_result || hr_auto_time >= 1000 * 60))
{
if (HR_MEAS_SUCC == meas_result)
hr_save_meas_result_to_history(SENSOR_HR);
hr_auto_time = 0;
hr_setting_t hr_state = {SENSOR_OFF, HR_AUTO_MEAS, SENSOR_HR};
send_msg_to_lcpu_thread(&hr_state, sizeof(hr_state), hr_setting_req_cb, 0);
LOG_I("hr_auto_meas finish!");
}