linux总线设备驱动模型
本篇文章通过平台总线设备模型为例,讲解总线设备驱动模型:
platform_device_register的作用:
1.把device放入bus的device链表
2.从bus的driver链表中取出每一个driver,用bus的match函数判断driver能否支持这个device
3.若可以支持,调用driver的probe函数
platform_driver_register的作用:
1.将driver放入bus的driver链表
2.从bus的device链表中取出每一个device,用bus的match函数判断这个driver能否支持这个device
3.若可以支持,调用driver的probe函数
一、device驱动程序
1.构造并初始化平台设备资源结构体resource
struct resource led_resource[] = { [0] = { .start = 0x56000000, .end = 0x56000000 + 8 - 1, .flags = IORESOURCE_MEM, }, [1] = { .start = 5, .end = 5, .flags = IORESOUCE_IRQ, }, };
2.构造并初始化平台设备结构体platform_device
struct platform_device led_dev = { .name = "myled"; .id = -1; .num_resource = ARRAY_SIZE(led_resource); .resource = led_resource, .dev = { .release = led_release, }, }; /* release函数可以什么都不做,但是不能为空 */ static void led_release(struct device * dev) { }
3.注册平台device
platform_device_register(&led_dev);
二、driver驱动程序
1.构造并初始化平台驱动结构体platform_driver
struct platform_driver led_drv = { .probe = led_probe, .remove = led_remove, .driver = { .name = "myled", }, };
2.构造并初始化file_operations结构体
static struct file_operations led_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = led_open, .write = led_write, }; static int led_open(struct inode *inode, struct file *file) { //printk("first_drv_open\n"); /* 配置为输出 */ *gpio_con &= ~(0x3<<(pin*2)); *gpio_con |= (0x1<<(pin*2)); return 0; } static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { int val; //printk("first_drv_write\n"); copy_from_user(&val, buf, count); // copy_to_user(); if (val == 1) { // 点灯 *gpio_dat &= ~(1<<pin); } else { // 灭灯 *gpio_dat |= (1<<pin); } return 0; }
3.实现platform_driver结构的probe函数
static int led_probe(struct platform_device *pdev) { struct resource *res; *platform_get_resource *@dev:platformdevice *@type:resourcetype *@num:resourceindex res = platform_get_resource(pdev, IORESOURCE_MEM, 0); gpio_con = ioremap(res->start,res->end-res->start+1); gpio_dat = gpio_con + 1; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0) pin = res->start; major = register_chrdev(0, "myled", &led_fops); cls = class_create(THIS_MODULE, "myled"); device_create(cls, NULL, MKDEV(major,0), NULL, "led"); }
4.注册平台driver驱动程序
platform_driver_register(&led_drv);