【Android驱动09】Sensor2.0传感器驱动框架

一、概述

MTK框架可以分为两部分,AP和SCP。
AP是主芯片,SCP是协处理器,他们一起工作来处理sensor数据。

SCP 是用来处理sensor和audio相关功能和其他客制化需求的一个协处理理器,MTK SCP选择freeRTOS作为操作系统,CHRE是处理传感器相关操作的专门任务。

kernel层负责汇总处理sensor传输上来的数据,以及处理应用层传递下来的指令。

hal层是硬件抽象层,具有硬件供应商实现的标准接口,允许Android不了解低级别的驱动程序实现。sensor service通过动态链接的方式加载hal层模块。经过动态链接,service可以调用hal层的函数,方便将控制传递,也可以从hal层获取数据。这样使用hal就可以在不影响或修改更高级别系统的情况下实现功能。

framework层中sensor service 能创建实例对象,并增加到service manager中,同时可以从驱动中获取原始数据并发送到客户端。

应用层中的应用可以发送调用sensor的指令到下层,同时也可以获得下层传来的传感器数据并进行分析处理。

整个sensor体系中包括:应用层、framework层、jni、hal层、kernel层、SCP/CHRE。

因为对于日常生活来说有一部分sensor是使用频率是很高的,所以必然也伴随着手机功耗的增加如果每次都是CPU进行处理的化,而且CPU一旦休眠还伴随着sensor会停止工作,为了优化手机使用Google和MTK分别开发了CHRE 和SCP 进行sensor控制。

二,介绍SCP
SCP是处理客制化需求的协处理器。

SCP 是用来处理sensor和audio相关功能和其他客制化需求的一个协处理理器,MTK SCP选择freeRTOS作为操作系统,CHRE是处理传感器相关操作的专门任务,它的架构如下
在这里插入图片描述

然后是CHRE:

在这里插入图片描述

在SCP下,MTK传感器集线器功能是在google CHRE ar上开发的,chre(Context Hub Runtime Environment)是一种事件驱动的体系结构,也可以被视为操作系统。

黄色部分是事件队列,CHRE只有一个while循环来处理事件队列中的头事件。如果以前的调用尚未完成,CHRE将无法调用队列中的一个任务。因此,没有优先级概念,当前事件队列处理只能

被中断中断。默认情况下,CHRE在事件队列中最多支持512个事件。CHRE的目的是实现实时性和轻量级,因此事件队列中调用的所有任务都必须快速运行。CHRE中的驱动程序实现称为nano hub app。

三,sensor2.0基本框架
整个sensor体系中包括:应用层、framework层、jni、hal层、kernel层、SCP/CHRE。
在这里插入图片描述
3.1 scp模块代码路径
路径:vendor/vendor/mediatek/proprietary/tinysys/freertos/source/
drivers/CM4_A:针对不同硬件的专有驱动程序代码

3.2 SCP 代码大小限制机制
memoryReport.py是一个用于在构建时限制代码大小的脚本。

如果代码大小超过了设置,它将会导致构建错误,以警告编码器。

如果你认为代码确实占据了你所看到的大小,你可以修改Setting.ini文件。

修改路径:

vendor/vendor/mediatek/proprietary/tinysys/freertos/source/tools/memoryReport.py

vendor/vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/$PLATFORM/platform/Setting.ini

3.3 overlay机制详解

一种类型的传感器可能来自两个不同的供应商。
如果将两个驱动程序放在SCP SRAM中进行自动检测,它会消耗大量SRAM。
因此,MTK解决方案将在DRAM中找到两个驱动程序,并在SCP启动时加载一个驱动程序。

驱动加载步骤:在这里插入图片描述overlay加载流程:

内存将SCP loader部分的代码从DRAM复制到SRAM中,同时SCP启动

SCP loader将Tinysys相同的代码从DRAM复制到SRAM,操作系统启动,同时传感器驱动进行初始化

OverlayRemap将传感器驱动1复制到SRAM,hw进行验证(主要是sensor的id),如果失败,就复制驱动2,如此往复,如果成功,就remap下一个传感器类型

一个section表示一个传感器类型(如加速度传感器类型),一个类型中可能有很多个驱动

3.4 sensor 加载顺序
代码位置
vendor/vendor/mediatek/proprietary/tinysys/freertos/source/drivers/CM4_A/$PLATFORM/overlay/inc/

目录下的文件mtk_overlay_init.h,它被overlay.c文件引用。

这段枚举,定义了每个sensor类型在overlay时的顺序编号。

在这里插入图片描述
在这里插入图片描述

上图的代码来自mtk_overlay_init.c文件,里面设置overlay table时使用的switch判断条件就是section的id。

在switch判断完成之后,所有sensor类型的虚拟地址vma,大小size等参数会被复制到table中,之后在进行加载时也是以section的id为判断依据。

理论上不同sensor类型的加载顺序可以改变

但是改变sensor加载顺序需要对后续所有相关代码的id顺序进行修改,修改会非常麻烦,容易出现bug。

所以一般情况下不改变sensor的加载顺序。

3.5 加载驱动流程

下面加载驱动的流程都是以挂载在SCP侧的驱动为例:

想要加载一个新的驱动,需要把驱动添加到如下目录中:
vendor/vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/ P L A T F O R M / PLATFORM/ PLATFORM/PROJECT/cust/

不同的目录是负责加载不同的传感器的:

accGyro加载加速度、陀螺仪传感器
alsps负责加载光距感传感器
barometer加载气压计传感器
magnetometer加载地磁传感器
overlay负责加载sensor overlay

3.6 添加客制化sensor信息

以加速度传感器为例,将需要添加的传感器添加到文件cust_accGyro.c中
在这里插入图片描述
文件路径:vendor/vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/ P L A T F O R M / PLATFORM/ PLATFORM/PROJECT/cust/accGyro/

路径中包含的 P L A T F O R M 是指 M T K S O C 平台代码, PLATFORM是指MTK SOC平台代码, PLATFORM是指MTKSOC平台代码,PROJECT是项目代码

配置包含sensor的方向以及i2c地址等等,需要根据实际情况进行修改

补充:对于.direction参数,在目录**/vendor/vendor/mediatek/proprietary/tinysys/freertos/source/middleware/contexthub/**下的hwsen.c文件中有详细体现
在这里插入图片描述参数0-7对应map[]中的8个元素,前面的参数±1表示取该轴的哪个方向为正方向,后面的参数0、1、2分别表示xyz轴,如map[1]表示芯片的正方向为x,-y,z

3.7 启用overlay功能,添加sensor编译宏
vendor/vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/ P L A T F O R M / PLATFORM/ PLATFORM/PROJECT/

在文件ProjectConfig.mk中添加
将传感器驱动添加到系统编译中
在这里插入图片描述目录:
vendor/vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/$PLATFORM//platform/feature_config/
在文件chre.mk中添加
判断条件由上一步的编译宏控制
在这里插入图片描述
3.8 将传感器驱动添加到overlayremap中
vendor/vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/ P L A T F O R M / PLATFORM/ PLATFORM/PROJECT/cust/overlay.c
在链接脚本中添加对象,添加到对应传感器区域
在这里插入图片描述

如加速度传感器添加到ACC中:
vendor/vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/ P L A T F O R M / PLATFORM/ PLATFORM/PROJECT/inc/overlay_sensor.c
在这里插入图片描述

四,kernel 层

4.1 kernel层代码位于kernel文件夹下,至于kernel版本会在device下定义,我们先看kernel-4.14。sensor在kernel中的代码位于:

kernel-4.14/drivers/misc/mediatek/sensor
kernel-4.14/drivers/misc/mediatek/sensors-1.0
kernel-4.14/drivers/staging/nanohub

sensor 文件夹下有一个我们要的类hf_manager.c,打开这个文件不然发现,它创建了节点dev/hf_manager,这刚好就和hal层的HfManager.cpp 链接上了,hal层的指令通过这个节点来到了kernel,这是一个普通的文件节点,里面有一些读写、指令操作。这里面有个核心结构体hf_core,后面很多操作都和这个结构体有关系

struct hf_core {

          struct mutex manager_lock;

          struct list_head manager_list; //外面注册的manager

          struct sensor_state state[SENSOR_TYPE_SENSOR_MAX];

     

          spinlock_t client_lock;

          struct list_head client_list;

     

          struct mutex device_lock;

          struct list_head device_list;

     

          struct kthread_worker kworker;

首先我们看下hf_manager 被打开时做了什么事情:创造了一个hf_client,这个hf_client记录了当前进程和线程的id,还创建了一个FIFO,用于数据交换

static int hf_manager_open(struct inode *inode, struct file *filp)

     {

         struct hf_client *client = hf_client_create();

       

         if (!client)

             return -ENOMEM;

       

         filp->private_data = client;   

         nonseekable_open(inode, filp);

         return 0;

     }

然后,大概浏览一下代码不难发现,指令好像后面都被hf_device这个结构体承担了,这个结构体来自与hf_manager,hf_manager 每次使用之前都会调用hf_manager_find_manager方法来查找,那我么看看这个方法做了什么:

 static struct hf_manager *hf_manager_find_manager(struct hf_core *core,

              uint8_t sensor_type)

      {

          int i = 0;

          struct hf_manager *manager = NULL;

          struct hf_device *device = NULL;

     

          list_for_each_entry(manager, &core->manager_list, list) {

              device = READ_ONCE(manager->hf_dev);

              if (!device || !device->support_list)

                  continue;

              for (i = 0; i < device->support_size; ++i) {

                  if (sensor_type == device->support_list[i].sensor_type)

                      return manager;

              }

          }

          pr_err("Failed to find manager, %u unregistered\n", sensor_type);

          return NULL;

      }

发现它只是从一个list中去查找,根据sensor_type进行匹配,这个core→manager_list 又是由hf_manager_create方法进行注册,而这个方法是向外提供的,然后搜索一下不难发现:

./2.0/sensorhub/transceiver.c 和 ./2.0/mtk_nanohub/mtk_nanohub.c使用到了它,也就是说这两个类分别注册了自己的hf_device,并且进行了相关的数据处理,这两个类所处的文件夹可以猜测一个是跟sensorhub相关,另一个则和CHRE相关。

4.2 sensor hub

sensor hub是个什么东西呢,故名思意,它是一个传感器集线器,也就是说某些传感器的数据要经过这个地方进行中转,transceiver.c它会和SCP通过IPI通信,将这边的指令还有DRAM地址发送到SCP端,然后把SCP 端的信息回传,先是读取DRAM内存获取信息,然后通过manager→report方法会传到hf_fifo,然后hf_fifo上的数据会被hal层读走。

ap侧sensor hub 通过kernel-4.14/drivers/misc/mediatek/sensor/2.0/sensorhub/ipi_comm.c和SCP侧建立链接:IPI_IN_SENSOR_NOTIFY接收ID,IPI_OUT_SENSOR_NOTIFY接收ID,IPI_IN_SENSOR_CTRL指令ID

sensor hub 所链接的SCP 侧在:vendor/mediatek/proprietary/tinysys/scp/middleware/sensorhub/comm/ipi_comm.c

4.3 nano hub

nano hub 是CHRE框架中的集线器,和sensor hub类似,nano hub 也是通过mtk_nonohub.c注册了hf_device ,和SCP通过IPI通信,将DRAM地址发送到SCP端,通过IPI把指令发过去,但是通过DRAM把信息读回来,然后通过manager→report 传递到hal层

ap侧nano hub 通过kernel-4.14/drivers/misc/mediatek/sensor/2.0/mtk_nanohub/nanohub/nanohub-mtk.c 和SCP建立链接 通过ID IPI_CHRE

nanohub 所链接的SCP侧在:vendor/mediatek/proprietary/hardware/contexthub/firmware/links/plat/src/hostIntfIPI.c

然后CHRE会调用bool SensorQueueEnqueue(struct SimpleQueue* sq, const void *data, int length, bool possiblyDiscardable)将数据传递到scp/middleware/contexthub/contexthub_fw.c,然后contexthub_fw.c 将数据写入DRAM,供AP侧读取

还有一部分指令会通过IPI_SENSOR直接传递到scp/middleware/contexthub/contexthub_fw.c

vendor/mediatek/proprierary/hardware/contexthub/firmware 下面有一些sensor,会将数据传递给hostIntf,然后传递给contexthub.c

vendor/mediatek/proprierary/tinysys/scp/middleware/sensorhub 下面也有一些sensor会传递信息

五,hal层的实现

真正实现hal转接口的代码是在:vendor/mediatek/proprietary/hardware/sensor 这个文件夹中也会有多个版本的代码根据android.mk 进行选择,由宏控制,选择相应的版本,当前选择最新2.0进行讨论
与framework层通信的代码在hidl文件夹下有多个文件夹:
在这里插入图片描述

1.0/2.0 表示版本号,配置hal哪个版本就哪个
multihal:多hal,需要单独配置由/vendor/etc/sensors/hals.conf这个文件控制
Sensors.h 中可以看出Sensors 继承了ISensors并实现了这些方法

从Sensors.cpp代码可以看出,Sensors初始化时会先判断是否使用了多hal,如果使用则会加载多hal模块,如果使用则通过hw_get_module加载id为SENSORS_HARDWARE_MODULE_ID的模块,并把它赋值给了mSensorModule。发现这个模块代码就放在sensor目录下面对应的那些不同版本的文件夹下,直接到vendor/mediatek/proprietary/hardware/sensor/2.0/hal 这个目录下放的都是2.0 hal 的代码,其中sensors.cpp 中的正式id为SENSORS_HARDWARE_MODULE_ID的模块

static struct hw_module_methods_t sensors_module_methods = {

        .open = open_sensors

    };


    struct sensors_module_t HAL_MODULE_INFO_SYM = {

        .common = {

            .tag = HARDWARE_MODULE_TAG,

            .version_major = 1,

            .version_minor = 0,

            .id = SENSORS_HARDWARE_MODULE_ID,

            .name = "MTK SENSORS Module",

            .author = "Mediatek",

            .methods = &sensors_module_methods,

        },

所以可以从此看出,从framework层过来的指令给了mSensorModule和mSensorDevice 进行处理,间接的传递给了这个模块处理,然后此模块又分出很多个类进行分别处理不同的指令,部分指令又会汇集到一个类去和另一个层通信它就是HfManager,这个类在2.0/core/文件夹下,

进到HfManager 我们发现,这个类里面还有一个内部类HfLooper,但是无论哪个类,他们的方法最后会通过一个节点他就是dev/hf_manager,hal层则是通过这个节点来到了kernel层kernel-4.14/d/misc/mediatek/sensor/2.0/core/hf_manager.h

所以,整个框架信息传递如下图:
在这里插入图片描述

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android中的Sensor驱动框架是用于管理和处理各种传感器数据的软件框架。它的主要功能是提供一种标准化的接口,使应用程序可以轻松地访问和使用各种传感器Android中的Sensor驱动框架由以下两个主要组件组成: 1. Sensor HAL(硬件抽象层):这是Android操作系统与各种硬件传感器之间的接口。它定义了一组标准API,使Android可以与各种不同类型的传感器交互。 2. Sensor Manager:这是一个Android系统服务,它提供了一组API,使应用程序可以轻松地获取和使用各种传感器数据。它还负责管理各种传感器的注册和注销,以及传感器数据的传递和处理。 在Android中,可以使用以下几种传感器: 1. 加速度计(Accelerometer):用于测量设备的加速度。 2. 陀螺仪(Gyroscope):用于测量设备的旋转速度和方向。 3. 磁力计(Magnetometer):用于测量设备的磁场。 4. 温度传感器(Temperature Sensor):用于测量设备的温度。 5. 光传感器(Light Sensor):用于测量设备的光线强度。 6. 压力传感器(Pressure Sensor):用于测量环境的气压。 7. 重力传感器(Gravity Sensor):用于测量设备的重力加速度。 8. 线性加速度计(Linear Acceleration Sensor):用于测量设备在三个轴向上的线性加速度。 9. 旋转矢量传感器(Rotation Vector Sensor):用于测量设备的旋转矢量。 以上是Android中常用的传感器类型,每种传感器都有其特定的用途和应用场景。在开发Android应用程序时,可以根据需要选择合适的传感器来获取所需的数据,并使用Sensor驱动框架来管理和处理这些数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤舟簔笠翁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值