MTK平台 -- Msensor移植(Android 5.1 -7.1)

mac2026-01-05  8

文章目录

前言背景步骤移植、编译刷机验证I2C地址问题msenor方向及校准 msensor软件如何实现兼容总结

前言

  对于驱动工程师来说,sensor是很基础的东西,很多人刚开始接触驱动都是从sensor开始的。这篇记录其实是很久之前的了,这段时间正好在整理以前的一些文章,于是重新梳理一下。

背景

  工作环境:linux,platform_version=android 5.1,mt6580;   工作任务:在原有的项目基础上兼容msensor AF8133J;

步骤

移植、编译

  此款msensor以前没有在Android 5.1中使用过,我只找到应用在Android 7.1上的一套代码,因为msensor的代码量不大,把Android 5.1中和Android 7.1中msensor的代码都看了一遍,发现除了获取i2c_address、i2c_num、direction、power_id、power_vol等属性的方式不一样,其它地方基本上一样,于是决定就采用Android 7.1中的代码,初期完成得很顺利,修改代码->编译->修改编译报错;修改了st480_init()函数中部分代码,如下:

原代码:

static int __init afx133_init(void) { const char *name = "mediatek,afx133"; hw = get_mag_dts_func(name, hw); #if 1 //def CONFIG_MTK_LEGACY struct i2c_board_info i2c_afx133={ I2C_BOARD_INFO("afx133", hw->i2c_addr[0])i2c_register_board_info(hw->i2c_num, &i2c_afx133, 1); #endif if(mag_driver_add(&afx133_init_info) < 0) { MAG_ALOGE("mag_driver_add failed!\n"); } return 0; }

修改后代码:

static int __init afx133_init(void) { hw = afx133_get_cust_mag_hw(); #if 1 struct i2c_board_info i2c_afx133={ I2C_BOARD_INFO("afx133", (0X1e))}; i2c_register_board_info(hw->i2c_num, &i2c_afx133, 1); #endif if(mag_driver_add(&afx133_init_info) < 0) { MAG_ALOGE("mag_driver_add failed!\n"); } return 0; }

  当然,肯定不仅仅修改这些,有些结构体的定义的方式因平台不同有差异,需做简单的修改,头文件的引用方式等也不太一样……回到上面所说的修改处,从上述代码中可以看出来,获取hw这个结构体的方式不一样,在Android 7.1中,是根据dts节点去获取,节点定义如下:

cust_mag@1 { compatible = "mediatek,afx133"; i2c_num = <2>; i2c_addr = <0x1E 0 0 0>; direction = <6>; power_id = <0xffff>; power_vol = <0>; is_batch_supported = <0>; };

  在Android 5.1中,没有使用dts文件,afx133_get_cust_mag_hw这个函数被单独定义在一个文件中,如下:

static struct mag_hw afx133_cust_mag_hw = { .i2c_num = 2, .direction = 6,//0 .power_id = MT65XX_POWER_NONE, /*!< LDO is not used */ .power_vol= VOL_DEFAULT, /*!< LDO is not used */ }; struct mag_hw* afx133_get_cust_mag_hw(void) { return &afx133_cust_mag_hw; }

  可以看出,实际上两者获取的信息是一样的,其它代码是可以不做改变的。

刷机验证

  在顺利编译完成之后,接下来就是刷机验证,但是,在打印的log中报了一个注册设备失败的错误,为什么失败呢?是因为I2C地址出错了,I2C的地址该从哪里得知呢(当时还是个小白)?问硬件么?后来同事告诉我可以从规格书中查看I2C的地址(这里的I2C地址指的是从设备地址,唯一的地址),I2C地址是拿来干什么的呢?经过查阅资料后我的理解:I2C总线有一个总的控制器,同时在I2C总线上挂着许多从设备,每一个从设备都有一个属于自己的专有地址,主设备不需要地址,因为I2C 是主从设备,主设备读写,从设备被动接受读写,因此主设备需要知道从设备的地址。 从设备的地址是已经固定了的吗?一般来说从设备的地址是厂商已经在寄存器里面写好了的,这个时候就需要结合代码仔细查看规格书。

I2C地址问题

  AF8133J规格书中关于I2C的内容如下:   从图中可以看出,I2C地址一共有两组,从硬件的角度来看,GND表接地,下拉,I2C地址为0x1E;DVDD表上拉,I2C地址为0x1C,两组I2C地址是为了必要的时候多一个选择;   OK,现在I2C地址也配对了,继续编译,刷机,嗷呜~悲剧了!机器这次直接起不来了,查看log,发现还是I2C的错误,打印addr的值为d,但是我在驱动中配置的是0x1E。   思路一:   难道驱动中其它地方会去修改这个值吗?仔细去看了代码,发现并没有其它地方对它 做了修改;   思路二:   dws文件里面可以对I2C的地址进行配置,看了一下dws文件,Msensor的I2C地址是0x0d,和打印出来的addr的值一样,试着修改了一下,然后就正常了。

疑问: 1、按照正常的思路,如果驱动里面对其进行了赋值,应该是以驱动为准,为什么dws还会有影响? 2、看了兼容之前用的Msensor,I2C地址是0x0c,和dws里面的0x0d也是不符的,为什么之前的代码能正常使用?

msenor方向及校准

  做了以上的修改后,机器能正常启动,#11#进入地磁测试界面,任由我东南西北的旋转手机,指南针在那里稳若磐石,一点都没有身为指南针该有的自觉。后来,在同事的帮助下,知道了原来指南针还需要有一个守护进程,于是去7.1的代码中找到文件放在5.1中,哈哈指南针动了,但是方向不对,我开始想着这个问题不大,direction的值为0~7,最坏的结果就是每个值都试一下,但是……

  是的,转折又来了……

  确定指南针的方向有两种:   1)、0~7这几个数字一个一个的试,比较慢,但是不需动脑,只需动手就好了;

  2)、有的规格书上会标向,需要结合硬件的贴片方式来看,从机子正面看过去靠近左下角的那个方向为正确的方向。(这种方法是听同事说的,还没实践过,因为这次做兼容的Msensor规格书上没标)

  然而,我把所有的数字都试完了,方向一点变化都没有,郁闷了,思考良久,难道方向没起作用,记得方向可以在设备节点里面打印,打印出来看了一下,果然,direction这个变量一直是0(下次记得更改之后要去确定恒修改是否生效,免得浪费时间);又倒回去看代码,去跟踪direction这个变量……,等等!我看到了什么? 在文件的开头定义了全局变量hw:

struct mag_hw mag_cust; static struct mag_hw *hw = &mag_cust;

在afx133_init()这个函数中定义了一个局部变量hw:

struct hw = afx133_get_cust_mag_hw();

  恍然大悟,难怪通过afx133_get_cust_mag_hw获得的direction打印出来的值一直没变,因为全局变量hw压根就没得到值,默认为0,把afx133_init()函数中的struct去掉,方向起作用了……一场局部变量引起的灾难(没有认认真真的写过代码对全局和局部不敏感);

  然后我又挨着试了一下,但是……还是没找到能用的,又思考良久,无果……跑去问同事,同事一句“你校准了吗?msensor使用之前都要校准的”让我茅塞顿开,于是,我又开始了校准之路~终于!这次没出状况,顺利完成!

msensor软件如何实现兼容

  通过对驱动模块的粗略了解,大概知道mtk平台驱动实际上分为平台驱动和IC驱动,平台驱动负责和HAL层联系,IC驱动负责对器件进行操作,摘取和msensor兼容相关的代码进行说明:

mag.c平台驱动文件: late_initcall的优先级为7,module_init的优先级为6,数字越小,优先级越高,所以先加载module_init,module_init对应具体的驱动。 在mag_init中执行probe,在probe中调用mag_real_driver_init,在mag_real_driver_init函数中会依次去加载msensor_init_list数组里面驱动的init函数。 afx133.c 具体驱动文件: 在__init函数中调用mag_driver_add,将具体驱动添加到msensor_init_list数组里面,__init执行完毕后,加载late_initcall模块: 在probe函数中,注册i2c驱动,调用probe。 在probe中调用afx133_Chipset_Init函数先判断该驱动是否和硬件匹配,若匹配,则操作寄存器初始化芯片。

总结

  Msensor的问题到此告一段落,文中遗留的问题后面有时间会继续跟进,有的地方可能不准确,理解不当之处欢迎指出。   准备空了去看看Android P和Android Q的sensor这部分框架有没有发生大的变化,若有新的变化,继续更进学习一下这部分。

最新回复(0)