1、实验八 platform驱动实验八 platform驱动实验目的理解bus_device_dirver驱动机制掌握platform驱动程序设计方法实验原理在“总线-设备-驱动”机制中,将驱动程序中的数据和代码分开,数据用struct device表示,驱动用struct device_driver表示。device需要单独注册到bus中;同样device_driver也需要单独注册到bus中。当device注册到bus中时,会跟bus中的所有device_driver进行匹配,匹配成功调用device_driver-probe方法。当device_driver注册到bus中时,会跟bus中的所
2、有device进行匹配,匹配成功调用device_driver-probe方法。实验步骤1 编写my_device.c文件,向系统中注册一个platform_device;#include #include #include #include #include #include #include #include #include #include /包含platform驱动相关的头文件static struct resource btn_resource = 0 = .start = IRQ_EINT(26), .end = IRQ_EINT(26), .flags = IORESOURCE
3、_IRQ, .name = “key1” , 1 = .start = 443 .end = 443 .flags = IORESOURCE_IRQ, .name = “key2” ,; /*定义一个platform_dervice变量*/void xxx_fun(struct device *dev)static struct platform_device my_device= .name = “abc”, .id= -1, .dev = .release = xxx_fun/void *platform_data; .num_resources = ARRAY_SIZE(btn_reso
4、urce), .resource = btn_resource;static int _init my_dev_init(void) /*注册platform_device*/ return 0;static void _exit my_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 #in
5、clude #include #include #include #include #include #include /包含platform驱动相关的头文件/* 编写一个探索函数(probe),函数只打印一些调试信息,然后返回0 */static int my_probe(struct platform_device *pdev) printk(: probe : device driver match success !n); int irq; int i; for(i = 0;i4;i+)struct resource * p = platform_get_resource(pdev,
6、IORESOURCE_IRQ, i);request_irq(IRQ_EINT(26+i), btn_irq_handler, IRQ_TYPE_EDGE_FALLING, btnsi.name, &btnsi); major = register_chrdev(0, btn,&btn_fops); btn_class = class_create(THIS_MODULE, btn); device_create(btn_class, NULL, MKDEV(major, 0),NULL,btn); return 0;/*编写一个移除函数(remove), 函数只打印一些调试信息,然后返回0*
7、/static int my_remove(struct platform_device *pdev) return 0;/*定义一个platform_driver变量*/struct platform_driver my_drv= .probe = , .remove = , .driver = .owner = THIS_MODULE, .name = , ;static int my_drv_init(void) /*注册platform_driver*/ return 0;static void my_drv_exit(void) /*注销platform_driver*/ modul
8、e_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_dev
9、ice.c#include #include #include #include #include #include #include #include #include #include static struct resource btn_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
10、= 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 ,;static void xxx_fun(struct device *dev)static s
11、truct platform_device my_device= .name = abc, .id = -1, .dev = .release = xxx_fun, , .num_resources = ARRAY_SIZE(btn_resource), .resource = btn_resource,;static int _init my_dev_init(void) platform_device_register(&my_device); return 0;static void _exit my_dev_exit(void) platform_device_unregister(&
12、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 static struct class *btn_class;static int g_iNum = 0;static int g_iMajor;static int i;static int btn
13、_open(struct inode *inode, struct file *file) printk(open functionn); return 0;static struct file_operations btn_fops = .owner = THIS_MODULE, .open = btn_open,;static irqreturn_t btn_irq_handler(int irq, void *dev) struct resource *p = (struct resource *)dev; printk(%sn, p-name); return IRQ_HANDLED;
14、static int my_probe(struct platform_device *pdev) struct resource *tpRes; printk(: probe : device driver match success !n); tpRes = platform_get_resource(pdev, IORESOURCE_IRQ, 0); g_iNum = tpRes-start; for(i = 1; i start, btn_irq_handler, IRQ_TYPE_EDGE_FALLING, tpRes-name, tpRes); g_iMajor = registe
15、r_chrdev(0, btn,&btn_fops); btn_class = class_create(THIS_MODULE, btn); device_create(btn_class, NULL, MKDEV(g_iMajor, 0),NULL,btn); return 0;static int my_remove(struct platform_device *pdev) struct resource *tpRes; device_destroy(btn_class, MKDEV(g_iMajor, 0); class_destroy(btn_class); unregister_
16、chrdev(g_iMajor, btn); for(i = 1; i start, tpRes); return 0;struct platform_driver my_drv = .probe = my_probe, .remove = my_remove, .driver = .name = abc, ;static int my_drv_init(void) platform_driver_register(&my_drv); return 0;static void my_drv_exit(void) platform_driver_unregister(&my_drv);modul
17、e_init(my_drv_init);module_exit(my_drv_exit);MODULE_LICENSE(GPL);Test.c(可有可无)#include #include #include #include void usage(char *file) printf(%s /dev/ n,file);int main(int argc,char *argv) int fd; int val=0; if(argc!=2) usage(argv0); return 0; fd=open(argv1,O_RDWR); if(fd0) printf(open failed!n); r
18、eturn 0; printf(open succeed!n); while(1); close(fd); return 0;MakefileKERN_DIR = /home/sice/linux-3.5#内核文件夹 = 内核文件夹的绝对路径 就是pwd的值all: make -C $(KERN_DIR) M=pwd modules # -C:指定目录 M=Makefile所在的目录 也是代码的所在位置#简单的说:make modules编译模块 但是我们的文件不在内核目录#这串代码就是让我们的驱动代码在指定的内核目录编译clean: make -C $(KERN_DIR) M=pwd modules clean rm -rf modules.order rm -rf Module.symvers#清理工作 通过命令make clean 清除编译出来的东西#这里就是要编译哪个文件obj-m += my_device.o
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2