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

有没有在线辅导家做的网站兰州seo整站优化服务商

有没有在线辅导家做的网站,兰州seo整站优化服务商,轻量应用服务器可以做网站吗,seo公司推广宣传复习和复现 今天重新复习了一下Linux中的面向对象/分离/分层思想,并且重新理解一下昨天学习的总线,platform_driver 和 platform_device 。 使用设备树来实现LED驱动 这里主要先来看一下有关设备树的语法部分,一个根结点下面的结点&#x…

复习和复现

今天重新复习了一下Linux中的面向对象/分离/分层思想,并且重新理解一下昨天学习的总线,platform_driver 和 platform_device 。

使用设备树来实现LED驱动 

这里主要先来看一下有关设备树的语法部分,一个根结点下面的结点,如果含有compatile属性,就会生成相应的platform_device , 如果根节点下的结点的compatile属性中含有simple-bus , "arm,amba-bus" , “simple-mfd” , "isa" , "pci"等。该结点下的子节点也会生成对应的platform_device,看看图中mytest结点的compatile属性中含有simple-bus , 那么其子节点mytest@0就会生成对应的platform_device , 反之如i2c , spi结点的子节点就不会生成对应的platform_device。

分析流程 

下面是大概的简要流程框图。

使用设备树来匹配platform_driver的一般流程设备树中 compatible = "atk,my_led"↓
of_platform_populate 创建 platform_device↓
platform_driver_register 注册驱动↓
platform_match 匹配 compatible↓
调用 myled_probe()

下面这个图是用来匹配的几个要素

1、通过 driver_override 强制匹配

如果 platform_device 中设置了 driver_override,则该字段会被用作强制绑定,只有与该字段字符串完全相同的 platform_driver.name 才会匹配成功。这种方式绕过了其他所有匹配逻辑,用于特定调试或临时需求。

/* When driver_override is set, only bind to the matching driver */if (pdev->driver_override)return !strcmp(pdev->driver_override, drv->name);

2、通过设备树中的 compatible 匹配

如果 platform_device 是由设备树生成的,并且驱动中定义了 of_match_table,内核会优先使用设备树节点中的 compatible 属性与驱动的 of_device_id 表进行匹配。这是设备树时代最常用、最可靠的匹配方式。

/* Attempt an OF style match first */if (of_driver_match_device(dev, drv))return 1;

3、通过 platform_device_id 匹配

如果设备不是通过设备树生成,而是通过手动注册的 platform_device,则系统会使用设备的 .name 字符串在驱动的 id_table 表中查找匹配项。

/* Then try to match against the id table */if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;

4、通过 device.namedriver.name 直接匹配

如果以上方式都未命中,内核会最后尝试直接比较 platform_device.nameplatform_driver.driver.name 是否一致。

(strcmp(pdev->name, drv->name) == 0)

Linux内核关于匹配的源代码如下

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);
}

编写流程 

那么我们编写这种方法的时候,就可以不用使用之前设置板子引脚资源的board_demo.c和led_resource.h两个文件。主要编写设备树文件.dts , chip_demo_gpio.c , led_template_drv.c

1、编写设备树文件.dts

找到各个板子的设备树文件,并将自己需要的设备树文件编写进去,设置compatile属性(让内核自动生成platform_device)。

#define GROUP_PIN(g , p) ((g<<16) | (p))
/ {myled@0{compatible = "my , myled";pin        = <GROUP_PIN(3 , 1)>;};myled@1{compatible = "my , myled";pin        = <GROUP_PIN(5 , 2)>;};
};

 2、编写chip_demo_gpio.c

这部分代码主要编写platform_driver结构体,并且要使用设备树在该结构体中的.driver成员中设置一个成员函数.of_match_table。这里不知道如何写这个,需要在内核其他代码中查找一下该函数的用法。模仿下面函数:

static const struct of_device_id imx_mmdc_dt_ids[] = {{ .compatible = "fsl,imx6q-mmdc", .data = (void *)&imx6q_data},{ .compatible = "fsl,imx6qp-mmdc", .data = (void *)&imx6qp_data},{ /* sentinel */ }
};static struct platform_driver imx_mmdc_driver = {.driver		= {.name	= "imx-mmdc",.of_match_table = imx_mmdc_dt_ids,},.probe		= imx_mmdc_probe,.remove		= imx_mmdc_remove,
};

改写:

static const struct of_device_id myled_match[] = {{ .compatible = "my , myled" },{},
};static struct platform_driver my_led_drv = {.probe		= my_led_drv_probe,.remove		= my_led_drv_remove,.driver		= {.name		= "my_led",.of_match_table = myled_match,},
};

3、led_template_drv.c

这部分不用需要改。按照之前的代码即可。

设备树编写LED驱动完整代码

1、chip_demo_gpio.c

#include <linux/gfp.h>
#include <linux/io.h>
#include <linux/of.h>
#include <asm/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include "led_resource.h"
#include "led_opr.h"static int g_ledpins[100];
static int g_ledcnt = 0;void led_device_create(int minor);
void led_device_destroy(int minor);
void register_led_operations(struct fed_operations *opr);static int board_demo_led_init(int which)
{printk("%s \n" , __FUNCTION__);printk("init gpio : group %d , pin %d \n" , GROUP(g_ledpins[which]) , PIN(g_ledpins[which]));switch (GROUP(g_ledpins[which])) {case 0:{printk("init pin of group 0...\n");break;}case 1:{printk("init pin of group 1...\n");break;}case 2:{printk("init pin of group 2...\n");break;}}return 0;
}static int board_demo_led_ctl(int which , char status)
{//printk("%s :%d \n" , __FUNCTION__ , status);printk("set led %s: group %d , pin %d \n"  , status ? "on" : "off" , GROUP(g_ledpins[which]) , PIN(g_ledpins[which]));//printk("set led : group %d , pin %d \n" , GROUP(led_rsc->pin) , PIN(led_rsc->pin));switch (PIN(g_ledpins[which])) {case 0:{printk("set pin of group 0...\n");break;}case 1:{printk("set pin of group 1...\n");break;}case 2:{printk("set pin of group 2...\n");break;}}return 0;
}static struct fed_operations board_demo_led_opr = {.num  = 1,.init = board_demo_led_init,.ctl  = board_demo_led_ctl,
};struct fed_operations *get_board_led_opr(void)
{return &board_demo_led_opr;
}static int my_led_drv_probe(struct platform_device *pdev)
{/* get group and pin */int err = 0;int led_pin;struct device_node * np;np = pdev->dev.of_node;if(!np)return -1;err = of_property_read_u32(np, "pin", &led_pin);g_ledpins[g_ledcnt] = led_pin;/* device_create */led_device_create(g_ledcnt);g_ledcnt++;return 0;
}static int my_led_drv_remove(struct platform_device *pdev)
{int err = 0;int led_pin;int i;struct device_node * np;np = pdev->dev.of_node;if(!np)return -1;err = of_property_read_u32(np, "pin", &led_pin);for(i = 0 ; i < g_ledcnt ; i++){if(g_ledpins[i] == led_pin){led_device_destroy(i);g_ledpins[i] = -1;break;}}for(i = 0 ; i < g_ledcnt ; i++){if(g_ledpins[i] != -1)break;}if(i == g_ledcnt)g_ledcnt = 0;return 0;
}static const struct of_device_id myled_match[] = {{ .compatible = "my , myled" },{},
};static struct platform_driver my_led_drv = {.probe		= my_led_drv_probe,.remove		= my_led_drv_remove,.driver		= {.name		= "my_led",.of_match_table = myled_match,},
};static int __init led_device_init(void)
{int err;register_led_operations(&board_demo_led_opr);err = platform_driver_register(&my_led_drv);return 0;
}static void __exit led_device_exit(void)
{platform_driver_unregister(&my_led_drv);
}module_init(led_device_init);
module_exit(led_device_exit);
MODULE_LICENSE("GPL");

2、 led_template_drv.c

#include <linux/module.h>     // 最基本模块宏
#include <linux/kernel.h>     // printk
#include <linux/init.h>       // __init/__exit
#include <linux/fs.h>         // register_chrdev 等
#include <linux/uaccess.h>    // copy_to_user, copy_from_user
#include <linux/types.h>      // dev_t, bool 等类型
#include <linux/device.h>
#include "led_opr.h"static int major = 0;static struct class *myled_class;struct fed_operations *p_led_opr;/* funciton */static ssize_t led_drv_read (struct file *file, char __user *buf , size_t size, loff_t * offset)
{printk("%s %s %d\n" , __FILE__ , __FUNCTION__ , __LINE__);printk("read from drivers:%s %s\n" , __FILE__ , __FUNCTION__ );return 0;
}
/* write(fd , &val , 1) */
static ssize_t led_drv_write (struct file *file, const char __user *buf , size_t size, loff_t * offset)
{unsigned char status;unsigned int ret;struct inode * inode = file_inode(file);int minor = iminor(inode); printk("%s %s %d\n" , __FILE__ , __FUNCTION__ , __LINE__);ret = copy_from_user(&status, buf, 1);/* minior and status  */p_led_opr->ctl(minor , status);return 1;
}static int led_drv_open (struct inode *node, struct file *file)
{int minor = iminor(node);printk("%s %s %d\n" , __FILE__ , __FUNCTION__ , __LINE__);/* init LED */p_led_opr->init(minor);return 0;
}static int led_drv_close (struct inode *node, struct file *file)
{// printk("%s %s %d\n" , __FILE__ , __FUNCTION__ , __LINE__);return 0;
}/*  create struct file_operations */
static struct file_operations myled_drv = 
{.owner          = THIS_MODULE,.open           = led_drv_open,.read           = led_drv_read,.write          = led_drv_write,.release        = led_drv_close,
};/* register_chrdev */
static int __init led_init(void)
{major = register_chrdev(0 , "led_drv", &myled_drv);/* do not need mknod */if(!myled_class){myled_class = class_create(THIS_MODULE, "led_class");if (IS_ERR(myled_class)) {printk("failed to allocate class\n");unregister_chrdev(major, "led_class");return PTR_ERR(myled_class);}}/* struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...) *///p_led_opr = get_board_led_opr();return 0;
}void led_device_create(int minor)
{device_create(myled_class , NULL , MKDEV(major, minor) , NULL , "myled%d" , minor); /* create node /dev/myled */
}
EXPORT_SYMBOL(led_device_create);void led_device_destroy(int minor)
{device_destroy(myled_class , MKDEV(major, minor));
}
EXPORT_SYMBOL(led_device_destroy);void register_led_operations(struct fed_operations *opr)
{p_led_opr = opr;
}
EXPORT_SYMBOL(register_led_operations);/* entry function */
static void __exit  led_exit(void)
{/* distroy void device_destroy(struct class *class, dev_t devt)*/printk("%s %s %d \n", __FILE__ , __FUNCTION__ , __LINE__);class_destroy(myled_class);unregister_chrdev(major, "led_drv");return;
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");//#warning "MODULE_LICENSE included in led_template_drv.c"

makefile

# 内核源码路径
KERN_DIR := /home/dd/RK3568/SDK/linux/rk3568_linux_sdk/kernel
CURRENT_PATH := $(shell pwd)# 驱动模块目标
obj-m := led_template_drv.o chip_demo_gpio.o # 源文件列表(注意 .o 后缀)
led_template_drv1-objs := led_template_drv.o chip_demo_gpio.o # 交叉编译工具链
CROSS_COMPILE ?= /home/dd/RK3568/SDK/linux/rk3568_linux_sdk/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
ARCH ?= arm64# 默认目标:编译模块 + 用户程序
build: kernel_modules ledtest# 编译内核模块
kernel_modules:$(MAKE) -C $(KERN_DIR) M=$(CURRENT_PATH) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules# 编译用户态测试程序
ledtest: ledtest.c$(CROSS_COMPILE)gcc -o ledtest ledtest.c# 清理所有编译产物
clean:$(MAKE) -C $(KERN_DIR) M=$(CURRENT_PATH) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) cleanrm -f ledtest

编写字符驱动程序的三种方法

1、资源和驱动在同一个文件

2、资源使用platform_device指定,驱动用platform_driver实现

3、资源用设备树指定。驱动在platform_driver实现

设备树编写LED驱动具体操作

找到单板的设备树文件(如rk3568操作文件中讲到其设备树文件在~/RK3568/SDK/linux/rk3568_linux_sdk/kernel/arch/arm64/boot/dts/rockchip/rk3568-atk-evb1-ddr4-v10.dtsi),保存完之后切换到SDK上层目录执行./build.sh kernel 编译一下新设备树的内核文件。

 将/kernel中的boot.img文件导入到PC端,然后将板子切换到LOADER模式,烧入新的boot.img。

重启加载之后就可以进入到/sys/firmware/devicetree/base/文件中,输入ls -ld *myled* , 可以看到加载完成之后的设备结点,使用cat命令可以看到里面的内容。 

 

进入到/sys/devices/platform/myled文件中,加载驱动程序之后,该目录底下会自动生成一个driver目录。

可以看到这个目录的类型是l,也就是软连接,进入软连接的目录就可以看到其适配的设备文件myled@0 , myled@1了。接着使用ls /dev/myled*查看挂载好的设备文件。便可以使用ledtest对驱动进行读写操作等。  

 

 

 

http://www.dtcms.com/a/517980.html

相关文章:

  • 做头像的网站横杆带字手机优化助手怎么样
  • 手机网站 自适应屏幕百度 营销推广是做什么的
  • 网站建设多少钱信息wordpress企业官网
  • 成都高度网站技术建设公司安庆什么网站做火
  • 公司网站可以自己做淘宝联盟的网站怎么做的
  • 个人业余做网站怎么弄东宁网站制作
  • 自适应企业网站模板网站托管流程
  • 个性化网站建设开发企业所得税25%怎么计算
  • 关键词工具网站如何进入wordpress
  • 建网站传播文化的好处wechat in wordpress
  • 南山网站seo免费的黄冈网站有哪些平台?
  • 咸阳兼职做网站建房城乡建设部网站
  • 网站改版 价格药品网站建设存在的问题
  • 企业网站优化徽号liu7yin出本词效果抖快均可做a7深圳公司排名前50
  • ios6软件下载网站author 1 wordpress
  • 南宁 建网站 公司莒县建设局网站
  • 南通做网站厉害的网站费用单
  • 深圳做app网站建设网站底部的备案信息修改
  • 网站关键词优化建议销售渠道有哪几种
  • 各大网站rss订阅源地址wordpress 纯代码
  • 网站怎么做第二个页面如何在百度上建免费网站
  • 人和做网站成都零起飞网站建设
  • 网站页面设计稿pano2vr输出html5教程
  • 网站制作的公司常用的搜索引擎网址
  • 做网站的公司多少钱wordpress如何访问量
  • 网站建设验收合同模板一个网站的建设流程有哪些资料
  • 做网站要求的资料网站开发生命周期
  • WHAT - 受控组件和非受控组件
  • 建设部网站规范查询包装设计效果图生成器
  • 成都公司的网站制作目前哪些企业需要做网站建设的呢