linux IIC子系统分析(三)——I2c子系统初始化顺序分析

对于linux的IIC子系统,看了很多人的IIC源码及架构分析,看完了自己还是一头雾水,不知从何下手。因此只能看开机启动LOG分析各初始化函数,先看linux IIC子系统已经为我们做了些什么,然后再看还需要我们做些什么。 从而了解整个IIC子系统架构。

1.linux初始化函数的执行顺序

决定函数执行顺序的有两个因素:

(一)vmlinux.lds 链接脚本

(二)驱动目录下的Makefile 文件定义

1.1 vmlinux.lds 链接脚本

该脚本位于/arch/arm/kernel/ vmlinux.lds ,该脚本规定了不同代码段,如_init, test, data等不同属性代码存放的位置。

vimlinux.lds

OUTPUT_ARCH(arm)
353 ENTRY(stext)
354 jiffies = jiffies_64;
355 SECTIONS
356 {
357  . = 0xC0000000 + 0x00008000;
358  .text.head : {
359   _stext = .;
	。。。。。。
382   __initcall_start = .;
383    *(.initcallearly.init) __early_initcall_end = .; *(.initcall0.init) *(.initcall0s.init) *(.initcall1.init    ) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initc    all4.init) *(.initcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.i    nit) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init)
384   __initcall_end = .;
	。。。。。。
402  }

看383行可以知道存放链接的顺序依次为:initcall0.init, initcall0s.init......

我们再看/include/linux/init.h中的定义:

183  * This only exists for built-in code, not for modules.
184  */
185 #define pure_initcall(fn)       __define_initcall("0",fn,0)
186 
187 #define core_initcall(fn)       __define_initcall("1",fn,1)
188 #define core_initcall_sync(fn)      __define_initcall("1s",fn,1s)
189 #define postcore_initcall(fn)       __define_initcall("2",fn,2)
190 #define postcore_initcall_sync(fn)  __define_initcall("2s",fn,2s)
191 #define arch_initcall(fn)       __define_initcall("3",fn,3)
192 #define arch_initcall_sync(fn)      __define_initcall("3s",fn,3s)
193 #define subsys_initcall(fn)     __define_initcall("4",fn,4)
194 #define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)
195 #define fs_initcall(fn)         __define_initcall("5",fn,5)
196 #define fs_initcall_sync(fn)        __define_initcall("5s",fn,5s)
197 #define rootfs_initcall(fn)     __define_initcall("rootfs",fn,rootfs)
198 #define device_initcall(fn)     __define_initcall("6",fn,6)
199 #define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
200 #define late_initcall(fn)       __define_initcall("7",fn,7)
201 #define late_initcall_sync(fn)      __define_initcall("7s",fn,7s)


从这里可以看出来,在实际驱动中,module_init(init_func) 最终展开后会将init_func做个initcall6.init的标记,最终该函数就被链接到initcall6.init的位置。在内核编译链接完成之后函数初始化的执行先后顺序就已经确定下了了。如果两个函数属性相同,比如module_init(inti_funcA); module_init(inti_funcB); 他们都属于initcall6.init,那么他们执行的先后顺序就跟Makefile文件有关了。

1.2 Makefile文件的控制

在/driver/i2c/Makefile:

  1 #                                                                                                           
  2 # Makefile for the i2c core.
  3 #
  4 
  5 obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
  6 obj-$(CONFIG_I2C)       += i2c-core.o
  7 obj-$(CONFIG_I2C_CHARDEV)   += i2c-dev.o
  8 obj-y               += busses/ chips/ algos/


在Makefile中,函数的连接顺序是按函数的存放位置先后决定的。这里可以看到是i2c-boardinf, i2c-core,i2c-dev...

2. IIC子系统初始化顺序

根据上面的分析我们可以知道在linux系统中iic子系统的初始化顺序为:

1. /driver/i2c/i2c-core.c                       postcore_initcall(i2c_init);

2. /arch/arm/mach-s3c2440                MACHINE_START(S3C2440, "SMDK2440")

3. /drivers/i2c/busses/i2c-s3c2410.c   subsys_initcall(i2c_adap_s3c_init);

4./driver/i2c/i2c-dev.c                          module_init(i2c_dev_init);

说明:

1.分析的内核版本是linux2.6.32.2

2.开发板为友善之臂的mini2440, 用的是ARM9(S3C2440A)处理器

3.链接的IIC设备是EEPROM(AT24C02)

4.按照内核I2C子系统的注册顺序分析。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

li_wen01

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

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

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

打赏作者

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

抵扣说明:

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

余额充值