fan54015 OTG/CHARGE 芯片调试时遇到的两个知识点

来源:互联网 发布:淘宝如何延迟确认收货 编辑:程序博客网 时间:2024/06/18 04:02
今天在移植fan54015驱动时遇到了一些问题,在此将其中两个比较重要的知识点记录下来:

1.    fan54015在作充电功能使用时,vbus脚作为外部充电电压的电压输入脚;而fan54015在做OTG功能使用时,vbus脚则作为外部USB设备的供电脚。所以如果OTG功能不正常,我们可以首先测量该脚是否有5.0 v电压输出。

2.    在展讯7731的代码中,Sprd_2713_power.c和Sprd_ext_ic_power.c文件里都存在着sprdbat_probe这个函数,而Sprd_2713_power.c和Sprd_ext_ic_power.c文件又是都被编译到系统当中的。在使用中我们希望使用的是Sprd_ext_ic_power.c文件中的sprdbat_probe函数,然而在实际运行中我们发现系统运行的是Sprd_2713_power.c文件中的sprdbat_probe函数,而非前者。这导致了系统的OTG功能未实现(因为没有调用到fan54015.c中的OTG ENABLE等多个函数)。
之前我已经在旧的7731代码中顺利实现了fan54015的OTG/CHARGE功能,此次只是将其移植到新的软件版本中,然而功能却出现了异常,原因何在?仔细对比代码才发现了一个很关键的不同之处:在旧的版本代码中,Sprd_2713_power.c的函数调用为late_initcall(sprd_battery_init),新版本则为module_init(sprd_battery_init)。网上百度一番,发现如下知识点:


在linux 中
init.h有如下定义

 

#define pure_initcall(fn)  __define_initcall("0",fn,1)

#define core_initcall(fn)  __define_initcall("1",fn,1)
#define core_initcall_sync(fn)  __define_initcall("1s",fn,1s)
#define postcore_initcall(fn)  __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
#define arch_initcall(fn)  __define_initcall("3",fn,3)
#define arch_initcall_sync(fn)  __define_initcall("3s",fn,3s)
#define subsys_initcall(fn)  __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
#define fs_initcall(fn)   __define_initcall("5",fn,5)
#define fs_initcall_sync(fn)  __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn)  __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn)  __define_initcall("6",fn,6)
#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
#define late_initcall(fn)  __define_initcall("7",fn,7)
#define late_initcall_sync(fn)  __define_initcall("7s",fn,7s)

#define module_init(x) __initcall(x);
#define __initcall(fn) device_initcall(fn)

所有的__init函数在区段.init.text区段中,同时还在.initcall.init中还保存了一份函数指针,在初始化时内核会通过这些函数指针调用这些__init函数指针,并在整个初始化完成后,释放整个init区段(包括.init.text,.initcall.init等)。
 
这些函数在内核初始化过程中的调用顺序只和这里的函数指针的顺序有关,而和这些函数本身在.init.text区段中的顺序无关。
在2.6内核中,initcall.init区段又分成7个子区段,不同的区段,调用的顺序不一样,数字越小的优先级越高。

也就是说 late_initcall 放在 module_init的后面调用。



在我们的代码中,旧的代码sprd_2713_power.c使用late_initcall(sprd_battery_init),使得其调用顺序在Sprd_ext_ic_power.c的module_init之后,也就是说系统会先调用到Sprd_ext_ic_power.c的sprdbat_probe的函数,将sprd_ext_chg_detected置1。然后继续执行到sprd_2713_power.c的sprd_battery_init的函数时,由于sprd_ext_chg_detected=1,程序就会返回,不再执行sprdbat_probe函数。
新的代码里sprd_2713_power.c使用module_init (sprd_battery_init)方式,恰好其调用在Sprd_ext_ic_power.c的module_init之前,使得Sprd_ext_ic_power.c的sprdbat_probe没有被运行,从而造成OTG功能无效。


0 0
原创粉丝点击