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)MakefileKERN_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
{
printf("can't open!\n");
}
if (argc != 2)
{
return 0;
}
val = atoi(argv[1]);
write(fd, &val, 4);
return 0;
}
查看执行结果: