字符设备驱动之LED-平台设备驱动(platform设备驱动)
2017-07-26 20:13
387 查看
转自http://blog.csdn.net/yicao821/article/details/6783261
怎么利用平台设备驱动机制来写驱动:
-------------------------------------------------------------------------
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); unsigned long copy_from_user(void * to, const void __user * from, unsigned long n) 第一个参数to是内核空间的数据目标地址指针, 第二个参数from是用户空间的数据源地址指针, 第三个参数n是数据的长度。 如果数据拷贝成功,则返回零;否则,返回没有拷贝成功的数据字节数。 此函数将from指针指向的用户空间地址开始的连续n个字节的数据产送到to指针指向的内核空间地址[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); platform_get_resource获取设备资源的方法是给出平台设备名 资源类型 和索引号 其中索引号实质就是为了区别相同资源类型而生的!他就是数组的下标! /*获取到资源以后再进行映射*/ 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"); |
相关文章推荐
- 字符设备驱动之LED-平台设备驱动(platform设备驱动)
- linux驱动platform平台设备总线
- linux平台总线驱动设备模型之点亮LED
- linux平台总线驱动设备模型之点亮LED
- linux平台设备驱动架构详解 Linux Platform Device and Driver——神文,非常详细
- s3c2410下 platform 总线设备和驱动 led_drv.c led_dev.c 和test
- 基于linux的虚拟平台设备驱动 led架构
- platform设备驱动之LED(cdev设备)
- Linux Platform devices 平台设备驱动
- platform平台设备驱动简化示例代码
- linux平台设备驱动架构详解 Linux Platform Device and Driver
- Linux学习:platform平台总线、平台设备、平台驱动
- platform驱动模型编程总结(基于mini2440平台的LED驱动)
- 【总结】设备树对platform平台设备驱动带来的变化
- 【总结】设备树对platform平台设备驱动带来的变化(史上最强分析)【转】
- 【平台设备驱动】中module_platform_driver的定义和使用
- platform_device(平台设备)和platform_driver(平台驱动)及平台设备驱动工作原理
- platform设备驱动之LED(misc设备)
- Linux平台设备驱动 platform_device
- platform平台设备驱动