平台总线设备驱动设计
2017-07-26 16:48
232 查看
平台总线概述
平台总线(Platform bus)是linux2.6内核加入的一种虚拟总线,其优势在于采用了总线的模型对设备与驱动进行了管理,这样提高了程序的可移植性。通过平台总线机制开发设备驱动的 流程 如图:
平台设备
平台设备使用 struct platform_device 结构 来描述:struct platform_device { const char *name; /* 设备名 */ int id; /* 设备编号,配合设备名使用 */ struct device dev; u32 num_resources; struct resource *resource; /* 设备资源 */ } struct resource { resource_size_t start; resource_size_t end; const char *name; unsigned long flags; /* 资源的类型 */ struct resource *parent, *sibling, *child; };
注册平台设备,使用函数:
int platform_device_register(struct platform_device *pdev)
平台驱动
平台驱动使用 struct platform_driver 结构体 描述:struct platform_driver { int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); //…… }
平台驱动注册使用函数:
int platform_driver_register(struct platform_driver *)
代码范例:
以按键中断驱动程序为例,平台总线驱动定义了程序的结构,混杂设备驱动定义了程序的功能。驱动程序:
#include <linux/module.h> #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/fs.h> #include <asm/uaccess.h> #include <linux/platform_device.h> //平台设备需要该头文件 MODULE_LICENSE("GPL"); struct work_struct *work; struct timer_list buttons_timer; unsigned int key_num = 0; wait_queue_head_t key_q; struct resource *res; struct resource *res_irq; unsigned int *key_base; void work_func(struct work_struct *work) { mod_timer(&buttons_timer, jiffies + (HZ /10)); } void buttons_timer_function(unsigned long data) { unsigned int key_val; key_val = readw(key_base+1)&0x1; if (key_val == 0) key_num = 4; key_val = readw(key_base+1)&0x4; if (key_val == 0) key_num = 3; wake_up(&key_q); } irqreturn_t key_int(int irq, void *dev_id) { //1. 检测是否发生了按键中断 //2. 清除已经发生的按键中断 //3. 提交下半部 schedule_work(work); //return 0; return IRQ_HANDLED; } void key_hw_init() { unsigned short data; data = readw(key_base); data &= ~0b110011; data |= 0b100010; writew(data,key_base); } int key_open(struct inode *node,struct file *filp) { return 0; } ssize_t key_read(struct file *filp, char __user *buf, size_t size, loff_t *pos) { wait_event(key_q,key_num); copy_to_user(buf, &key_num, 4); key_num = 0; return 4; } struct file_operations key_fops = { .open = key_open, .read = key_read, }; struct miscdevice key_miscdev = { .minor = 200, .name = "key", .fops = &key_fops, }; int key_probe(struct platform_device *pdev) { int ret,size; ret = misc_register(&key_miscdev); if (ret !=0) printk("register fail!\n"); //注册中断处理程序 res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); request_irq(res_irq->start,key_int,IRQF_TRIGGER_FALLING,"key",(void *)4); request_irq(res_irq->end,key_int,IRQF_TRIGGER_FALLING,"key",(void *)3); //按键初始化 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); size = (res->end - res->start) + 1; key_base = ioremap(res->start, size); key_hw_init(); /* 创建工作 */ work = kmalloc(sizeof(struct work_struct),GFP_KERNEL); INIT_WORK(work, work_func); /* 初始化定时器 */ init_timer(&buttons_timer); buttons_timer.function = buttons_timer_function; /* 向内核注册一个定时器 */ add_timer(&buttons_timer); /*初始化等待队列*/ init_waitqueue_head(&key_q); return 0; } int key_remove(struct platform_device *dev) { free_irq(res_irq->start, (void *)4); free_irq(res_irq->end, (void *)3); iounmap(key_base); misc_deregister(&key_miscdev); return 0; } static struct platform_driver key_driver = { //定义 平台设备驱动 结构体 .probe = key_probe, .remove = key_remove, .driver = { .owner = THIS_MODULE, .name = "my-key", }, }; static int button_init()//入口函数 { return platform_driver_register(&key_driver);//注册平台驱动 } static void button_exit()//出口函数 { platform_driver_unregister(&key_driver);//注销平台驱动 } module_init(button_init); module_exit(button_exit);
设备程序:
#include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/platform_device.h> //平台设备需要该头文件 MODULE_LICENSE("GPL"); #define GPFCON 0x56000050 //寄存器物理地址 static struct resource key_resource[] = { //定义平台设备的资源,注意数组的写法 [0] = { .start = GPFCON, .end = GPFCON + 8, .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_EINT0, //中断 .end = IRQ_EINT2, .flags = IORESOURCE_IRQ, }, }; struct platform_device key_device = { //定义平台设备 .name = "my-key", .id = 0, .num_resources = ARRAY_SIZE(key_resource), //平台设备资源数目 .resource = key_resource, }; static int button_init() { platform_device_register(&key_device); //平台设备注册 return 0; } static void button_exit() { platform_device_unregister(&key_device);//注销平台设备 } module_init(button_init); module_exit(button_exit);
相关文章推荐
- 13.总线设备驱动模型(2)-平台总线设备设计
- 平台总线驱动设计
- Linux内核平台总线设备驱动模型浅析
- 嵌入式linux平台设备驱动(设备驱动模型)开发之linux内核中bus总线
- 平台总线设备驱动模型——代码分析
- 基于platform总线的中断(按键)字符设备驱动设计
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- linux 设备驱动之平台总线
- 平台总线驱动设计
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- (平台)总线 设备 驱动
- linux平台总线驱动设备模型之点亮LED
- linux驱动platform平台设备总线
- 总线设备驱动模型和平台设备模型
- 平台总线设备驱动模型——基础知识
- 平台总线设备驱动详解
- 设备模型(device-model)之平台总线(bus),驱动(driver),设备(device)
- 平台总线设备驱动模型—代码分析