欢迎来到天天文库
浏览记录
ID:45756726
大小:84.75 KB
页数:25页
时间:2019-11-17
《Linux驱动笔记--基础》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、【说明】:该系列笔记均是看韦东山视频教程的记录。Linux驱动学习笔记(2)当我们着于•写一个驱动的时候,并不需要从0开始,而是对以在内核源码里面找到别人成熟的类似的報动进行修改,移植。这也是一个非常高效的过程°首先,我们要明白白己的目标,要的是什么.从上到下,一个软件系统可分为:应用程序.库.操作系统(内核).驱动程序°以点灯程序为例:现在的内核都有一个VFS文件系统,会根据用户空间(应用程序)里而的役备提供的设备属件、设备号來进行填充,然后根据填充的内容注册进内核。实现流程如下:1,写出要实现的功能:led_open>led^write2,怎么告诉内核file_ope
2、ration结构体a,定义fileoperation并填充b,把这个结构告诉内核register_chrdev(...)3,谁來调用驱动入11:int_led_drv_init(void)4丿对驱动进行修饰module_init(lQd_drv_init);【驱动程序】#inelude#inelude#inelude#inelude#inelude#inelude#inelude3、>#inelude#inelude#ineludestaticstructclass*leddrv_class;staticstructclass_device*leddrv_class_dev;volatileunsignedlong*gpfcon=NULL;volatileunsignedlong*gpfdat=NULL;staticintled_drv_open(structinode*inode^structfile*file){printk(Hled_drv_open4、H);gpfcon&二~((0x3<<(4*2))5、(0x3<<(5*2))6、(0x3<<(6*2));〃清零gpfcon7、=((0xl<<(4*2))8、(0xl«(5*2))9、(0xl«(6*2));〃输出return0;}ssize_tled_drv_write(structfile*file,char_user*bufsize_tcount,loff_t*ppos){intval;copy^from^userC&val,buf,count);//copytouserif(val==1){//open_ledgpfdat&=~((1<<4)10、(1<<5)11、(1<<12、6));}else{//close_ledgpfdat13、=(1<<4)14、(1<<5)15、(1<<6);}printk(,,led_drv_write");return0;}staticstructfile_operationsled_drv_fops={•owner=THIS_MODULE,•open=led_drv_open,•write=leddrvwrite,};intmajor;intled_drv_init(void){major=register_chrdev(0,,,led_drv,&led_drv_fops);//调JIJregister_chrdev16、向内核注册设备leddrv_class=class_create(THIS_MODULE^"leddrv");if(IS_ERR(leddrv_class))returnPTR_ERR(leddrv_class);leddrv_class_dev=class_device_creat(leddrv_class,NULL,MKDEV(majorJ0),NULL>nledH);if(unlikely(IS_ERR(leddrv_class_dev)))returnPTR_ERR(leddrv_class_dev);gpfcon=(volatileunsignedlong*)i17、oremap(0x56000050^16);//将物理地址映射为虚拟地址gpfdat=gpfcon+1;//加1是以(volatileunsignedlong*)的长度为单位,即为4字节return0;}voidled_drv_exit(void){unregister_chrdev(major,nled_drv");class_device_unregister(leddrv_class_dev);class_destroy(leddrv_class);iounmap(gpfcon);//鄴放gpfcon的虚拟地址retur
3、>#inelude#inelude#ineludestaticstructclass*leddrv_class;staticstructclass_device*leddrv_class_dev;volatileunsignedlong*gpfcon=NULL;volatileunsignedlong*gpfdat=NULL;staticintled_drv_open(structinode*inode^structfile*file){printk(Hled_drv_open
4、H);gpfcon&二~((0x3<<(4*2))
5、(0x3<<(5*2))
6、(0x3<<(6*2));〃清零gpfcon
7、=((0xl<<(4*2))
8、(0xl«(5*2))
9、(0xl«(6*2));〃输出return0;}ssize_tled_drv_write(structfile*file,char_user*bufsize_tcount,loff_t*ppos){intval;copy^from^userC&val,buf,count);//copytouserif(val==1){//open_ledgpfdat&=~((1<<4)
10、(1<<5)
11、(1<<
12、6));}else{//close_ledgpfdat
13、=(1<<4)
14、(1<<5)
15、(1<<6);}printk(,,led_drv_write");return0;}staticstructfile_operationsled_drv_fops={•owner=THIS_MODULE,•open=led_drv_open,•write=leddrvwrite,};intmajor;intled_drv_init(void){major=register_chrdev(0,,,led_drv,&led_drv_fops);//调JIJregister_chrdev
16、向内核注册设备leddrv_class=class_create(THIS_MODULE^"leddrv");if(IS_ERR(leddrv_class))returnPTR_ERR(leddrv_class);leddrv_class_dev=class_device_creat(leddrv_class,NULL,MKDEV(majorJ0),NULL>nledH);if(unlikely(IS_ERR(leddrv_class_dev)))returnPTR_ERR(leddrv_class_dev);gpfcon=(volatileunsignedlong*)i
17、oremap(0x56000050^16);//将物理地址映射为虚拟地址gpfdat=gpfcon+1;//加1是以(volatileunsignedlong*)的长度为单位,即为4字节return0;}voidled_drv_exit(void){unregister_chrdev(major,nled_drv");class_device_unregister(leddrv_class_dev);class_destroy(leddrv_class);iounmap(gpfcon);//鄴放gpfcon的虚拟地址retur
此文档下载收益归作者所有