总线设备驱动模型
来源:互联网 发布:java外部类访问内部类 编辑:程序博客网 时间:2024/05/16 12:37
总线描述结构
在 Linux 内核中, 总线由 bus_type 结构表示,
定义在 <linux/device.h>
struct bus_type {
const char *name; /*总线名称*/
int (*match) (struct device *dev, struct
device_driver *drv); /*驱动与设备的匹配函数*/
………
}
int (*match)(struct device * dev, struct device_driver * drv)
当一个新设备或者新驱动被添加到这个总线
时,该函数被调用。用于判断指定的驱动程
序是否能处理指定的设备。若可以,则返回
非零
总线的注册使用如下函数
bus_register(struct bus_type *bus)
若成功,新的总线将被添加进系统,并可在
/sys/bus 下看到相应的目录。
总线的注销使用:
void bus_unregister(struct bus_type *bus)
驱动描述结构
在 Linux内核中, 驱动由 device_driver结构表示。
struct device_driver {
const char *name; /*驱动名称*/
struct bus_type *bus; /*驱动程序所在的总线*/
int (*probe) (struct device *dev);
………
}
驱动注册与注销
驱动的注册使用如下函数
int driver_register(struct device_driver *drv)
驱动的注销使用:
void driver_unregister(struct device_driver *drv)
设备描述结构
在 Linux内核中, 设备由struct device结构表示。
struct device {
{
const char *init_name; /*设备的名字*/
struct bus_type *bus; /*设备所在的总线*/
………
}
设备驱动注册与注销
设备的注册使用如下函数
int device_register(struct device *dev)
设备的注销使用:
void device_unregister(struct device *dev)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
MODULE_LICENSE("GPL");
int my_match(struct device *dev, struct device_driver *drv)
{
return !strncmp(dev->kobj.name,drv->name,strlen(drv->name));
}
struct bus_type my_bus_type = {
.name = "my_bus",
.match = my_match,
};
EXPORT_SYMBOL(my_bus_type);
int my_bus_init()
{
int ret;
ret = bus_register(&my_bus_type);
return ret;
}
void my_bus_exit()
{
bus_unregister(&my_bus_type);
}
module_init(my_bus_init);
module_exit(my_bus_exit);
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
extern struct bus_type my_bus_type;
int my_probe(struct device *dev)
{
printk("driver found the device it can handle!\n");
return 0;
}
struct device_driver my_driver = {
.name = "my_dev",
.bus = &my_bus_type,
.probe = my_probe,
};
int my_driver_init()
{
int ret;
ret = driver_register(&my_driver);
return ret;
}
void my_driver_exit()
{
driver_unregister(&my_driver);
}
module_init(my_driver_init);
module_exit(my_driver_exit);
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
extern struct bus_type my_bus_type;
struct device my_dev = {
.init_name = "my_dev",
.bus = &my_bus_type,
};
int my_device_init()
{
int ret;
ret = device_register(&my_dev);
return ret;
}
void my_device_exit()
{
device_unregister(&my_dev);
}
module_init(my_device_init);
module_exit(my_device_exit);
============================
平台设备驱动
平台总线概述
平台总线(Platform bus)是linux2.6内核
加入的一种虚拟总线,其优势在于采用了
总线的模型对设备与驱动进行了管理,这
样提高了程序的可移植性。
平台总线驱动与设备匹配机制
struct bus_type platform_bus_type = {
947 .name = "platform",
948 .dev_attrs= platform_dev_attrs,
949 .match = platform_match,
950 .uevent = platform_uevent,
951 .pm = &platform_dev_pm_ops,
952};
平台设备使用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 *);
……
}
//key_dev.c
#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);
//key_drv.c
#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);
在 Linux 内核中, 总线由 bus_type 结构表示,
定义在 <linux/device.h>
struct bus_type {
const char *name; /*总线名称*/
int (*match) (struct device *dev, struct
device_driver *drv); /*驱动与设备的匹配函数*/
………
}
int (*match)(struct device * dev, struct device_driver * drv)
当一个新设备或者新驱动被添加到这个总线
时,该函数被调用。用于判断指定的驱动程
序是否能处理指定的设备。若可以,则返回
非零
总线的注册使用如下函数
bus_register(struct bus_type *bus)
若成功,新的总线将被添加进系统,并可在
/sys/bus 下看到相应的目录。
总线的注销使用:
void bus_unregister(struct bus_type *bus)
驱动描述结构
在 Linux内核中, 驱动由 device_driver结构表示。
struct device_driver {
const char *name; /*驱动名称*/
struct bus_type *bus; /*驱动程序所在的总线*/
int (*probe) (struct device *dev);
………
}
驱动注册与注销
驱动的注册使用如下函数
int driver_register(struct device_driver *drv)
驱动的注销使用:
void driver_unregister(struct device_driver *drv)
设备描述结构
在 Linux内核中, 设备由struct device结构表示。
struct device {
{
const char *init_name; /*设备的名字*/
struct bus_type *bus; /*设备所在的总线*/
………
}
设备驱动注册与注销
设备的注册使用如下函数
int device_register(struct device *dev)
设备的注销使用:
void device_unregister(struct device *dev)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
MODULE_LICENSE("GPL");
int my_match(struct device *dev, struct device_driver *drv)
{
return !strncmp(dev->kobj.name,drv->name,strlen(drv->name));
}
struct bus_type my_bus_type = {
.name = "my_bus",
.match = my_match,
};
EXPORT_SYMBOL(my_bus_type);
int my_bus_init()
{
int ret;
ret = bus_register(&my_bus_type);
return ret;
}
void my_bus_exit()
{
bus_unregister(&my_bus_type);
}
module_init(my_bus_init);
module_exit(my_bus_exit);
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
extern struct bus_type my_bus_type;
int my_probe(struct device *dev)
{
printk("driver found the device it can handle!\n");
return 0;
}
struct device_driver my_driver = {
.name = "my_dev",
.bus = &my_bus_type,
.probe = my_probe,
};
int my_driver_init()
{
int ret;
ret = driver_register(&my_driver);
return ret;
}
void my_driver_exit()
{
driver_unregister(&my_driver);
}
module_init(my_driver_init);
module_exit(my_driver_exit);
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
extern struct bus_type my_bus_type;
struct device my_dev = {
.init_name = "my_dev",
.bus = &my_bus_type,
};
int my_device_init()
{
int ret;
ret = device_register(&my_dev);
return ret;
}
void my_device_exit()
{
device_unregister(&my_dev);
}
module_init(my_device_init);
module_exit(my_device_exit);
============================
平台设备驱动
平台总线概述
平台总线(Platform bus)是linux2.6内核
加入的一种虚拟总线,其优势在于采用了
总线的模型对设备与驱动进行了管理,这
样提高了程序的可移植性。
平台总线驱动与设备匹配机制
struct bus_type platform_bus_type = {
947 .name = "platform",
948 .dev_attrs= platform_dev_attrs,
949 .match = platform_match,
950 .uevent = platform_uevent,
951 .pm = &platform_dev_pm_ops,
952};
平台设备使用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 *);
……
}
//key_dev.c
#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);
//key_drv.c
#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);
阅读全文
0 0
- 总线设备驱动模型
- 总线/设备/驱动模型
- 总线-设备-驱动模型
- 总线设备驱动模型
- 总线设备驱动模型
- 总线设备驱动模型
- 总线设备驱动模型
- 总线设备驱动模型
- 总线设备驱动模型
- 总线设备驱动模型
- 总线、设备、驱动模型
- 总线设备驱动模型
- 设备驱动模型-总线
- 总线设备驱动模型
- 设备模型:总线、驱动、设备
- 13.总线设备驱动模型(1)-总线设备驱动模型
- 总线设备驱动模型总结
- 总线设备模型-LED驱动
- 利用面向对象做简略的图书管理系统
- Bundler 及 PMVS 常见问题&解决方法--相机内参
- JVM加载class文件的原理机制
- 结构型模式--适配器模式
- ospf原理
- 总线设备驱动模型
- 排序
- 直接插入排序
- sublime text3安装和支持中文fcitx输入
- 键盘获取3个整型数据
- 余弦的两种表示方法:边长和向量
- Cause: java.lang.ClassCastException: com.github.pagehelper.PageHelper cannot be cast to org.apache.i
- POJ 1716 Integer Intervals(差分约束)
- 关于判断输入字符的单词个数的非数组做法