1、总线设备驱动模型
2、实现一个平台总线设备驱动(也称虚拟总线)
1)demo_dev
#include#include #include #include #include #include #include /* 分配/设置/注册一个platform_device */ static struct resource demo_resource[] = { [0] = { .start = 0xffffffee, .end = 0xffffffff, .flags = IORESOURCE_MEM, }, [1] = { .start = 1, .end = 1, .flags = IORESOURCE_IRQ, } }; static void demo_release(struct device * dev) { } static struct platform_device demo_dev = { .name = "mydemo", .id = -1, .num_resources = ARRAY_SIZE(demo_resource), .resource = demo_resource, .dev = { .release = demo_release, }, }; static int demo_dev_init(void) { printk("[%s %d]\n",__func__,__LINE__); platform_device_register(&demo_dev); return 0; } static void demo_dev_exit(void) { printk("[%s %d]\n",__func__,__LINE__); platform_device_unregister(&demo_dev); } module_init(demo_dev_init); module_exit(demo_dev_exit); MODULE_LICENSE("GPL");
2)demo_drv
/* 分配/设置/注册一个platform_driver */ #include#include #include #include #include #include #include static int major; static struct class *cls; static int demo_open(struct inode *inode, struct file *file) { printk("[%s %d],open!!!\n",__func__,__LINE__); return 0; } static ssize_t demo_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { int val = 0; printk("[%s %d],write!!!\n",__func__,__LINE__); copy_from_user(&val, buf, count); // 从用户空间到内核空间; printk("[%s %d],write value = %d\n",__func__,__LINE__,val); return 0; } static struct file_operations demo_fops = { .owner = THIS_MODULE, // 这是一个宏,推向编译模块时自动创建的__this_module变量 .open = demo_open, .write = demo_write, }; static int demo_probe(struct platform_device *pdev) { struct resource *res; printk("into [%s %d]\n",__func__,__LINE__); /* 获取platform_device的资源 */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//这里获取到的地址是物理地址,需要使用ioremap映射 printk("[%s %d] io res->start = %x,res->end = %x\n",__func__,__LINE__,res->start,res->end); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); printk("[%s %d] irq res->start = %d\n",__func__,__LINE__,res->start); /* 注册字符设备驱动程序 */ major = register_chrdev(0, "mydemo", &demo_fops); cls = class_create(THIS_MODULE, "mydemo"); device_create(cls, NULL, MKDEV(major, 0), NULL, "demo"); /* /dev/demo */ return 0; } static int demo_remove(struct platform_device *pdev) { /* 卸载字符设备驱动程序 */ printk("[%s %d] remove demo\n",__func__,__LINE__); device_destroy(cls, MKDEV(major, 0)); class_destroy(cls); unregister_chrdev(major, "mydemo"); return 0; } struct platform_driver demo_drv = { .probe = demo_probe, .remove = demo_remove, .driver = { .name = "mydemo", } }; static int demo_drv_init(void) { platform_driver_register(&demo_drv); return 0; } static void demo_drv_exit(void) { platform_driver_unregister(&demo_drv); } module_init(demo_drv_init); module_exit(demo_drv_exit); MODULE_LICENSE("GPL");
3)Makefile
KERN_DIR = /usr/src/linux-3.10.62 obj-m += demo_drv.o obj-m += demo_dev.o all: make -C $(KERN_DIR) M=`pwd` modules clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order
3、装载设备和驱动模块
4、查看设备并卸载模块
5、编写测试应用程序demo_test.c
#include#include #include #include int main(int argc, char **argv) { int fd; int val = 0; fd = open("/dev/demo", O_RDWR); if (fd < 0) { printf("can't open!\n"); } if (argc != 2) { return 0; } val = atoi(argv[1]); write(fd, &val, 4); return 0; }
查看执行结果: