UC头条:linux应用程序控制底层硬件原理解析

#defineMYMAJOR200#defineMYNAME'testchar'#defineGPJ0CONS5PV210_GPJ0CON#defineGPJ0DATS5PV210_GPJ0DAT#definerGPJ0CON*((volatileunsignedint*)GPJ0CON)#definerGPJ0DAT*((volatileunsignedint*)GPJ0DAT)intmymajor;charkbuf[100];//内核空间的bufstaticinttest_chrdev_open(structinode*inode,structfile*file){//这个函数中真正应该放置的是打开这个设备的硬件操作代码部分//但是现在暂时我们写不了这么多,所以用一个printk打印个信息来做代表。printk(KERN_INFO'test_chrdev_open\n');rGPJ0CON=0x11111111;rGPJ0DAT=((0<<3)|(0<<4)|(0<<5));//亮return0;}staticinttest_chrdev_release(structinode*inode,structfile*file){printk(KERN_INFO'test_chrdev_release\n');rGPJ0DAT=((1<<3)|(1<<4)|(1<<5));return0;}ssize_ttest_chrdev_read(structfile*file,char__user*ubuf,size_tcount,loff_t*ppos){intret=-1;printk(KERN_INFO'test_chrdev_read\n');ret=copy_to_user(ubuf,kbuf,count);if(ret){printk(KERN_ERR'copy_to_userfail\n');return-EINVAL;}printk(KERN_INFO'copy_to_usersuccess..\n');return0;}//写函数的本质就是将应用层传递过来的数据先复制到内核中,然后将之以正确的方式写入硬件完成操作。staticssize_ttest_chrdev_write(structfile*file,constchar__user*ubuf,size_tcount,loff_t*ppos){intret=-1;printk(KERN_INFO'test_chrdev_write\n');//使用该函数将应用层传过来的ubuf中的内容拷贝到驱动空间中的一个buf中//memcpy(kbuf,ubuf);//不行,因为2个不在一个地址空间中memset(kbuf,0,sizeof(kbuf));ret=copy_from_user(kbuf,ubuf,count);if(ret){printk(KERN_ERR'copy_from_userfail\n');return-EINVAL;}printk(KERN_INFO'copy_from_usersuccess..\n');if(kbuf[0]=='1'){rGPJ0DAT=((0<<3)|(0<<4)|(0<<5));}elseif(kbuf[0]=='0'){rGPJ0DAT=((1<<3)|(1<<4)|(1<<5));}return0;}//自定义一个file_operations结构体变量,并且去填充staticconststructfile_operationstest_fops={.owner=THIS_MODULE,//惯例,直接写即可.open=test_chrdev_open,//将来应用open打开这个设备时实际调用的.release=test_chrdev_release,//就是这个.open对应的函数.write=test_chrdev_write,.read=test_chrdev_read,};//模块安装函数staticint__initchrdev_init(void){printk(KERN_INFO'chrdev_inithelloworldinit\n');mymajor=register_chrdev(0,MYNAME,&test_fops);if(mymajor<0){printk(KERN_ERR'register_chrdevfail\n');return-EINVAL;}printk(KERN_INFO'register_chrdevsuccess...mymajor=%d.\n',mymajor);return0;}//模块卸载函数staticvoid__exitchrdev_exit(void){printk(KERN_INFO'chrdev_exithelloworldexit\n');//在module_exit宏调用的函数中去注销字符设备驱动unregister_chrdev(mymajor,MYNAME);}module_init(chrdev_init);module_exit(chrdev_exit);//MODULE_xxx这种宏作用是用来添加模块描述信息MODULE_LICENSE('GPL');//描述模块的许可证MODULE_AUTHOR('aston');//描述模块的作者MODULE_DESCRIPTION('moduletest');//描述模块的介绍信息MODULE_ALIAS('aliasxxx');//描述模块的别名信息

(0)

相关推荐