热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

对于linux的IIC子系统,看了很多人的IIC源码及架构分析,看完了自己还是一头雾水,不知从何下手。因此只能看开机启动LOG分析各初始化

对于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.o6 obj-$(CONFIG_I2C) += i2c-core.o7 obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o8 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子系统的注册顺序分析。



推荐阅读
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • 在Linux环境下编译安装Heartbeat时,常遇到依赖库缺失的问题。为确保顺利安装,建议预先通过yum安装必要的开发库,如glib2-devel、libtool-ltdl-devel、net-snmp-devel、bzip2-devel和ncurses-devel等。这些库是编译过程中不可或缺的组件,能够有效避免编译错误,确保Heartbeat的稳定运行。 ... [详细]
  • 我正在使用 Ruby on Rails 构建个人网站。总体而言,RoR 是一个非常出色的工具,它提供了丰富的功能和灵活性,使得创建自定义页面变得既高效又便捷。通过利用其强大的框架和模块化设计,我可以轻松实现复杂的功能,同时保持代码的整洁和可维护性。此外,Rails 的社区支持也非常强大,为开发过程中遇到的问题提供了丰富的资源和解决方案。 ... [详细]
  • Understanding the Distinction Between decodeURIComponent and Its Encoding Counterpart
    本文探讨了 JavaScript 中 `decodeURIComponent` 和其编码对应函数之间的区别。通过详细分析这两个函数的功能和应用场景,帮助开发者更好地理解和使用它们,避免常见的编码和解码错误。 ... [详细]
  • 在CentOS上部署和配置FreeSWITCH
    在CentOS系统上部署和配置FreeSWITCH的过程涉及多个步骤。本文详细介绍了从源代码安装FreeSWITCH的方法,包括必要的依赖项安装、编译和配置过程。此外,还提供了常见的配置选项和故障排除技巧,帮助用户顺利完成部署并确保系统的稳定运行。 ... [详细]
  • Spring Boot 实战(一):基础的CRUD操作详解
    在《Spring Boot 实战(一)》中,详细介绍了基础的CRUD操作,涵盖创建、读取、更新和删除等核心功能,适合初学者快速掌握Spring Boot框架的应用开发技巧。 ... [详细]
  • 在Unity中进行3D建模的全面指南,详细介绍了市场上三种主要的3D建模工具:Blender 3D、Maya和3ds Max。每种工具的特点、优势及其在Unity开发中的应用将被深入探讨,帮助开发者选择最适合自己的建模软件。 ... [详细]
  • 本文详细介绍了使用响应文件在静默模式下安装和配置Oracle 11g的方法。硬件要求包括:内存至少1GB,具体可通过命令`grep -i memtotal /proc/meminfo`进行检查。此外,还提供了详细的步骤和注意事项,确保安装过程顺利进行。 ... [详细]
  • Ceph API微服务实现RBD块设备的高效创建与安全删除
    本文旨在实现Ceph块存储中RBD块设备的高效创建与安全删除功能。开发环境为CentOS 7,使用 IntelliJ IDEA 进行开发。首先介绍了 librbd 的基本概念及其在 Ceph 中的作用,随后详细描述了项目 Gradle 配置的优化过程,确保了开发环境的稳定性和兼容性。通过这一系列步骤,我们成功实现了 RBD 块设备的快速创建与安全删除,提升了系统的整体性能和可靠性。 ... [详细]
  • 深入解析Tomcat:开发者的实用指南
    深入解析Tomcat:开发者的实用指南 ... [详细]
  • Go语言实现Redis客户端与服务器的交互机制深入解析
    在前文对Godis v1.0版本的基础功能进行了详细介绍后,本文将重点探讨如何实现客户端与服务器之间的交互机制。通过具体代码实现,使客户端与服务器能够顺利通信,赋予项目实际运行的能力。本文将详细解析Go语言在实现这一过程中的关键技术和实现细节,帮助读者深入了解Redis客户端与服务器的交互原理。 ... [详细]
  • 在处理大规模并发请求时,传统的多线程或多进程模型往往无法有效解决性能瓶颈问题。尽管它们在处理小规模任务时能提升效率,但在高并发场景下,系统资源的过度消耗和上下文切换的开销会显著降低整体性能。相比之下,Python 的 `asyncio` 模块通过协程提供了一种轻量级且高效的并发解决方案。本文将深入解析 `asyncio` 模块的原理及其在实际应用中的优化技巧,帮助开发者更好地利用协程技术提升程序性能。 ... [详细]
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 如何在Android应用中设计和实现专业的启动欢迎界面(Splash Screen)
    在Android应用开发中,设计与实现一个专业的启动欢迎界面(Splash Screen)至关重要。尽管Android设计指南对使用Splash Screen的态度存在争议,但一个精心设计的启动界面不仅能提升用户体验,还能增强品牌识别度。本文将探讨如何在遵循最佳实践的同时,通过技术手段实现既美观又高效的启动欢迎界面,包括加载动画、过渡效果以及性能优化等方面。 ... [详细]
  • Linux学习精华:程序管理、终端种类与命令帮助获取方法综述 ... [详细]
author-avatar
手机用户2502887641
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有