当前位置: 首页 > news >正文

神马网站排名wordpress easy stmp

神马网站排名,wordpress easy stmp,app开发网站建设前景,服务平台的宗旨以下内容源于朱有鹏嵌入式课程的学习与整理#xff0c;如有侵权请告知删除。 一、前言 由I2C总线设备的驱动框架可知#xff0c;I2C总线设备驱动框架涉及的文件如下#xff1a; #xff08;1#xff09;I2C设备驱动层相关的文件 x210开发板的电容触摸屏gslX680采用I2C接口…以下内容源于朱有鹏嵌入式课程的学习与整理如有侵权请告知删除。 一、前言 由I2C总线设备的驱动框架可知I2C总线设备驱动框架涉及的文件如下 1I2C设备驱动层相关的文件 x210开发板的电容触摸屏gslX680采用I2C接口因此以这个I2C设备为例进行分析。 其对应的驱动源代码文件是x210_kernel\drivers\input\touchscreen\gslX680.c文件。 它由触摸屏IC原厂工程师提供代码中涉及到很多触摸屏专业方面的知识但无需理会。 gslX680.c文件进行了I2C设备驱动的注册相应的I2C设备注册是在mach-x210.c文件中。 2I2C核心层相关的文件 I2C核心层相关的文件是i2c-core.c文件它由内核开发者提供和具体的硬件操作无关。 3I2C总线驱动层相关的文件 algos目录存放的是I2C通信的算法主要是时序等内容。 busses目录存放的是各种已经编写好的、将来要向i2c核心层注册的适配器文件。 我们主要分析drivers\i2c\busses\i2c_s3c2410.c文件。 下面我们将对I2C核心层相关的文件进行分析主要分析i2c-core.c文件。 二、I2C核心层源码分析 1、I2C子系统的注册函数i2c_init() i2c子系统实现为一个模块在内核配置的时候可以进行动态的加载和卸载。 struct bus_type i2c_bus_type {.name i2c, // 总线的名字.match i2c_device_match, // 总线下设备与设备驱动的匹配函数.probe i2c_device_probe, // 总线层的probr函数.remove i2c_device_remove, // 总线卸载时执行的函数.shutdown i2c_device_shutdown,.pm i2c_device_pm_ops, // 电源管理 }; static int __init i2c_init(void) {int retval;retval bus_register(i2c_bus_type); // 注册i2c总线 /sys/bus/i2cif (retval)return retval; #ifdef CONFIG_I2C_COMPATi2c_adapter_compat_class class_compat_register(i2c-adapter);if (!i2c_adapter_compat_class) {retval -ENOMEM;goto bus_err;} #endifretval i2c_add_driver(dummy_driver); //注册一个空设备驱动/sys/bus/i2c/driver/dummyif (retval)goto class_err;return 0;class_err: #ifdef CONFIG_I2C_COMPATclass_compat_unregister(i2c_adapter_compat_class); bus_err: #endifbus_unregister(i2c_bus_type);return retval; }/* We must initialize early, because some subsystems register i2c drivers* in subsys_initcall() code, but are linked (and initialized) before i2c.*/ postcore_initcall(i2c_init); 2、略过smbus代码 因为smbus是基于I2C总线发展出来的。 3、i2c_device_match函数分析 函数内容如下 static int i2c_device_match(struct device *dev, struct device_driver *drv) { // 通过dev指针获取到对应的i2c_client指针struct i2c_client *client i2c_verify_client(dev); struct i2c_driver *driver; // 定义一个i2c_driver 指针if (!client)return 0;// 通过device_driver指针获取到对应的i2c_driver指针driver to_i2c_driver(drv); /* match on an id table if there is one */// 如果设备驱动中存在id_table表则通过这个来进行与设备的匹配// 匹配的方式就是比较 id_table指向的i2c_device_id数组中各个元素的名字if (driver-id_table) // 如果匹配成功就会返回这个 i2c_device_id 元素项地址 return i2c_match_id(driver-id_table, client) ! NULL; return 0;// 匹配失败返回 0 } 由i2c_match_id函数的分析可知在i2c总线下的设备与驱动的匹配是将设备的名字和驱动的i2c_device_id表中的各个表项的名字依次进行对比只要有一个匹配成功则表示设备和驱动匹配成功如果都没有匹配成功则表明匹配失败。 对比平台总线的匹配方法两者基本一致但是平台总线的匹配方法多了一个步骤即还会将设备的名字和驱动的名字进行匹配如果这个也没有成功才表明设备与设备驱动匹配过程失败。 4、i2c_device_probe函数分析 函数内容如下 static int i2c_device_probe(struct device *dev) { // 通过device指针获取到对应的i2c_client指针struct i2c_client *client i2c_verify_client(dev); struct i2c_driver *driver;int status;if (!client)return 0;// 通过device-driver指针获取到对应的i2c_driver指针driver to_i2c_driver(dev-driver); if (!driver-probe || !driver-id_table)return -ENODEV; // i2c设备通过i2c_client-driver指针去指向与他匹配成功的设备驱动i2c_driverclient-driver driver; if (!device_can_wakeup(client-dev))device_init_wakeup(client-dev,client-flags I2C_CLIENT_WAKE);dev_dbg(dev, probe\n); // 调用设备驱动层的probe函数status driver-probe(client, i2c_match_id(driver-id_table, client)); if (status) {client-driver NULL;i2c_set_clientdata(client, NULL);}return status; } 总结I2C总线上有2条分支即i2c_client链和i2c_driver链。当注册任何一个driver或者client时I2C总线调用match函数去对client.name和driver.id_table.name进行循环匹配。若driver.id_table中所有的id都匹配不上则说明client没有找到对应的driver如果匹配上则表明client和driver是适用的那么I2C总线会调用自身的probe函数自身的probe函数又会调用driver中提供的probe函数driver中的probe函数会对设备进行硬件初始化和后续工作。 5、核心层开放的注册接口 1i2c_add_adapter函数 / i2c_add_numbered_adapter函数 这两个函数用来向核心层注册一个适配器。两者的区别在于i2c_add_adapter函数自动分配适配器编号而i2c_add_numbered_adapter函数需要手动指定一个适配器编号。 分析可知这两个函数都调用了i2c_register_adapter函数而i2c_register_adapter函数是I2C子系统核心层提供给I2C总线驱动层的、用来向核心层注册一个适配器的接口函数。 1i2c_register_adapter函数及分析 // 向i2c总线注册适配器adapter static int i2c_register_adapter(struct i2c_adapter *adap) {int res 0, dummy;/* Cant register until after driver model init */if (unlikely(WARN_ON(!i2c_bus_type.p))) {res -EAGAIN;goto out_list;}rt_mutex_init(adap-bus_lock);// 初始化i2c_adapter-userspace_clients链表INIT_LIST_HEAD(adap-userspace_clients); /* Set default timeout to 1 second if not already set */if (adap-timeout 0)adap-timeout HZ;// 设置适配器设备的名字 i2c-%d(nr)dev_set_name(adap-dev, i2c-%d, adap-nr); adap-dev.bus i2c_bus_type; // 设置设备的总线类型adap-dev.type i2c_adapter_type; // 设置设备的设备类型 // 注册设备,如果前面没有指定父设备那么创建的设备文件是: /sys/devices/i2c-%dres device_register(adap-dev); if (res) // samsung在注册适配器的时候是指定了父设备的所以他创建的设备是: // /sys/devices/platform/s3c2410-i2cn/i2c-%dgoto out_list; // 为什么是这个会在后面说到dev_dbg(adap-dev, adapter [%s] registered\n, adap-name);#ifdef CONFIG_I2C_COMPATres class_compat_create_link(i2c_adapter_compat_class, adap-dev,adap-dev.parent);if (res)dev_warn(adap-dev,Failed to create compatibility class link\n); #endif/* create pre-declared device nodes */if (adap-nr __i2c_first_dynamic_bus_num) // 扫描__i2c_board_list链表上挂接的所有的i2c次设备信息并与适配器进行匹配 // 匹配成功创建i2c次设备i2c_scan_static_board_info(adap); /* Notify drivers */mutex_lock(core_lock);dummy bus_for_each_drv(i2c_bus_type, NULL, adap,__process_new_adapter);mutex_unlock(core_lock);return 0;out_list:mutex_lock(core_lock);idr_remove(i2c_adapter_idr, adap-nr);mutex_unlock(core_lock);return res; } 2i2c_scan_static_board_info函数及分析 static void i2c_scan_static_board_info(struct i2c_adapter *adapter) {struct i2c_devinfo *devinfo; // 定义一个i2c_devinfo 结构体指针down_read(__i2c_board_lock); // 遍历 __i2c_board_list 链表上的所有i2c_devinfo 结构体 // 比较 i2c_devinfo-busnum 与 适配器的编号是否匹配 // 如果匹配就会调用 i2c_new_device 函数进行注册添加新的次设备 i2c_clientlist_for_each_entry(devinfo, __i2c_board_list, list) { if (devinfo-busnum adapter-nr !i2c_new_device(adapter, devinfo-board_info))dev_err(adapter-dev,Cant create device at 0x%02x\n,devinfo-board_info.addr);}up_read(__i2c_board_lock); } 3i2c_new_device函数及分析 struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) {struct i2c_client *client; // 定义一个 i2c_client 指针int status;client kzalloc(sizeof *client, GFP_KERNEL); // 申请分配if (!client)return NULL;// 对i2c_client结构体变量进行填充client-adapter adap; // i2c次设备通过i2c_client-adapter指针去指向与它匹配成功的适配器i2c_adapterclient-dev.platform_data info-platform_data; // 将传进来的i2c_board_info结构体作为i2c次设备的platform平台数据if (info-archdata)client-dev.archdata *info-archdata;client-flags info-flags; // 标志位client-addr info-addr; // i2c次设备的地址client-irq info-irq; // 中断号strlcpy(client-name, info-type, sizeof(client-name)); // 名字/* Check for address validity */status i2c_check_client_addr_validity(client); // 次设备地址校验if (status) {dev_err(adap-dev, Invalid %d-bit I2C address 0x%02hx\n,client-flags I2C_CLIENT_TEN ? 10 : 7, client-addr);goto out_err_silent;}/* Check for address business */status i2c_check_addr_busy(adap, client-addr);if (status)goto out_err;client-dev.parent client-adapter-dev; // 指定i2c 次设备的父设备是与它匹配成功的适配器对应的设备client-dev.bus i2c_bus_type; // 指定次设备的总线类型client-dev.type i2c_client_type; // 指定次设备的设备类型 #ifdef CONFIG_OFclient-dev.of_node info-of_node; #endifdev_set_name(client-dev, %d-%04x, i2c_adapter_id(adap), // 设置次设备的名字 %d-%04xclient-addr);status device_register(client-dev); // 注册次设备: /sys/devices/platform/s3c2410-i2cn/i2c-%d/%d-%04xif (status)goto out_err;dev_dbg(adap-dev, client [%s] registered with bus id %s\n,client-name, dev_name(client-dev));return client;out_err:dev_err(adap-dev, Failed to register i2c client %s at 0x%02x (%d)\n, client-name, client-addr, status); out_err_silent:kfree(client);return NULL; } i2c_new_device函数是I2C核心层提供给设备驱动层的、用来注册i2c设备的接口函数我们可以在直接调用这个函数来注册I2C设备。 在这里I2C核心层还提供了另外一种机制来实现自动注册。其原理是在系统启动时在硬件初始化函数中例如 smdkc110_machine_init 函数里注册板子的I2C从设备实际上就是构建i2c_devinfo结构体变量挂接到__i2c_board_list链表上当我们向I2C总线核心层注册适配器时就会去扫描该链表然后根据相关的信息去注册I2C从设备。这也就是上面那个函数的意义。   smdkc110_machine_init { //省略部分代码platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices)); /* 这个是设置的是SoC中的i2c控制器(适配器)作为平台设备的私有数据 */s3c_i2c1_set_platdata(NULL); // 通过这个函数注册板子上的i2c次设备的信息i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs0)); //省略部分代码 } 2i2c_add_driver函数分析 在i2c_add_driver函数的内部调用了I2C核心层的i2c_register_driver函数来注册一个I2C总线下的设备驱动。i2c_register_driver函数内容如下 int i2c_register_driver(struct module *owner, struct i2c_driver *driver) {int res;/* Cant register until after driver model init */if (unlikely(WARN_ON(!i2c_bus_type.p)))return -EAGAIN;/* add the driver to the list of i2c drivers in the driver core */driver-driver.owner owner;driver-driver.bus i2c_bus_type; // 指定该设备驱动的总线类型 i2c/* When registration returns, the driver core* will have called probe() for all matching-but-unbound devices.*/res driver_register(driver-driver); // 注册设备驱动 /sys/bus/i2c/drivers/dummy dummy就是一个设备驱动文件if (res)return res;pr_debug(i2c-core: driver [%s] registered\n, driver-driver.name);INIT_LIST_HEAD(driver-clients); // 初始化i2c_driver - clients 链表/* Walk the adapters that are already present */mutex_lock(core_lock);bus_for_each_dev(i2c_bus_type, NULL, driver, __process_new_driver); // 可以忽略这条语句的执行效果mutex_unlock(core_lock);return 0; } 6、总结 从上面的分析可知i2c子系统内部存在着2个匹配过程 1i2c总线下的设备与设备驱动之间的匹配通过设备驱动的id_table。 2适配器与设备之间的匹配通过适配器编号。
http://www.zqtcl.cn/news/308890/

相关文章:

  • 如何建设一个新的网站h5网站建设价格
  • 无锡专业做网站的怎么攻击php做的网站
  • 盐城网站建设代理商wordpress定义字体颜色
  • 成都旅游网站建设地址自己做的网站怎么被搜索出来
  • 网站建设免费免代码商城微网站如何做
  • 网站建设域名是什么东莞网络科技营销
  • 法语网站建设高端网站建设 骆
  • vue网站开发注意事项做设计想接外单去哪个网站好
  • 免费模板下载网站推荐苏州seo
  • 徐州市水利工程建设有限公司网站网站建设技术团队有多重要性
  • 合肥佰瑞网站搜索引擎优化步骤
  • 营销型网站建设亏1广西桂林天气预报15天
  • 想做一个网站平台怎么做公司网站建设费用估计
  • 电商网站开发平台pi netwo网页设计文件下载
  • 南平网站设计笔记本怎么建设网站
  • 舆情分析网站免费人工智能培训班收费标准
  • 青岛网站建设 大公司制作相册视频
  • 什么是网站的域名jquery素材网站
  • 课程网站建设ppt模板百度seo推广
  • 网站建设需要用到什么怎么在电脑上用手机app软件
  • 公司做网站有意义么网站认证必须做么
  • 网站虚拟空间更新缓存php外贸网站建设
  • 河南省建设执业资格注册中心网站门户定制网站建设公司
  • 网站开发比较厉害wordpress中文 插件
  • 文化投资的微网站怎么做个人微信公众号如何推广
  • 单位的网站怎样设计才美观网页设计图片的代码
  • 长沙专业做网站排名济南手机网站定制费用
  • 西安专题门户响应式网站建设系统网站有哪些
  • 山东省建设局网站监理员考试asp.net mvc6电商网站开发实践
  • 做网站需要提供什么资料网站备案是什么意思