
MTK平台的Sensor驱动调试最让人头疼的往往不是驱动代码本身而是数据从AP到SCP这条链路上到底谁在管、谁在转、谁在算。很多刚接触MTK平台的兄弟一上来就扎进kernel层的驱动文件里改寄存器改了半天发现数据压根没从SCP侧传上来或者SCP传上来的数据格式跟AP侧解析的对不上白白浪费好几天。这篇内容就把MTK Sensor驱动从AP侧到SCP侧的完整调试流程拆开讲清楚包括Tinysys的基本概念、驱动分层结构、数据通路、实际调试步骤以及我在项目中踩过的那些坑。不管你是刚接手MTK平台Sensor bringup的新手还是想搞清楚SCP侧到底在干什么的老手这篇都能给你一条清晰的排查路径。1. 先搞清楚MTK Sensor架构里AP和SCP到底各管什么1.1 AP侧和SCP侧的分工逻辑MTK平台从Helio系列开始Sensor的处理架构就逐渐从AP侧独揽转向APSCP协同。AP就是Application Processor跑Android系统那一套负责上层应用、HAL层、Sensor Service。SCP是Sensor Control Processor的缩写它是MTK平台里一个独立的低功耗协处理器跑的是Tinysys操作系统。Tinysys是MTK自研的一个RTOS专门用来处理Sensor数据采集、融合运算这类需要低功耗常开的任务。为什么要这么分核心原因是功耗。如果所有Sensor数据都让AP来处理AP就得频繁从休眠中唤醒续航直接崩掉。把计步、抬腕、方向融合这些任务丢给SCPAP可以安心睡觉SCP用极低的功耗维持Sensor数据流的运转。只有当上层App真正需要数据时AP才被唤醒去SCP拿结果。所以你在调试时会发现MTK的Sensor驱动代码实际上分布在两个地方一个是AP侧的kernel驱动通常在kernel-4.19/drivers/misc/mediatek/sensors/下面另一个是SCP侧的代码在vendor/mediatek/proprietary/tinysys/scp/里面。两边通过共享内存和IPC机制通信。1.2 Tinysys在Sensor链路中的角色Tinysys不是一个简单的透传层。它上面跑着SCP侧的Sensor框架包括Sensor Manager、Driver层、以及各种算法模块。SCP侧的驱动直接操作硬件寄存器去读取原始数据然后经过初步处理后通过共享内存传给AP侧。AP侧的kernel驱动拿到数据后再通过HAL层上报给Android的SensorService。这里有个关键点SCP侧的代码和AP侧的代码是独立编译的。SCP的固件是一个单独的bin文件通常在scp.img或者scp_ramdisk.img里面。你改了SCP侧的代码必须重新编译SCP固件并烧录光编译kernel是没用的。这一点我在第一次调试MTK Sensor时吃了大亏改了SCP代码只push了kernel的ko文件结果死活不生效后来才发现SCP固件根本没更新。1.3 数据从硬件到App的完整通路一颗Sensor从硬件到App的数据通路大致是这样的Sensor硬件产生原始数据通过I2C或SPI总线传到SCP侧的驱动SCP驱动读取后交给SCP Sensor框架框架根据配置决定是直接在SCP侧处理还是透传给AP。如果需要在SCP侧做融合运算数据会在SCP内部流转如果需要上报给AP数据会被写入AP和SCP之间的共享内存区域然后通过IPC中断通知AP侧。AP侧kernel驱动收到中断后从共享内存读取数据再通过input子系统或者sensor class上报到HAL层最终到达Android SensorService。理解这条通路非常重要因为调试时你需要判断问题出在哪一段。是I2C通信本身就不通还是SCP侧驱动读到了数据但没传上来还是AP侧收到了但解析错了每一段的排查方法都不一样。2. 调试环境搭建与SCP固件编译的关键细节2.1 代码目录结构与关键文件定位MTK平台的Sensor相关代码分散在多个目录先把关键路径列清楚。AP侧kernel驱动一般在kernel-4.19/drivers/misc/mediatek/sensors/ ├── hwmon/ │ ├── accelerometer/ │ ├── gyroscope/ │ ├── magnetometer/ │ ├── alsps/ │ └── ... ├── sensorHub/ └── ...SCP侧代码在vendor/mediatek/proprietary/tinysys/scp/ ├── middleware/ │ └── sensor/ │ ├── driver/ │ └── ... ├── project/ │ └── mtXXXX/ └── ...配置文件通常在vendor/mediatek/proprietary/tinysys/scp/project/下面每个项目有自己的文件夹里面定义了哪些Sensor被使能、I2C地址、中断引脚等。2.2 SCP固件编译与烧录的注意事项编译SCP固件不像编译kernel那么简单。你需要先确认编译环境里SCP的toolchain是否配置正确。通常MTK的编译脚本会通过make scp或者在整个工程编译时自动带上SCP。但如果你只改了SCP代码单独编译SCP的命令大概是./mk -t scp project_name编译完成后生成的scp.img需要跟其他镜像一起烧录。这里有个坑有些项目SCP固件是打包在scp_ramdisk.img里的有些是独立的scp.img具体看项目的partition表。烧录时如果只烧了boot.img而没烧SCP相关的img你的修改就不会生效。另外SCP固件烧录后需要重启设备才能加载。有些平台支持通过sysfs节点触发SCP reload但大多数情况下还是老老实实重启。2.3 调试工具与日志抓取方式调试MTK Sensor最常用的日志来源有几个。AP侧kernel log用dmesg或者adb shell cat /proc/kmsg。SCP侧的日志需要通过特定通道抓取MTK提供了scp_log相关的节点通常在/sys/kernel/debug/scp/下面。你可以用adb shell cat /sys/kernel/debug/scp/log或者有些平台是/proc/scp_log。如果SCP日志没开需要在SCP的配置里使能log输出等级。我一般会把SCP log level调到最高虽然日志量大但排查问题时信息最全。还有一个工具是metalogMTK的日志系统可以同时抓AP和SCP的日志并打上时间戳方便对照分析。用metalog -s启动日志会存在/data/metalog/下面。3. AP侧驱动调试的核心操作与常见问题3.1 设备树与GPIO配置的核对AP侧驱动调试的第一步不是看驱动代码而是核对设备树DTS配置。MTK平台的Sensor在DTS里的配置包括I2C总线号、设备地址、中断GPIO、供电GPIO等。这些配置如果错了驱动加载了也读不到数据。以加速度计为例DTS里通常有这样的节点accelerometer68 { compatible mediatek,accelerometer; reg 0x68; interrupt-parent pio; interrupts 12 IRQ_TYPE_EDGE_RISING; vdd-supply mt_pmic_vio28_ldo_reg; ... };你需要确认几个点I2C地址跟硬件原理图是否一致中断引脚编号是否正确供电LDO是否使能。我遇到过好几次中断引脚配错导致数据不更新的情况因为Sensor的INT引脚没接对驱动一直在等中断但永远等不到。3.2 I2C通信是否正常的快速验证在深入驱动逻辑之前先确认I2C通信本身是通的。最直接的方法是用i2c-toolsadb shell i2cdetect -y bus_number如果能看到Sensor的地址出现在列表里说明I2C物理连接和基本通信没问题。如果看不到那就要查硬件焊接、上拉电阻、供电是否正常。进一步可以用i2cget读取Sensor的WHO_AM_I寄存器确认读到的值跟datasheet一致adb shell i2cget -y bus_number device_addr register_addr这一步能排除很多低级问题。我见过有人调了两天驱动最后发现是I2C总线上拉电阻没焊。3.3 数据上报通路的排查方法如果I2C通信正常但App收不到数据就要排查数据上报通路。AP侧kernel驱动通常通过input子系统或者sensor_class上报数据。你可以先看/sys/class/sensor/下面的节点是否有数据变化或者用getevent看input事件adb shell getevent -l如果kernel层有数据但HAL层没有那问题可能出在HAL的配置或者SCP到AP的数据传递上。这时候需要同时抓AP和SCP的日志对照看。4. SCP侧调试数据不通时怎么逐层排查4.1 SCP侧驱动加载状态的确认SCP侧的驱动加载日志是排查的第一手资料。在SCP log里搜索驱动名称看是否有probe成功的打印。如果SCP侧驱动根本没加载AP侧再怎么调也没用。SCP侧驱动的probe流程跟AP侧类似会去读chip id、配置寄存器、注册中断等。如果probe失败日志里通常会有错误码。常见的失败原因包括I2C地址配错、GPIO配置冲突、供电未使能等。4.2 共享内存与IPC通信的检查AP和SCP之间的数据传递依赖共享内存和IPC。如果SCP侧读到了数据但AP侧收不到就要检查共享内存区域是否正常初始化、IPC中断是否触发。在AP侧kernel log里搜索scp相关的IPC日志看是否有中断收到但数据解析失败的打印。SCP侧则看是否有写入共享内存的日志。两边对照就能定位是发送端没发还是接收端没收。有个常见问题是共享内存的地址或大小配置不对导致SCP写入了但AP读的是另一块区域。这种问题通常需要核对scp_reserve_mem相关的DTS配置。4.3 SCP侧算法模块的配置与影响很多Sensor数据在SCP侧会经过算法处理比如计步、方向融合、抬腕检测等。如果算法模块配置不对可能导致数据被错误处理或者根本不上报。SCP侧的算法配置通常在vendor/mediatek/proprietary/tinysys/scp/middleware/sensor/下面的配置文件里。你需要确认哪些算法被使能、输入输出格式是什么。我遇到过因为算法模块的输入数据率配置跟驱动不匹配导致算法一直输出无效值的情况。5. 几个真实踩坑案例与排查思路复盘5.1 案例一SCP固件未更新导致调试无效这个坑我在前面提过但值得展开说。当时改了SCP侧的驱动代码编译了kernel并push了ko文件重启后发现问题依旧。抓SCP log发现打印的还是旧代码的日志。后来才意识到SCP固件是独立编译和烧录的只更新kernel没用。重新编译SCP并烧录scp.img后问题解决。教训每次改SCP代码必须确认SCP固件被重新编译并烧录。可以通过SCP log里的版本号或者编译时间戳来确认。5.2 案例二I2C地址冲突导致probe失败有一次调试一颗新的ALSPS SensorI2C地址配的是0x48但probe一直失败。用i2cdetect扫描发现0x48地址上有两个设备响应。查原理图发现另一颗Sensor也用了0x48地址硬件上冲突了。解决办法是改其中一颗的地址引脚配置或者换到不同的I2C总线。这个问题的排查思路是probe失败先看I2C通信i2cdetect能快速暴露地址冲突。5.3 案例三中断触发方式配错导致数据不更新还有一次是加速度计数据一直不更新但手动读寄存器有数据。查DTS发现中断配置的是IRQ_TYPE_EDGE_RISING但Sensor的INT引脚实际是低电平有效。改成IRQ_TYPE_LEVEL_LOW后数据正常更新。中断触发方式一定要跟Sensor datasheet里的INT配置一致上升沿、下降沿、高电平、低电平四种组合不能配错。6. 提升调试效率的几个实用技巧6.1 善用SCP log level动态调整SCP的log level可以在运行时通过sysfs节点调整不用重新编译固件。具体节点路径看平台通常在/sys/kernel/debug/scp/log_level或者类似位置。把level调高可以看到更详细的驱动和框架日志排查完再调回去减少日志量。6.2 用metalog做AP和SCP日志的时间对齐AP和SCP的日志时间戳基准可能不同直接对照容易看错。metalog会把两边日志统一到一个时间轴上排查跨AP-SCP的问题时特别有用。启动metalog后复现问题然后拉出日志文件分析比分别抓两边日志再手动对齐效率高得多。6.3 建立自己的调试检查清单调多了之后我总结了一个检查清单每次遇到Sensor问题按顺序过一遍I2C通信是否正常、DTS配置是否跟硬件一致、SCP固件是否最新、SCP驱动probe是否成功、共享内存和IPC是否正常、算法配置是否匹配。按这个顺序排查大部分问题都能在半小时内定位。这个清单不是死的不同项目可能有不同的侧重点但核心思路是先确认底层通信再往上查数据通路最后看算法和应用层。从下往上排查比一上来就改上层代码有效得多。调试MTK Sensor驱动说到底就是对整条数据链路的理解程度。你知道数据从哪来、经过谁、到哪去排查时就能有的放矢。AP和SCP的分工是MTK平台的设计特点理解了这个架构调试就不再是碰运气。希望这些经验能帮你在下一个项目中少走弯路。