高通sensor架构实例分析之一

本文深入剖析了高通Sensor架构,介绍了从传统架构到引入独立音频DSP (aDSP) 的转变,以降低功耗并提高效率。文章详细阐述了aDSP上的软件组件,并通过Sensor1 API接口展示了应用处理器与aDSP之间的通信机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本系列导航:

linux驱动由浅入深系列:高通sensor架构实例分析之一(整体概览+AP侧代码分析)

linux驱动由浅入深系列:高通sensor架构实例分析之二(adsp驱动代码结构)
Linux驱动由浅入深系列:高通sensor架构例分析之三(adsp上报数据详解、校准流程详解)


最初的时候芯片厂家对sensor的处理和对待其它外设一样都是直接挂在processor上,sensor的驱动也和其他linux或android的驱动一样,生成对应的设备节点给上层提供数据(关于此类linux基础驱动的知识,可以参考本博客其他博文)。但后来这一切发生了变化,最主要的原因就是功耗。Sensor希望自己能够一直处于工作状态下,如计步器等应用场景。这样如果sensor还挂在主processor上(这时候处理器就分多核啦)势必影响待机功耗。因此各个芯片厂推出了各自的方案,如sensor-hub等等。高通在MSM8960之后就将sensor的处理塞到了一个单独的音频dsp中了(MSM8953中这个dsp叫作aDSP),这样待机时主处理器休眠降低功耗,由这个aDSP在处理音频数据的间隙捎带着就能把sensor的数据处理了^^。下面以MSM8953为例分析一下其结构。

 

高通sensor软件架构

首先来看一下高通sensor处理的软件框图:


1,  框图上半部分是应用处理器,下半部分是aDSP。

2,  aDSP中包含了log接口,电源管理,sensor算法库,sensor校准,各个sensor的管理模块。最后一个是直接挂载各个传感器的(Prox、Press、Mag、Gyro、Acc),软件中的主要部分叫作SMGR。[上图文字怎么乱了,补充一张^-^]


3,  在应用处理器中,软件接口中不再有每个sensor的设备节点了。那有的是什么呢,只有Sensor1 API Socket Remoting Layer层对应的API接口。这个接口是本文的重点,下文详细解释。

4,  那么aDSP与应用处理器之间用什么机制进行通信呢?图中可以看到一个叫QMI的东西,就是它了,这个高通基于共享内存机制开发的多核间通信技术,在应用处理器侧和aDSP侧都有相应的库已经完成了底层实现。之后有机会分析一下这种号称最为有效的多核间通信技术。

5,  应用处理器侧还有些乱七八糟的蓝色框,这部分是运行在应用处理器侧的sensor算法、校准相关的东西。这是些只会在非待机模式运行的算法,就适合放在这个地方了。

 

android中sensor架构

在android中sensor的架构图如下:


在Sensor1 API Socket Remoting Layer层的基础上转换成了android的Framwork层就可以被APP调用了,目前我们先以linux 应用程序的直接调用Sensor1 API Socket Remoting Layer层接口为例进行演示。


高通sensor测试工具

高通为sensor的测试提供了默认的工具,代码位于:

vendor\qcom\proprietary\sensors\dsps\test\src\sns_dsps_tc0001.c

vendor\qcom\proprietary\sensors\dsps\test\src\sns_cm_test.cpp

编译后生成对应的bin文件:

1,sns_dsps_tc0001用来查看当前系统挂载的sensor的相关信息:



2,sns_cm_test用来获取对应sensor_id的传感器数据:



Sensor的API接口:

1,

sensor1_error_e sensor1_open(sensor1_handle_s**hndl, sensor1_notify_data_cb_t data_cbf,  intptr_t cb_data );

hndl

Opaque handle used to identify this client

data_cbf

Pointer to the client’s callback function to process received data

cb_data

This data is set by the client and will be passed unmodified as a
parameter to the callback function

2,

typedef void (*sensor1_notify_data_cb_t) (uint32 cb_data, sensor1_msg_header_s* msg_hdr,  sensor1_msg_type_e msg_type, void *msg_ptr);

cb_data

Unmodified value passed in when the callback was registered in
sensor1_open()

msg_hdr

Message header defining the message

msg_type

Type of message

msg_ptr

Pointer to the QMI-based message; these messages are defined in their
respective service header files; client shall free this pointer via
sensor1_free_msg_buf()

3,

sensor1_error_e sensor1_close(sensor1_handle_s* hndl );

hndl

Opaque handle used to identify this client


4,

sensor1_error_e sensor1_write(sensor1_handle_s* hndl, sensor1_msg_header_s* msg_hdr, void *msg_ptr);

hndl

Opaque handle to identify this client

msg_hdr

Message header defining the message

msg_ptr

Pointer to the QMI-based request message; these messages are defined
in their respective service header files; memory pointed to shall be
allocated by sensor1_alloc_msg_buf()


5,

sensor1_error_e sensor1_writeable(sensor1_handle_s* hndl, sensor1_write_cb_t cbf, intptr_t cb_data, uint32_t service_number );

hndl

Opaque handle to identify this client

cbf

Pointer to the client’s callback function

cb_data

This data is set by the client and will be passed unmodified as a
parameter to the callback function

service_number

Client callback function will be called when it is possible that this
Service ID can accept new requests via sensor1_write


6,

typedef void (*sensor1_write_cb_t) (intptr_t cb_data, uint32_t service_number);

cb_data

Unmodified value passed in when the callback was registered in
sensor1_writable()

service_number

Service ID to which this callback refers


7,

sensor1_error_e sensor1_alloc_msg_buf(sensor1_handle_s* hndl,  uint16_t size,  void **buffer );

hndl

Opaque handle to identify this client

size

Size of the message structure

buffer

Address of a pointer to the memory address where the message should be
placed


8,

sensor1_error_e sensor1_free_msg_buf(sensor1_handle_s* hndl,  void* msg_buf );

hndl

Opaque handle to identify this client

msg_buf

Buffer to free



sns_cm_test.cpp代码实例

有了上面的api接口介绍,来看一下sns_cm_test.cpp中对其使用就比较清晰了:

  1. 好吧,为了避免麻烦,删除了高通私有代码演示,有代码的去上面指出的文件分析即可。相信没有代码的也不会看这篇文章^^ 本文仅做学习交流目的,如有侵权请联系博主。 
<think>好的,我需要解析用户提供的C++函数`static vector<unique_ptr<sensor>> get_available_als_sensors`的实现与作用,包括涉及到的`ambient_light`类、`sensor_factory`和`sensor_attributes`的用法,以及异常处理部分的意义。让我先仔细理解代码的上下文和相关引用。 首先,根据引用[3],传感器驱动模型分为HDI和Driver部分,负责设备管理、驱动加载等。`sensor_factory`可能属于Driver中的器件驱动子模块,用于创建传感器实例。`ambient_light`类继承自`ssc_sensor`,如引用[2]所示,构造函数设置了传感器类型、名称等信息。这说明`ambient_light`类代表具体的光传感器类型。 函数名`get_available_als_sensors`中的ALS指环境光传感器(Ambient Light Sensor),所以该函数的作用可能是获取系统中所有可用的环境光传感器实例。返回类型是`vector<unique_ptr<sensor>>`,说明通过智能指针管理传感器对象,确保资源安全。 接下来,考虑`sensor_factory`的用法。工厂模式常用于创建对象,可能根据传感器类型或属性生成对应的实例。结合引用[3]中的`sensor_device_if.h`接口,推测`sensor_factory`可能封装了驱动加载和实例化的逻辑。 `sensor_attributes`可能用于存储传感器的配置参数,如引用[3]提到的寄存器配置和解析。在创建传感器时,属性可能包括设备地址、采样率等,这些信息可能来自配置文件或动态检测。 异常处理部分的意义在于处理传感器初始化过程中可能出现的错误,如硬件不可用、配置错误等。通过try-catch块捕获异常,确保单个传感器的故障不影响整个列表的获取,同时记录错误信息方便调试。 现在,假设函数实现大致如下: 1. 查询所有传感器设备,筛选出环境光类型。 2. 使用`sensor_factory`根据设备信息创建对应的`ambient_light`实例。 3. 配置传感器属性,如采样率、精度等。 4. 异常处理确保部分失败不影响整体流程。 需要验证各部分的关联。引用[2]中的`ambient_light`构造函数设置类型为`SENSOR_TYPE_LIGHT`,而函数名中的ALS可能对应此类型。`sensor_factory`可能通过设备UID或其他标识符创建特定传感器对象。 异常处理可能包括`std::exception`或其派生类,捕获如资源分配失败、无效参数等错误。使用`try...catch`包围每个传感器的创建过程,确保即使某个失败,其他仍可加入列表。 总结各部分的作用: - `ambient_light`类:具体传感器实现,继承基类`sensor`。 - `sensor_factory`:工厂类,负责实例化传感器对象。 - `sensor_attributes`:配置参数,初始化时传入工厂。 - 异常处理:提高鲁棒性,记录错误,防止程序崩溃。 可能存在其他细节,如设备枚举方式、属性如何传递到工厂,但根据现有引用,可以合理推断主要逻辑。</think>### C++函数解析:get_available_als_sensors #### 函数作用 此函数用于**获取系统中所有可用的环境光传感器(Ambient Light Sensor实例**,返回通过智能指针管理的传感器对象集合。核心逻辑包含: - 传感器设备发现与初始化 - 工厂模式实例化对象 - 异常安全处理 #### 代码逻辑分析(假设实现) ```cpp static vector<unique_ptr<sensor>> get_available_als_sensors() { vector<unique_ptr<sensor>> sensors; auto device_list = sensor_factory::enumerate_devices(SENSOR_TYPE_LIGHT); // 枚举设备 for (auto& device_info : device_list) { try { sensor_attributes attr = parse_config(device_info.config); // 解析配置 auto sensor = sensor_factory::create<sensor>( device_info.suid, attr.wakeup_type, attr.parameters ); if (dynamic_cast<ambient_light*>(sensor.get())) { // 类型验证 sensors.emplace_back(std::move(sensor)); } } catch (const sensor_exception& e) { log_error("Failed to initialize ALS: %s", e.what()); // 记录异常 } } return sensors; } ``` #### 关键组件解析 1. **ambient_light类** - 继承自基础传感器类(如引用[2]中的`ssc_sensor`) - 构造函数设置传感器元数据: ```cpp ambient_light::ambient_light(sensor_uid suid, sensor_wakeup_type wakeup) : ssc_sensor(suid, wakeup) { set_type(SENSOR_TYPE_LIGHT); // 引用[2] set_string_type(SENSOR_STRING_TYPE_LIGHT); } ``` 2. **sensor_factory** - 实现**工厂模式**,封装驱动加载逻辑(引用[3]) - 核心方法: - `enumerate_devices()`:通过HDI接口查询设备列表 - `create()`:根据设备UID和属性创建具体传感器实例 3. **sensor_attributes** - 存储传感器配置参数(如采样率、阈值) - 可能来源于: - 设备描述文件(引用[3]中的`sensor_config_parser.h`) - 动态配置(如用户设置的灵敏度) #### 异常处理意义 - **try-catch块**:隔离单个传感器初始化失败对整体的影响 - **sensor_exception类型**:封装硬件访问错误、配置无效等异常 - **日志记录**:帮助定位驱动兼容性问题(如引用[4]中的硬件适配问题) #### 工作流程示意图 $$ \begin{aligned} &\text{1. 枚举设备} \rightarrow \text{2. 解析配置} \rightarrow \text{3. 工厂创建实例} \\ &\rightarrow \text{4. 类型校验} \rightarrow \text{5. 异常处理} \end{aligned} $$ #### 关联现有引用 - 传感器注册逻辑(引用[1]的`sns_register_sensor_list`) - 驱动模型分层(引用[3]的HDI/Driver架构) - 硬件适配问题(引用[4]的高通平台开发)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值