博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
平台设备驱动开发流程设计
阅读量:2432 次
发布时间:2019-05-10

本文共 4689 字,大约阅读时间需要 15 分钟。

1平台总线概述

2.平台设备
3.平台驱动
4.范例程序
1平台总线概述
1.1平台总线概述
平台总线(Platform bus)是linux2.6内核加入的一种虚拟总线,是在linxu系统中最为重要的一种总线。
linux系统中除了去支持这些实际的总线,USB总线,PCI总线,还支持虚拟总线,之前是自己创建总线并基于总线去创建驱动和设备。
linux提供了虚拟总线,平台总线(Platform bus)是linux为我们创建的虚拟总线,我们只需要去挂载驱动程序和设备。其同样具备总线的优势在于采用了总线的模型对设备与驱动进行了管理,这样提高了程序的可移植性
通过平台总线机制开发设备驱动的流程
创建和注册设备,将平台设备挂载到平台总线上
创建驱动
平台总线驱动与设备的匹配机制,前面自己创建总线,通过设备和驱动的名称匹配。platform大多数依然使用平台的设备和驱动名称相同进行匹配。
2.平台设备
平台设备使用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;
};
2.2注册平台设备
注册平台设备,使用函数:
int platform_device_register(struct platform_device *pdev)

4.范例程序

将按键程序进行改写,采用平台设备方式编写。
key_dev.c

#include
#include
#include
#define GPXCON 0x11000C20#include
#include
#define GPXCON 0x11000C20#define GPXDAT 0x11000C24MODULE_LICENSE("GPL");struct resource key_resource[]={ [0]= { .start = GPXCON, .end = GPXCON+8, .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_EINT(9), .end = IRQ_EINT(10), .flags = IORESOURCE_IRQ, },};struct platform_device key_device = { .name = "my-key", .id = 0, .num_resources = 2, .resource = key_resource,};int keydev_init(){ platform_device_register(&key_device);}void keydev_exit(){ platform_device_unregister(&key_device);}module_init(keydev_init);module_exit(keydev_exit);

insmod key_dev.ko

ls /sys/bus/platform/device
平台设备已经挂载到平台总线上
现在将平台驱动创建和注册
3.平台驱动
平台总线设备只是起到找到设备的作用,当匹配成功再按设备类型进行相应的注册。
3.1平台驱动描述
平台驱动使用struct platform_driver 描述:
struct platform_driver {
int (probe)(struct platform_device );//加载驱动,总线会将平台设备和设备驱动进行匹配,匹配成功则驱动调用probe。
int (remove)(struct platform_device );当设备移出时,驱动调用
……
}
3.2平台驱动注册
int platform_driver_register(struct platform_driver *)
下面将一个杂项设备采用平台设备的方式改写
key_drv

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");unsigned int key_num = 0;wait_queue_head_t key_queue;struct work_struct *work1;struct resource *res_irq;struct resource *res_mem;struct timer_list key_timer;unsigned int *key_base;void work1_fun(struct work_struct *work){ mod_timer(&key_timer,jiffies+(HZ/10));}void key_timer_func(unsigned long data){ unsigned int key_val; key_val = readl(key_base+1)&(0x1<<1); if(key_val==0) { key_num = 1; } key_val = readl(key_base+1)&(0x1<<2); if(key_val==0) { key_num = 2; } wake_up(&key_queue);}irqreturn_t key_int(int irq,void *dev_id){ //检测是否发生了按键中断 //清除按键中断 //提交下半部 schedule_work(work1); return 0;}void keyint(){ writel(readl(key_base)&~(0xff<<4)|(0xff<<4),key_base);}ssize_t key_read(struct file *filp, char __user *buf, size_t size, loff_t *pos){ wait_event(key_queue,key_num); printk("in kernel :key num is %d\n",key_num); copy_to_user(buf, &key_num, 4); key_num = 0; return 4;}int key_open(struct inode *node,struct file *filp){ return 0;}struct file_operations key_fops ={ .open = key_open, .read = key_read,};struct miscdevice key_miscdev = { .minor = 200, .name = "my-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 *)1); request_irq(res_irq->end,key_int,IRQF_TRIGGER_FALLING,"key",(void *)2); size =res_mem->end -res_mem->start; key_base = ioremap(res_mem->start,size);//将物理基地址转化为虚拟地址 keyint(); work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);//创建工作 INIT_WORK(work1,work1_fun);init_timer(&key_timer);//初始化定时器 key_timer.function = key_timer_func;//添加超时函数 add_timer(&key_timer);//向内核注册 init_waitqueue_head(&key_queue);//初始化等待队列 return ret;}int key_remove(struct platform_device *pdev){ free_irq(res_irq->start, 0); free_irq(res_irq->end,0); iounmap(key_base); misc_deregister(&key_miscdev); return 0;}struct platform_driver key_driver = { .probe =key_probe, .remove =key_remove, .driver = { .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);

insmod key_dev.ko

insmod key_drv.ko
mknod /dev/mykey c 10 200
./key_app
应用程序运行成功,平台总线设备模型对程序进行了优化。驱动程序可能包含几个层次,从总线方式看可以分为平台设备,从功能上看属于字符设备。USB从总线看设备上看,从功能上看有属于网络设备。直接放内核。

转载地址:http://evomb.baihongyu.com/

你可能感兴趣的文章
简化Windows 2003域控制器密码(转)
查看>>
GSM无线网络的虚拟分层(转)
查看>>
不用重装 轻松解决Windows系统棘手问题(转)
查看>>
对移动通信网络优化工作的一些见解(转)
查看>>
正确网络配置建议 减少卡机死机的关键(转)
查看>>
智能手机Smartphone开发从零起步(五)(转)
查看>>
SEO技巧中你可能没有注意的细节(转)
查看>>
微软开始二代Windows Live 不见Cloud OS踪影
查看>>
创建ISAPI扩展(转)
查看>>
病毒及木马预警一周播报(06.04.17~04.23)(转)
查看>>
黑客口述:我的第一台3389肉鸡的经历(转)
查看>>
关于 cleanup stack 和 two phase consturction [1](转)
查看>>
Oracle数据导入导出imp/exp (转)
查看>>
如何构建固定网(PSTN)短消息系统(转)
查看>>
Delphi文件管理(三)(转)
查看>>
关于网线的一些问题的解答(转)
查看>>
深度分析Win 2003自动升级补丁功能(转)
查看>>
使用Carbide.vs与VS.NET2003构建Symbian开发平台-S60 平台(转)
查看>>
来访者地址统计,很好的一个程序!(转)
查看>>
UpdateWindow函数 (转)
查看>>