字符设备注册platform平台驱动机制
2016-04-14 23:13
411 查看
怎么利用平台设备驱动机制来写驱动:
-------------------------------------------------------------------------
1.先实现设备方向的:
1)看芯片手册,和原理图获取资源
2)构建平台设备结构体,将平台资源加入进来
3)把我们的设备资源挂在到虚拟总线的设备连表中去
2. 再实现设备驱动:
1)构建平台驱动结构体,不知道的时候可以看别人的
2)注册,把我们的驱动加入到平台设备驱动连表中去
3)实现probe函数
4)实现操作硬件的方法
5)注册字符设备驱动
led_dev.c
led_drv.c
-------------------------------------------------------------------------
1.先实现设备方向的:
1)看芯片手册,和原理图获取资源
2)构建平台设备结构体,将平台资源加入进来
3)把我们的设备资源挂在到虚拟总线的设备连表中去
2. 再实现设备驱动:
1)构建平台驱动结构体,不知道的时候可以看别人的
2)注册,把我们的驱动加入到平台设备驱动连表中去
3)实现probe函数
4)实现操作硬件的方法
5)注册字符设备驱动
led_dev.c
#include <linux/fs.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/ioport.h> #include <linux/pci.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/irq.h> #include <linux/interrupt.h> #include <asm/mach/irq.h> #include <asm/arch/regs-gpio.h> #include <linux/poll.h> #include <linux/platform_device.h> /* 参考arch/arm/plat-s3c24xx/devs.c */ /*1. 根据芯片手册来获取资源*/ static struct resource led_resource[] = { [0] = { .start = 0x56000050, .end = 0x56000057, .flags = IORESOURCE_MEM, }, [1] = { .start = 5, .end = 5, .flags = IORESOURCE_IRQ, }, }; void led_release(struct device *dev) { } /*1.构建平台设备结构体,将平台资源加入进来*/ struct platform_device led_device = { .name = "myled", /* 使用名为"myled"的平台驱动 */ .id = -1, .dev = { .release = led_release, }, .num_resources = ARRAY_SIZE(led_resource), .resource = led_resource, }; /*2。把我们的设备资源挂在到虚拟总线的设备连表中去*/ int led_dev_init(void) { platform_device_register(&led_device); return 0; } void led_dev_exit(void) { platform_device_unregister(&led_device); } module_init(led_dev_init); module_exit(led_dev_exit); MODULE_LICENSE("GPL"); |
#include <linux/fs.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/ioport.h> #include <linux/pci.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/irq.h> #include <linux/interrupt.h> #include <asm/mach/irq.h> #include <asm/arch/regs-gpio.h> #include <linux/poll.h> #include <linux/platform_device.h> static int major = 0; static volatile unsigned long *gpio_con; static volatile unsigned long *gpio_dat; static int pin; static struct class *cls; int led_open(struct inode *inode, struct file *file) { /* 设置对应的引脚为输出引脚 */ *gpio_con &= ~(0x3 << (pin * 2)); *gpio_con |= (0x1 << (pin * 2)); return 0; } ssize_t led_write(struct file *file, const char __user *buf, size_t size, loff_t *offset) { char ker_buf[1]; /* 根据buf传入的值点/灭灯 */ /* buf[0] - 亮/灭 , 0 - 亮, 1 - 灭 */ if (size != 1) { return -EINVAL; } copy_from_user(ker_buf, buf, 1); if ((ker_buf[0] != 0) && (ker_buf[0] != 1)) return -EINVAL; if (ker_buf[0]) { // 某个LED *gpio_dat |= (0x1<< pin); } else { // 某个LED *gpio_dat &= ~(0x1<<pin); } return 1; } /*4实现操作硬件的方法*/ static struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .write = led_write, }; /*3。实现probe函数*/ static int led_probe(struct platform_device *dev) { struct resource *r; /* 根据平台设备确定点哪一个LED */ r = platform_get_resource(dev, IORESOURCE_MEM, 0); /*获取到资源以后再进行映射*/ gpio_con = ioremap(r->start, r->end - r->start + 1); gpio_dat = gpio_con + 1; r = platform_get_resource(dev, IORESOURCE_IRQ, 0); pin = r->start; /* 注册驱动向内核里面注册我们的字符设备驱动 */ major = register_chrdev(0, "led", &led_fops); /* sysfs ==> 挂接到/sys */ cls = class_create(THIS_MODULE, "led_class"); class_device_create(cls, NULL, MKDEV(major, 0), NULL, "led"); // mdev会根据/sys下的这些内容创建/dev/led return 0; } int led_remove(struct platform_device *dev) { unregister_chrdev(major, "led"); class_device_destroy(cls, MKDEV(major, 0)); class_destroy(cls); iounmap(gpio_con); return 0; } /*1。构建平台驱动结构体,不知道的时候可以看别人的*/ static struct platform_driver led_driver = { .probe = led_probe, /* 平台总线下增加一个平台设备时,调用枚举函数 */ .remove = led_remove, /* 平台总线下去掉一个平台设备时,调用remove函数 */ .driver = { .name = "myled", /* 能支持名为"myled"的平台设备 */ .owner = THIS_MODULE, }, }; /*2。注册,把我们的驱动加入到平台设备驱动连表中去*/ static int led_drv_init(void) { platform_driver_register(&led_driver); return 0; } static int led_drv_exit(void) { platform_driver_unregister(&led_driver); return 0; } module_init(led_drv_init); module_exit(led_drv_exit); MODULE_LICENSE("GPL"); |
相关文章推荐
- 正式开启Android之旅
- Java之路之Helloworld
- JAVA - 如何通过RGB值判断颜色深浅 , 并输出默认头像
- 编程之美 - 寻找合适的数字
- 利用nginx搭建http和rtmp协议的流媒体服务器
- javaWeb之文件上传
- andorid SQLite数据库的增删改查 和事务操作
- 20145206《Java程序设计》实验二Java面向对象程序设计实验报告
- Hadoop1.2.1伪分布模式安装教程
- javascript 理解闭包
- #define (关键字) 宏替换笔记
- 维数灾难
- c++容器和适配器
- CSU 1559 外卖的撕‘哔’大战
- 启动、关闭tomcat脚本
- 分布式文件系统元数据服务模型[转]
- ubuntu系统下更新后wfi图标不显示
- 新博客地址
- attachEvent和addEventListener详解
- C++实现链表常见面试题