全志公司对I2C的讲解

上传人:新** 文档编号:458134916 上传时间:2023-01-25 格式:DOCX 页数:12 大小:42KB
返回 下载 相关 举报
全志公司对I2C的讲解_第1页
第1页 / 共12页
全志公司对I2C的讲解_第2页
第2页 / 共12页
全志公司对I2C的讲解_第3页
第3页 / 共12页
全志公司对I2C的讲解_第4页
第4页 / 共12页
全志公司对I2C的讲解_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《全志公司对I2C的讲解》由会员分享,可在线阅读,更多相关《全志公司对I2C的讲解(12页珍藏版)》请在金锄头文库上搜索。

1、全志公司对I2C的讲解1. 几个基本概念 1.1. 设备模型 由 总线 + 设备 + 驱动 组成,在该模型下,所有的设备通过总线连接起来,即使有些设备没有连接到一根物理总线上,linux为其设置了一个内部的、虚拟的platform总线,用以维持总线、驱动、设备的关系。 因此,对于实现一个linux下的设备驱动,可以划分为两大步: 1、设备注册; 2、驱动注册。 当然,其中还有一些细节问题: 1、驱动的probe函数 2、驱动和设备是怎么进行绑定的。 1.2. i2c设备驱动的几个数据结构 i2c_adapter: 每一个i2c_adapter对应一个物理上的i2c控制器,在i2c总线驱动pro

2、be函数中动态创建。通过i2c_add_adapter注册到i2c_core。 i2c_algorithm: i2c_algorithm中的关键函数master_xfer,以i2c_msg为单位产生i2c访问需要的信号。不同的平台所对应的master_xfer是不同的,需要根据所用平台的硬件特性实现自己的xxx_xfer方法以填充i2c_algorithm的master_xfer指针;在A31上即是sun6i_i2c_algorithm函数。 i2c_client: 代表一个挂载到i2c总线上的i2c从设备,包含该设备所需要的数据: 该i2c从设备所依附的i2c控制器 struct i2c_a

3、dapter *adapter 该i2c从设备的驱动程序struct i2c_driver *driver 该i2c从设备的访问地址addr, name 该i2c从设备的名称name。 2. i2c总线驱动 2.1. 功能划分 从硬件功能上可划分为:i2c控制器和i2c外设。每个i2c控制器总线上都可以挂载多个i2c外设。Linux中对i2c控制器和外设分开管理:通过 i2c-sun6i.c 文件完成了i2c控制器的设备注册和驱动注册;通过i2c-core.c为具体的i2c外设提供了统一的设备注册接口和驱动注册接口,它分离了设备驱动device driver和硬件控制的实现细节。 2.2. i

4、2c-sun6i.c 该文件是与具体硬件平台相关的,对应于A3x系列芯片。该文件实际上是i2c总线驱动的实现,本质上就是向内核注册i2c总线设备、注册总线驱动、实现总线传输的时序控制算法。i2c控制器被注册为Platform设备,如下: if (twi_used_mask & TWI0_USED_MASK) platform_device_register(&sun6i_twi0_device); if (twi_used_mask & TWI1_USED_MASK) platform_device_register(&sun6i_twi1_device); if (twi_used_mask

5、 & TWI2_USED_MASK) platform_device_register(&sun6i_twi2_device); if (twi_used_mask & TWI3_USED_MASK) platform_device_register(&sun6i_twi3_device); if (twi_used_mask) return platform_driver_register(&sun6i_i2c_driver); 需要注意的是:设备与驱动的对应关系是多对一的;即如果设备类型是一样的,会共用同一套驱动,因此上面代码只是注册了一次驱动platform_driver_registe

6、r(&sun6i_i2c_driver)。 设备注册: 将i2c控制器设备注册为platform设备,为每一个控制器定义一个struct platform_device数据结构,并且把.name都设置为sun6i-i2c,然后是调用platform_device_register将设备注册到platform bus上。 设备注册完成后其直观的表现就是在文件系统下出现:/sys/bus/platform/devices/sun6i-i2c.0 通过platform_device_register进行的注册过程,说到底就是对struct platform_device这个数据结构的更改,逐步完成.

7、dev.parent、.dev.kobj、.dev.bus的赋值,然后将.dev.kobj加入到platform_bus-kobj的链表上。 驱动注册: 步骤和设备注册的步骤类似,也是为驱动定义了一个数据结构: struct platform_driver sun6i_i2c_driver; 因为一个驱动是可以对应多个设备的,而在系统里的3个控制器基本上是一致的,所以上面注册的3个设备共享的是同一套驱动。 初始化.probe和.remove函数,然后调用platform_driver_register进行驱动注册。主要函数调用流程: platform_driver_register - dri

8、ver_register - bus_add_driver - driver_attach 需要注意的是driver_attach,这个函数遍历了总线上的所有设备,寻找与驱动匹配的设备,并把满足条件的设备结构体上的驱动指针指向驱动,从而完成了驱动和设备的匹配。 如果匹配到设备,这时就需要执行platform_bus_type的probe函数,最终会调用设备驱动的probe函数。 2.2.1 sun6i_i2c_probe 在sun6i_i2c_probe函数中完成了大量的工作,包括硬件初始化、中断注册、为每个i2c控制器创建i2c_adapter等。 1268 pdata = pdev-dev

9、.platform_data; 1269 if (pdata = NULL) 1270 return -ENODEV; 1271 1272 1273 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1274 irq = platform_get_irq(pdev, 0); 1275 if (res = NULL | irq start, resource_size(res), res-name) 1280 return -ENOMEM; 1281 首先得到当前设备的私有数据指针,并将其保留在pdata;进而通过platform_get

10、_resource得到该设备占用的内存资源,并申请:request_mem_region。同时将irq资源也保留下来。 1288 1289 strlcpy(i2c-adap.name, sun6i-i2c, sizeof(i2c-adap.name); 1290 i2c-adap.owner = THIS_MODULE; 1291 i2c-adap.nr = pdata-bus_num; 1292 i2c-adap.retries = 3; 1293 i2c-adap.timeout = 5*HZ; 1294 i2c-adap.class = I2C_CLASS_HWMON | I2C_CLA

11、SS_SPD; 1295 i2c-bus_freq = pdata-frequency; 1296 i2c-irq = irq; 1297 i2c-bus_num = pdata-bus_num; 1298 i2c-status = I2C_XFER_IDLE; 1299 i2c-suspended = 0; 1300 spin_lock_init(&i2c-lock); 1301 init_waitqueue_head(&i2c-wait); 初始化i2c_adapter,并初始化一个工作队列 init_waitqueue_head。 通过ioremap申请IO资源; 通过request_i

12、rq申请irq资源,中断的处理服务函数是:sun6i_i2c_handler; sun6i_i2c_hw_init,对i2c控制进行硬件初始化; i2c-adap.algo = &sun6i_i2c_algorithm,初始化控制器的总线传输算法,设备驱动调用; 将初始化好的i2c_adapter注册到i2c_core:i2c_add_numbered_adapter。 至此,probe函数完成。 2.2.2 sun6i_i2c_core_process i2c控制器的中断服务程序sun6i_i2c_handler调用了sun6i_i2c_core_process,i2c总线的实际传输控制也是

13、在该函数里完成的。 主要流程: 1. 读取i2c控制器当前状态,twi_query_irq_status,保留在state中; 2. 根据state的值进行分支跳转,控制i2c的工作状态; 3. 传输完成,调用sun6i_i2c_xfer_complete,唤醒工作队列。 2.2.3 sun6i_i2c_xfer 每一个i2c控制器设备,在驱动绑定后,都会创建一个i2c_adapter,用以描述该控制器,i2c_adapter的建立与初始化是在驱动probe的时候建立的。每一个i2c_adapter包含了一个i2c_algorithm结构体的指针,i2c_algorithm是用来对外提供操作i

14、2c控制器的函数接口的,主要是master_xfer函数,对应于i2c-sun6i.c,实际就是: static int sun6i_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 该函数的功能是通知i2c_adapter需要对外设进行数据交换,需要交换的信息通过struct i2c_msg *msgs传入。sun6i_i2c_xfer实际上是调用了sun6i_i2c_do_xfer进行传输。 因为i2c总线读写速率有限,sun6i_i2c_do_xfer启动i2c传输后,通过wait_event_timeout进入休眠,直到中断唤醒或者超时;中断唤醒是由sun6i_i2c_xfer_complete完成的。 3. i2c设备驱动 3.1. 驱动注册 i2c从设备的驱动注册,使用的是i2c-core.c提供的接口:i2c_register_driver;其调用如下: i2c_register_driver - driver_

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号