一、概念
1. Android系统组成:应用层、框架层、硬件抽象层、Linux驱动层。
2. Scp:是用来处理sensor和audio相关功能和其他客制化需求的一个协处理器,MTK scp选择freeRTOS作为操作系统。
3. HAL:
4. kernel:
5. I2C:双向二线制同步串行总线。它只需要两根线即可在连接于总线上的设备之间传送信息。
6. 驱动目录:
(1)AP侧:
kernel-4.14/drivers/misc/mediatek/sensors-1.0
(2)SCP侧:
vendor/mediatek/proprietary/tinysys/freertos/source/middleware/contexthub/MEMS_Driver
7. hal层和framework层通信使用的是HIDL(硬件抽象层接口定义语言),底层使用的都是binder机制实现跨进程通信。
二、器件点亮
MTK sensor 分为AP和SCP两大部分,AP主芯片,SCP协处理器,都可以负责处理sensor数据。
1. sensor挂在AP侧,由mtk-Hal 层和 kernel 组成,其主要思想在于实现了一个HfManager 完成了对多个sensor 的control 处理由一个.cpp 处理(以kernel-4.9 / sensor-1.0为例)
(1) 根据原理图编辑对应的dts;
(2) 将拿到的代码合入到kernel-4.19/drivers/misc/mediatek/sensors-1.0对应的器件子目录,在新增的子目录中增加Makefile跟Kconfig文件,Kconfig中就配置下当前器件模块名称,Makefile指定编译的文件与文件目标;
(3) 在 kernel-4.19/arch/arm64/configs对应的config配置文件enable对应的sensor,例如我调的时light sensor 跟p sensor器件,配置CONFIG_CUSTOM_KERNEL_ALSPS=y,因为只有这个选项配置了,kernel-4.19/drivers/misc/mediatek/sensors-1.0/Makefile才配置对应的模块进行编译;增加步骤一的某块名称如CONFIG_MTK_XXX=y;
(4) 编辑device/custom/custom_project/ProjectConfig.mk文件,enable对应的sensor模块,例如我的时L/P sensor挂载在AP侧,那就编辑CUSTOM_KERNEL_ALSPS = yes;
(5) 开始编译内核,解决对应的编译问题;
(6) 新boot.img,scp.img文件,抓内核的开机日志,看是否有正常跑到module_init;
(7) 安装应用查看应用层是否能获取到对应的sensor。如果没有获取到,这里需要关注下驱动的probe代码中是否有调用sensorlist_register_deviceinfo进行sensor注册,如果没有sensorlist中是获取不到新增的sensor的件;
2. sensor挂在SCP侧
(1)添加器件原厂提供的驱动文件path:vendor/mediatek/proprietary/tinysys/freertos/source/middleware/contexthub/MEMS_Driver/accGyro;
(2)修改
path:vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/project/
CustomerProject/ProjectConfig.mk文件,定义支持新增的sensor如:CFG_XXXX_SUPORT = yes;
(3)修改vendor/mediatek/proprietary/tinsys/freertos/source/project/CM4_A/project/platform/feature_config/chre.mk,根据步骤2中的定义控制驱动代码参与编译;
(4) 修改vendor/mediatek/proprietary/tinsys/freetos/source/project/CM4_A/project/customerporject/inc/overlay_sensor.h,看是什么sensor,例如我添加的是gsensor,则修改
#define OVERLAY_SECTION_ACCGYRO, 添加新的器件
(5)修改vendor/mediatek/proprietary/tinsys/freetos/source/project/CM4_A/project/customerproject/cust/overlay/overlay.c,修改accGyroOverlayRemap,添加新的器件;
(6)修改vendor/mediatek/proprietary/tinsys/freertos/source/project/CM4_A/project/customerproject/cust/accGyro/cust_accGyro.c,根据原理图添加器件的对应的i2c引脚;
(7)然后就开始编译,如果编译中提示超出memory,那就需要修改下 vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/project/platform/Setting.ini根据对应的编译错误修改对应的size;
(8)更新scp.img,重启抓scp日志,查看日志是否有正常加载器
三、HAL
1. hal层代码接口位于:hardware/interfaces/sensors/
ISensorsCallback.hal 里面定义的动态sensor的回调接口
ISensors.hal 里面定义的是服务的主要功能接口
types.hal 里面定义的是一些要用到的结构类型
multihal里面是关于多hal的实现,vts里面是vs测试相关
2. hal的实现
真正实现hal转接口的代码是在:vendor/mediatek/proprietary/hardware/sensor, 这个文件夹中也会有多个版本的代码根据android.mk 进行选择,由宏控制,选择相应的版本。
四、sensor hub
1. 概念:智能传感集线器,是一种基于低功耗MCU(微控制单元,如STM32单片机)和轻量级RTOS操作系统之上的软硬件结合的解决方案,其主要功能是连接并处理来自各种传感器设备的数据。
2. 主要功能:
(1)在CPU休眠的情况下,实现对传感器的实时控制,从而达到降低功耗的功能;
(2)将不同类型Sensor的数据进行融合,实现多种sensor数据结合才能实现的功能;
(3)多种物理sensor的数据,可以根据需要,拆解或融合成虚拟sensor,来满足功能需求;
3. 配置路径:
path: vendor/mediatek/proprietary/tinysys/freertos/source/project/CM4_A/mt6771/power3_k71_bsp/cust
五、sensor框架及信息传递流程
(整个sensor体系中包括:应用层、framework层、jni、hal层、kernel层、SCP/CHRE)
1. 应用层
(1)获取到 SensorManager 的实例
SensorManager senserManager
= (SensorManager)getSystemService(Context.SENSOR_SERVICE);
(2)SensorManager 是系统所有传感器的管理器,有了它的实例之后就可以调用 getDefaultSensor()方法来得到任意的传感器类型了
Sensor mAccelerometer
= mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
(3)需要对传感器输出的信号进行监听,借助 SensorEventListener 来实现。
SensorEventListener listener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// 当传感器的精度发生变化时就会调用
}
@Override
public void onSensorChanged(SensorEvent event) {
// 当传感器监测到的数值发生变化时就会调用
// 方法中传入了一个 SensorEvent 参数,这个参数里又包含了一个 values 数组,
// 所有传感器输出的信息都是存放在这里的
}
};
(4)在恢复时:
protected void onResume() {
super.onResume();
//需要调用SensorManager的registerListener()方法来注册SensorEventListener才能使其生效;
mSensorManager.registerListener(this,mAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
/*
注册sensor的信息回调
registerListener()方法接收三个参数,第一个参数就是 SensorEventListener 的实例,
第二个参数是 Sensor 的实例,这两个参数我们在前面都已经成功得到了。
第三个参数是用于表示传感器输出信息的更新速率
SENSOR_DELAY_UI
SENSOR_DELAY_NORMAL
SENSOR_DELAY_GAME
SENSOR_DELAY_FASTEST 这四种值可选,它们的更新速率是依次递增的。
*/
}
(5)在暂停时:
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
//当程序退出或传感器使用完毕时, 一定要调用 unregisterListener ()方法将使用的资源释放掉
}
2. framework层
经过上层的getSystemService获取了服务,功能就来到了framework层。
(1)对应的代理抽象类:
path: framework/base/core/java/android/hardware/SensorManager.java
真正获取服务的类是:SystemSensorManager
path: framework/base/core/java/android/hardware/SystemSensorManager.java
(2)SystemSensorManager在最上层控制着所有的sensor ,他的实现仅仅靠自己是不够的,它还链接了一个jni库,注册了很多native方法。
android_hardware_SensorManager:framework/base/core/jni/android_hardware_SensorManager.cpp
android_hardware_SensorManager用来绑定java类和相关方法的。然后又将方法实现转移到SensorManager.cpp:framework/native/libs/sensor/SensorManager.cpp
(3)SystemSensorManager创建时 会创建native SensorManager的实例并持有,然后获取sensorlist。SystemSensorManager中封装了很多方法,如:启用、禁用、刷新、添加监听等。SensorManager也不是自己去做事情,它通过BitTube(BitTube是用来处理进程间通讯的机制,和管道类似,主要是对socketpair的封装)和SensorService 链接,将指令传到sensorservice。android_hardware_SensorManager 有一个内部类专门监听了BitTube通道文件描述符,会将sensor上报的信息通过这里上报到上层。