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

网站改版方案建筑资源网站

网站改版方案,建筑资源网站,苏州网站建设科技,石家庄网站系统建设文章目录1 平台驱动程序2 平台设备2.1 资源和平台数据1 设备配置---废弃的旧方法资源平台数据声明平台设备2 设备配置---推荐的新方法3 设备、驱动程序和总线匹配OF风格ACPIID表匹配匹配平台设备的名字和平台驱动的名字平台设备和平台驱动程序如何匹配4 Platfrom架构驱动程序有… 文章目录1 平台驱动程序2 平台设备2.1 资源和平台数据1 设备配置---废弃的旧方法资源平台数据声明平台设备2 设备配置---推荐的新方法3 设备、驱动程序和总线匹配OF风格ACPIID表匹配匹配平台设备的名字和平台驱动的名字平台设备和平台驱动程序如何匹配4 Platfrom架构驱动程序有些物理总线已为人熟知USB、I2S、I2C、UART、SPI、PIC、SATA等。这种总线是名为控制器的硬件设备。由于它们是SoC的一部分因此无法删除不可发现也称为平台设备。 从SoC的角度来看这些设备总线内部通过专用总线连接而且大部分时间是专用的专门针对制造商。从内核的角度来看这些是根设备未连接到任何设备也就是未连接到任何总线上。这就是伪平台总线的用途伪平台总线也称为平台总线是内核虚拟总线该总线实际不存在用于连接不在内核所知物理总线上的设备和驱动程序也就是根设备和其相关的驱动程序。在下面的讨论中平台设备是指依靠伪平台总线的设备。 处理平台设备实际上需要两个步骤 注册管理设备的平台驱动程序具有唯一的名称。注册平台设备与驱动程序具有相同的名称及其资源以便内核获取设备位置。 1 平台驱动程序 在进一步介绍之前请注意以下警告并非所有平台设备都由平台驱动程序处理。平台驱动程序专用于不基于传统总线的设备。I2C设备或SPI设备是平台设备但分别依赖I2C或SPI总线而不是平台总线。对于平台驱动程序一切都需手工完成。平台驱动程序必须实现probe函数在插入模块或设备声明时内核调用它。在开发平台驱动程序时必须填写主结构struct platform_driver由它来代表平台驱动程序并用专门函数把驱动程序注册到平台总线上。 struct platform_driver定义在include/linux/platform_device.h中 struct platform_driver {int (*probe)(struct platform_device *); /* 设备和驱动匹配后调用的函数 */int (*remove)(struct platform_device *); /* 驱动程序不再为设备所需而要删除时调用的函数 */void (*shutdown)(struct platform_device *); /* 设备被关闭时调用的代码 */int (*suspend)(struct platform_device *, pm_message_t state); /* 设备被挂起执行的函数 */int (*resume)(struct platform_device *); /* 设备从挂起中恢复所执行的函数 */struct device_driver driver; /* 设备驱动 */const struct platform_device_id *id_table; /* 设备的ID表 */bool prevent_deferred_probe; };/*** struct device_driver - The basic device driver structure* name: Name of the device driver.* bus: The bus which the device of this driver belongs to.* owner: The module owner.* mod_name: Used for built-in modules.* suppress_bind_attrs: Disables bind/unbind via sysfs.* probe_type: Type of the probe (synchronous or asynchronous) to use.* of_match_table: The open firmware table.* acpi_match_table: The ACPI match table.* probe: Called to query the existence of a specific device,* whether this driver can work with it, and bind the driver* to a specific device.* remove: Called when the device is removed from the system to* unbind a device from this driver.* shutdown: Called at shut-down time to quiesce the device.* suspend: Called to put the device to sleep mode. Usually to a* low power state.* resume: Called to bring a device from sleep mode.* groups: Default attributes that get created by the driver core* automatically.* pm: Power management operations of the device which matched* this driver.* p: Driver cores private data, no one other than the driver* core can touch this.** The device driver-model tracks all of the drivers known to the system.* The main reason for this tracking is to enable the driver core to match* up drivers with new devices. Once drivers are known objects within the* system, however, a number of other things become possible. Device drivers* can export information and configuration variables that are independent* of any specific device.*/ struct device_driver {const char *name;struct bus_type *bus;struct module *owner;const char *mod_name; /* used for built-in modules */bool suppress_bind_attrs; /* disables bind/unbind via sysfs */enum probe_type probe_type;const struct of_device_id *of_match_table;const struct acpi_device_id *acpi_match_table;int (*probe) (struct device *dev);int (*remove) (struct device *dev);void (*shutdown) (struct device *dev);int (*suspend) (struct device *dev, pm_message_t state);int (*resume) (struct device *dev);const struct attribute_group **groups;const struct dev_pm_ops *pm;struct driver_private *p; };在内核中注册平台驱动程序很简单只需在init函数中调用platform_driver_register()或platform_driver_probe()。这两个函数之间的区别如下 platform_driver_register()注册驱动程序并将其放入由内核维护的驱动程序列表中内核遍历注册的平台设备表每当发现新的匹配时就可以按需调用其probe函数。为防止驱动程序在该列表中插入和注册请使用下一个函数。platform_driver_probe()调用该函数后内核立即运行匹配循环检查是否有平台设备名称匹配如果匹配则调用驱动程序的probe这意味着设备存在否则驱动程序将被忽略。此方法可防止延迟探测因为它不会在系统上注册驱动程序。 platform_driver_probe和 platform_driver_register的一点区别就是如果设备是热插拔的那么就使用 platform_driver_register函数因为platform_driver_register将驱动注册到内核上每当发现新的匹配时就可以按需调用其probe函数如果设备不是热插拔的例如dm368芯片中的USB接口这种情况下usb控制器是在片内集成的任何情况下都不会出现插拔情况这种情况下可以使用函数 platform_driver_probeplatform_driver_probe被调用后就开始匹配如果没有匹配上驱动程序将被忽略。 2 平台设备 实际上应该叫伪平台设备完成驱动程序后必须向内核提供需要该驱动程序的设备。平台设备在内核中表示为struct platform_device的实例定义在文件include/linux/platform_device.h中。如下所示 struct platform_device {const char *name; /* 用于和platform_driver进行匹配的名字 */int id; /* 设备ID */bool id_auto;struct device dev;u32 num_resources; /* resource的个数*/struct resource *resource; /* 资源数组 */const struct platform_device_id *id_entry;char *driver_override; /* Driver name to force a match *//* MFD cell pointer */struct mfd_cell *mfd_cell;/* arch specific additions */struct pdev_archdata archdata; };对于平台驱动程序在驱动程序和设备匹配之前struct platform_device的name字段要和 struct platform_driver.driver.name相同这样才能匹配上。 使用platform_device_register(struct platform_device *pdev)函数注册平台设备 2.1 资源和平台数据 在可热插拔的另一端内核不知道系统上存在那些设备、它们能够做什么或者需要什么才能运行。因为没有自主协商的过程所以提供给内核的任何信息都会收到欢迎。有两种方法可以把相关设备所需的资源和数据通知内核。 1 设备配置—废弃的旧方法 这种方法用于不支持设备树的内核版本使用这种方法驱动程序可以保持其通用性使设备注册到与开发板相关的源文件中。 资源 资源代表设备在硬件方面的所有特征元素以及设备所需的所有元素以便设置使其正常运行平台设备struct platform_device由struct source *resource描述其资源。内核中只有6种类型的资源全部列在include/linux/ioport.h中并用标志来描述资源类型 #define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */ #define IORESOURCE_MEM 0x00000200 /*内存区域 */ #define IORESOURCE_REG 0x00000300 /* Register offsets */ #define IORESOURCE_IRQ 0x00000400 /* IRQ线 */ #define IORESOURCE_DMA 0x00000800 /* DMA通道 */ #define IORESOURCE_BUS 0x00001000 /* 总线 */资源在内核中表示为struct resource的实例 struct resource {resource_size_t start;resource_size_t end;const char *name;unsigned long flags;unsigned long desc;struct resource *parent, *sibling, *child; };start/end这代表资源的开始结束位置。对于I/O或内存区域它表示开始结束位置。对于中断线、总线或DMA通道开始结束必须具有相同的值。flags这是表示资源类型的掩码例如IORESOURCE_BUSname标识或描述资源 一旦提供了资源就需要在驱动中获取使用它们。probe功能是获取它们的好地方。嵌入在struct platform_device中的struct resource可以通过platform_get_resource函数进行检索 struct resource *platform_get_resource(struct platform_device *dev,unsigned int type,unsigned int num);第一个参数是平台设备自身的实例。第二个参数说明需要什么样的资源。对于内存它应该是IORESOURCE_MEM。num是一个索引表示需要那个资源类型0表示第一个以此类推。 平台数据 所有类型不属于上一部分所列举资源的其他数据都属于这里如GPIO。无论它们是什么类型struct platform_device都包含struct device字段该字段又包含struct platform_data字段。通常应该将数据嵌入结构中将其传输到platform_data字段中。 声明平台设备 用设备的资源和数据注册设备在这个废弃的方法中它们声明在单独的模块中或者arch/arch/mach-xxx/yyy.c的开发板init文件中在函数platform_device_register()内实现声明 static struct platform_device my_device {//进行初始化 }; platform_device_register(my_device);2 设备配置—推荐的新方法 在第一种方法中任何修改都需要重构整个内核。如果内核必须包含所有应用程序/开发板特殊配置则其大小将会大大增加。为了简单起见从内核源中分离设备声明并引入一个新的概念设备树DTS)。设备树(DTS)的主要目的是从内核中删除特定且从未测试过的代码。使用设备树平台数据和资源时同质的。设备树是硬件描述文件其格式类似于树形结构每个设备用一个结点表示任何数据、资源或配置数据都表示为结点的属性。这样在做一些修改只需重新编译设备树。 3 设备、驱动程序和总线匹配 在匹配发生之前Linux会调用platform_match(struct device *dev,struct device_driver *drv) 。平台设备struct platform_device的实例通过字符name字段与驱动程序匹配(struct platform_driver.driver.name。根据Linux设备模型总线元素是最重要的部分。每个总线都维护一个注册的驱动程序和设备列表。总线驱动程序负责设备和驱动程序的匹配。每当连接新设备或者向总线添加新的驱动程序时总线都会启动匹配循环。 现在假设使用I2C核心提供的函数注册新的I2C设备。内核提供如下方法触发I2C总线匹配循环调用由I2C总线驱动程序注册的I2C核心匹配函数以检查是否有已注册的驱动程序与该设备匹配。如果没有匹配则什么都不做如果发现匹配则内核通知设备管理器(udev/mdev)由它加载与设备匹配的驱动程序。一旦设备驱动程序加载完成其probe()函数将立即执行。不仅I2C这样运行而且每个总线自己的匹配机制都大致于此相同。总线匹配循环在每个设备或驱动程序注册时被触发。 内核负责平台设备和驱动程序匹配功能的函数在/drivers/base/platform.c中定义如下 /*** platform_match - bind platform device to platform driver.* dev: device.* drv: driver.** Platform device IDs are assumed to be encoded like this:* nameinstance, where name is a short description of the type of* device, like pci or floppy, and instance is the enumerated* instance of the device, like 0 or 42. Driver IDs are simply* name. So, extract the name from the platform_device structure,* and compare it against the name of the driver. Return whether they match* or not.*/ static int platform_match(struct device *dev, struct device_driver *drv) {struct platform_device *pdev to_platform_device(dev);struct platform_driver *pdrv to_platform_driver(drv);/* When driver_override is set, only bind to the matching driver */if (pdev-driver_override)return !strcmp(pdev-driver_override, drv-name);/* Attempt an OF style match first */if (of_driver_match_device(dev, drv))return 1;/* Then try ACPI style match */if (acpi_driver_match_device(dev, drv))return 1;/* Then try to match against the id table */if (pdrv-id_table)return platform_match_id(pdrv-id_table, pdev) ! NULL;/* fall-back to driver name match */return (strcmp(pdev-name, drv-name) 0); }该函数的描述如下 平台设备 ID 假定编码如下“nameinstance”其中\ name是设备类型的简短描述如“pci”或“floppy”instance 是 设备的枚举实例如“0”或“42”。 驱动程序 ID只是“name”。 因此从 platform_device 结构中提取 name并将其与驱动程序的名称进行比较。返回它们是否匹配。 对于平台驱动程序在驱动程序和设备匹配之前struct platform_device的name字段要和 struct platform_driver.driver.name相同这样才能匹配上。 匹配顺序如下 平台设备设置 driver_override 时仅绑定到匹配的驱动程序尝试OFOpen Firmware开放固件风格匹配尝试ACPI风格匹配尝试ID表匹配匹配平台设备的名字和平台驱动的名字 OF风格 /*** of_driver_match_device - Tell if a drivers of_match_table matches a device.* drv: the device_driver structure to test* dev: the device structure to match against*/ static inline int of_driver_match_device(struct device *dev,const struct device_driver *drv) {return of_match_device(drv-of_match_table, dev) ! NULL; }of_driver_match_device判断驱动程序的 of_match_table 是否与设备匹配。 ACPI ACPI基于ACPI表不讨论 ID表匹配 ID表基于struct device_id结构。所有设备ID结构都在include/linux/mod_devicetable.h中定义。要找到正确的结构名称需要在device_id前加上设备驱动程序所在的总线名称。例如对于I2C结构名称是struct i2c_device_id而平台设备是struct platform_device_idSPI设备是spi_device_id。 if (pdrv-id_table)return platform_match_id(pdrv-id_table, pdev) ! NULL;static const struct platform_device_id *platform_match_id(const struct platform_device_id *id,struct platform_device *pdev) {while (id-name[0]) {if (strcmp(pdev-name, id-name) 0) {pdev-id_entry id;return id;}id;}return NULL; }平台驱动的id_table是 平台驱动的ID表类似是platform_device_id struct platform_device_id {char name[PLATFORM_NAME_SIZE];kernel_ulong_t driver_data; };name字段必须与注册设备时所指定的设备名称相同platform_match_id函数会找到平台驱动的ID表然后遍历ID表中的ID将每个ID的name字段与平台设备的name作比较如果相同则平台设备的id_entry 等于ID然后返回该ID如果没有ID的name字段和平台设备的name相同返回NULL。 无论如何如果ID表已经注册则每当内核运行匹配函数为止或新的平台设备查找驱动程序时都会遍历ID表。如果匹配成功则调用已匹配驱动程序的probe函数。 匹配平台设备的名字和平台驱动的名字 现在大多数平台驱动程序根本不提供任何ID表它们只在程序名称字段中填写驱动程序本身的名称。但是仍然可行因为platform_match函数在最后会回到名字匹配比较驱动程序名称和设备名称。 /* fall-back to driver name match */return (strcmp(pdev-name, drv-name) 0);平台设备和平台驱动程序如何匹配 MODULE_DEVICE_TABLE(type,name)宏让驱动程序公开其ID表该表描述它可以支持那些设备。同时如果驱动程序可以编译成模块则平台驱动实例的driver.name字段要与模块名称匹配。如果不匹配模块则不会自动加载除非已经使用MODULE_ALIAS宏为模块添加了另一个名称。编译时从所有驱动程序中提取该消息以构建设备表。当设备和驱动程序匹配时内核遍历设备表。如果找到的条目与添加的设备兼容并与设备/供应商ID或名称匹配则加载提供该匹配的模块运行模块的init函数调用probe函数。 MODULE_DEVICE_TABLE宏在linux/module.h中定义 /* Creates an alias so file2alias.c can find device table. */ #define MODULE_DEVICE_TABLE(type, name) \ extern const typeof(name) __mod_##type##__##name##_device_table \__attribute__ ((unused, alias(__stringify(name))))type这可以是i2c、spi、acpi、of、platform、usb、pci。也可以是在include/linux/mod_devicetable.h中找到的其他任何总线name这是XXX_device_id数组上的指针用于设备匹配。对于I2C设备。结构是i2c_device_id。对于设备树的Open Firmware开放固件OF匹配机制必须使用of_device_id。 4 Platfrom架构驱动程序 代码原文章https://www.toutiao.com/article/6874918991081505283/?log_fromd62ff69d6ea06_1651283905265 #include linux/module.h #include linux/moduleparam.h #include linux/cdev.h #include linux/platform_device.h #include linux/fs.h #include linux/wait.h #include linux/poll.h #include linux/slab.h#define BUFFER_MAX (10) #define OK (0) #define ERROR (-1)struct cdev *gDev; struct file_operations *gFile; dev_t devNum; unsigned int subDevNum 1; int reg_major 232; int reg_minor 0; char *buffer; #define LEDBASE 0x56000010 #define LEDLEN 0x0cint hello_open(struct inode *p, struct file *f) {printk(KERN_INFO hello_open\r\n);return 0; }ssize_t hello_write(struct file *f, const char __user *u, size_t s, loff_t *l) {printk(KERN_INFO hello_write\r\n);return 0; } ssize_t hello_read(struct file *f, char __user *u, size_t s, loff_t *l) {printk(KERN_INFO hello_read\r\n); return 0; }static int hellodev_probe(struct platform_device *pdev) {printk(KERN_INFO hellodev_probe\n);devNum MKDEV(reg_major, reg_minor);if(OK register_chrdev_region(devNum, subDevNum, helloworld)){printk(KERN_INFO register_chrdev_region ok \n); }else {printk(KERN_INFO register_chrdev_region error n);return ERROR;}printk(KERN_INFO hello driver init \n);gDev kzalloc(sizeof(struct cdev), GFP_KERNEL);gFile kzalloc(sizeof(struct file_operations), GFP_KERNEL);gFile-open hello_open;gFile-read hello_read;gFile-write hello_write;gFile-owner THIS_MODULE;cdev_init(gDev, gFile);cdev_add(gDev, devNum, 1);return 0; } static int hellodev_remove(struct platform_device *pdev) {printk(KERN_INFO hellodev_remove \n);cdev_del(gDev);kfree(gFile);kfree(gDev);unregister_chrdev_region(devNum, subDevNum);return; }static void hello_plat_release(struct device *dev) {return; } static struct resource hello_dev_resource[] {[0] {.start LEDBASE,.end LEDBASE LEDLEN - 1,.flags IORESOURCE_MEM,} };struct platform_device hello_device {.name hello-device,.id -1,.num_resources ARRAY_SIZE(hello_dev_resource),.resource hello_dev_resource,.dev {.release hello_plat_release,} }; static struct platform_driver hellodev_driver {.probe hellodev_probe,.remove hellodev_remove,.driver {.owner THIS_MODULE,.name hello-device,}, };int charDrvInit(void) {platform_device_register(hello_device);return platform_driver_register(hellodev_driver); }void __exit charDrvExit(void) {platform_device_unregister(hello_device);platform_driver_unregister(hellodev_driver);return; } module_init(charDrvInit); module_exit(charDrvExit); MODULE_LICENSE(GPL);Makefile ifneq ($(KERNELRELEASE),) obj-m : helloDev.o else PWD : $(shell pwd) #KDIR:/home/jinxin/linux-4.9.229 #KDIR: /lib/modules/4.4.0-31-generic/build KDIR : /lib/modules/uname -r/build all:make -C $(KDIR) M$(PWD) clean: rm -rf *.o *.ko *.mod.c *.symvers *.c~ *~ endif
http://www.yutouwan.com/news/385698/

相关文章:

  • 网站常用的优化方法旅游网页图片素材
  • 教育网站 怎么做吸引人字体设计网站大全
  • wordpress多个视频百度首页关键词优化
  • 商城网站方案模板东莞网站建设方案咨询
  • 岳阳网网有鱼百度关键词搜索优化
  • 应式网站网页设计与制作课程评价方案
  • 无锡网站营销公司网站开发人员上级主管
  • 个人做网站模版是否有人买做网站怎么设置背景
  • 微网站怎么搭建高端网页定制
  • 一学一做教育视频网站有哪些内容西安seo公司
  • 企业网站设计制作服务担路网做网站多少钱
  • 如何做网校网站与别人相比自己网站建设优势
  • 做谷歌网站使用什么统计代码吗怎么提升学历最快
  • 网站设计维护合同肇庆关键词网站排名
  • 沙坪坝网站建设国内外最新新闻
  • 网页制作与网站建设期末考试电商项目流程
  • 动易网站管理系统wordpress资源博客
  • 惠州app网站建设排行榜代做seo关键词排名
  • 百度站长平台网站蓝色网站导航
  • 网站培训费用wordpress搭建环境
  • 网站做什么内容西安设计工作室
  • 做产品的往这看:国外工业设计网站大全!甘肃第九建设集团公司网站
  • 亿度网络网站建设hype做网站动效
  • 策划案需要给做网站吗北京网站建设资讯
  • 网站服务器有哪些种类重庆网站有哪些
  • 三亚房地产网站制作没有公众号建微信网站
  • 做调查网站怎样换IPwordpress 中文tag标签 404
  • 莲湖区建设局网站啥网站都能看的浏览器下载
  • 福千欣隆网站建设公司 概况长沙网站优化外包服务
  • 郑州正规的网站制作价钱德阳装修公司