实验八 platform驱动.docx
《实验八 platform驱动.docx》由会员分享,可在线阅读,更多相关《实验八 platform驱动.docx(13页珍藏版)》请在冰点文库上搜索。
实验八platform驱动
实验八platform驱动
实验目的
理解bus_device_dirver驱动机制
掌握platform驱动程序设计方法
实验原理
在“总线-设备-驱动”机制中,将驱动程序中的数据和代码分开,数据用structdevice表示,驱动用structdevice_driver表示。
device需要单独注册到bus中;同样device_driver也需要单独注册到bus中。
当device注册到bus中时,会跟bus中的所有device_driver进行匹配,匹配成功调用device_driver->probe方法。
当device_driver注册到bus中时,会跟bus中的所有device进行匹配,匹配成功调用device_driver->probe方法。
实验步骤
1编写my_device.c文件,向系统中注册一个platform_device;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include//包含platform驱动相关的头文件
staticstructresourcebtn_resource[]={
[0]={
.start=IRQ_EINT(26),
.end=IRQ_EINT(26),
.flags=IORESOURCE_IRQ,
.name=“key1”
},
[1]={
.start=443
.end=443
.flags=IORESOURCE_IRQ,
.name=“key2”
},
};
/*定义一个platform_dervice变量*/
}
voidxxx_fun(structdevice*dev)
{
}
staticstructplatform_devicemy_device={
.name=“abc”,
.id=-1,
.dev={
.release=xxx_fun
//void*platform_data;
}
.num_resources=ARRAY_SIZE(btn_resource),
.resource=btn_resource
};
staticint__initmy_dev_init(void)
{
/*注册platform_device*/
return0;
}
staticvoid__exitmy_dev_exit(void)
{
/*注销platform_device*/
}
module_init(my_dev_init);
module_exit(my_dev_exit);
MODULE_LICENSE("GPL");
2编写my_driver.c文件,向系统中注册一个platform_driver;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include//包含platform驱动相关的头文件
/*编写一个探索函数(probe),函数只打印一些调试信息,然后返回0*/
staticintmy_probe(structplatform_device*pdev)
{
printk(":
:
probe:
devicedrivermatchsuccess!
\n");
intirq;
inti;
for(i=0;i<4;i++){
structresource*p=platform_get_resource(pdev,IORESOURCE_IRQ,i);
request_irq(IRQ_EINT(26+i),btn_irq_handler,IRQ_TYPE_EDGE_FALLING,
btns[i].name,&btns[i]);
}
major=register_chrdev(0,"btn",&btn_fops);
btn_class=class_create(THIS_MODULE,"btn");
device_create(btn_class,NULL,MKDEV(major,0),NULL,"btn");
return0;
}
/*编写一个移除函数(remove),函数只打印一些调试信息,然后返回0*/
staticintmy_remove(structplatform_device*pdev)
{
return0;
}
/*定义一个platform_driver变量*/
structplatform_drivermy_drv={
.probe=,
.remove=,
.driver={
.owner=THIS_MODULE,
.name=,
}
};
staticintmy_drv_init(void)
{
/*注册platform_driver*/
return0;
}
staticvoidmy_drv_exit(void)
{
/*注销platform_driver*/
}
module_init(my_drv_init);
module_exit(my_drv_exit);
MODULE_LICENSE("GPL");
3分别编译上面两个文件为内核模块(就是分别编译得到两个ko文件)。
4在开发板中,先插入my_device.ko,后插入my_driver.ko,查看效果!
5在开发板中,先插入my_driver.ko,再插入my_device.ko,查看效果!
6编写符合bus_device_driver驱动机制的按键输入驱动代码,并编译,在开发板上测试效果!
7卸载模块时,出现什么错误?
如何改进这个错误?
实验完成后,可以举手叫老师过来检查,以作平时成绩加分!
My_device.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
staticstructresourcebtn_resource[]={
[0]={
.start=4,
.end=4,
.flags=IORESOURCE_IRQ,
.name="PinSum"
},
[1]={
.start=IRQ_EINT(26),
.end=IRQ_EINT(26),
.flags=IORESOURCE_IRQ,
.name="key1"
},
[2]={
.start=IRQ_EINT(27),
.end=IRQ_EINT(27),
.flags=IORESOURCE_IRQ,
.name="key2"
},
[3]={
.start=IRQ_EINT(28),
.end=IRQ_EINT(28),
.flags=IORESOURCE_IRQ,
.name="key3"
},
[4]={
.start=IRQ_EINT(29),
.end=IRQ_EINT(29),
.flags=IORESOURCE_IRQ,
.name="key4"
},
};
staticvoidxxx_fun(structdevice*dev)
{
}
staticstructplatform_devicemy_device={
.name="abc",
.id=-1,
.dev={
.release=xxx_fun,
},
.num_resources=ARRAY_SIZE(btn_resource),
.resource=btn_resource,
};
staticint__initmy_dev_init(void)
{
platform_device_register(&my_device);
return0;
}
staticvoid__exitmy_dev_exit(void)
{
platform_device_unregister(&my_device);
}
module_init(my_dev_init);
module_exit(my_dev_exit);
MODULE_LICENSE("GPL");
My_driver.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
staticstructclass*btn_class;
staticintg_iNum=0;
staticintg_iMajor;
staticinti;
staticintbtn_open(structinode*inode,structfile*file)
{
printk("openfunction\n");
return0;
}
staticstructfile_operationsbtn_fops={
.owner=THIS_MODULE,
.open=btn_open,
};
staticirqreturn_tbtn_irq_handler(intirq,void*dev)
{
structresource*p=(structresource*)dev;
printk("%s\n",p->name);
returnIRQ_HANDLED;
}
staticintmy_probe(structplatform_device*pdev)
{
structresource*tpRes;
printk(":
probe:
devicedrivermatchsuccess!
\n");
tpRes=platform_get_resource(pdev,IORESOURCE_IRQ,0);
g_iNum=tpRes->start;
for(i=1;i<=g_iNum;i++)
{
tpRes=platform_get_resource(pdev,IORESOURCE_IRQ,i);
request_irq(tpRes->start,btn_irq_handler,IRQ_TYPE_EDGE_FALLING,tpRes->name,tpRes);
}
g_iMajor=register_chrdev(0,"btn",&btn_fops);
btn_class=class_create(THIS_MODULE,"btn");
device_create(btn_class,NULL,MKDEV(g_iMajor,0),NULL,"btn");
return0;
}
staticintmy_remove(structplatform_device*pdev)
{
structresource*tpRes;
device_destroy(btn_class,MKDEV(g_iMajor,0));
class_destroy(btn_class);
unregister_chrdev(g_iMajor,"btn");
for(i=1;i<=g_iNum;i++)
{
tpRes=platform_get_resource(pdev,IORESOURCE_IRQ,i);
free_irq(tpRes->start,tpRes);
}
return0;
}
structplatform_drivermy_drv={
.probe=my_probe,
.remove=my_remove,
.driver={
.name="abc",
}
};
staticintmy_drv_init(void)
{
platform_driver_register(&my_drv);
return0;
}
staticvoidmy_drv_exit(void)
{
platform_driver_unregister(&my_drv);
}
module_init(my_drv_init);
module_exit(my_drv_exit);
MODULE_LICENSE("GPL");
Test.c(可有可无)
#include
#include
#include
#include
voidusage(char*file)
{
printf("%s/dev/
>\n",file);
}
intmain(intargc,char**argv)
{
intfd;
intval=0;
if(argc!
=2)
{
usage(argv[0]);
return0;
}
fd=open(argv[1],O_RDWR);
if(fd<0)
{
printf("openfailed!
\n");
return0;
}
printf("opensucceed!
\n");
while
(1);
close(fd);
return0;
}
Makefile
KERN_DIR=/home/sice/linux-3.5
#内核文件夹=内核文件夹的绝对路径就是pwd的值
all:
make-C$(KERN_DIR)M=`pwd`modules
#-C:
指定目录M=Makefile所在的目录也是代码的所在位置
#简单的说:
makemodules编译模块但是我们的文件不在内核目录
#这串代码就是让我们的驱动代码在指定的内核目录编译
clean:
make-C$(KERN_DIR)M=`pwd`modulesclean
rm-rfmodules.order
rm-rfModule.symvers
#清理工作通过命令makeclean清除编译出来的东西
#这里就是要编译哪个文件
obj-m+=my_device.o