版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
北京邮电大学嵌入式系统开发实验报告学院:班级:姓名:学号:序号:目录一、 实验目的 1二、 实验设备 1三、 根底实验〔实验一~实验七〕 11. 实验五 12. 实验六 13. 实验七 1四、 驱动程序 51. 设备驱动程序的概念 52. 驱动程序结构 63. 设备注册和初始化 74. 设备驱动程序的开发过程 8五、 根本接口实验 81. 实验十二简单设备驱动程序 92. 实验十三CPUGPIO驱动程序设计 93. 实验十四中断实验 104. 实验十五数码管显示实验 125. 实验十六LED点阵驱动程序设计 196. 实验十七AD驱动实验 237. 实验十八DA驱动实验 26六、 实验中遇到的问题及解决方法 30七、 实验总结及心得 31实验目的通过实验熟悉Linux环境,并掌握一些根本接口驱动的写法和用C语言编写简单的实验程序。学习LINUX开发环境的搭建,通讯配置等。并熟练掌握LINUX驱动程序的编写及开发流程。对嵌入式系统有进一步的了解。实验设备1.一套PXA270EP嵌入式实验箱2.安装Redhat9的宿主PC机,并且配置好ARMLinux的开发环境根底实验〔实验一~实验七〕实验一~七为根底实验,目的是为后续实验搭建好软、硬件环境,配置好相关的协议、效劳,并通过编写最简单的HelloWorld程序进行测试。由于后面的实验都要依靠前面实验的配置,故本段只着重表达实验七的具体实现。实验五实验五为宿主PC机配置了TFTP效劳。TFTP(TrivialFileTransferProtocol)是简单文件传输协议,由于特定开发环境的制约,这一效劳是必须的。在配置完成后,每次重启宿主PC机时,都须先输入命令:servicexinetdrestart,以启动TFTP效劳。实验六实验六为宿主PC机配置了NFS效劳。NFS(NetworkFileSystem)指网络文件系统,它实现了文件在不同的系统间使用。当我们想用远端档案时,只需调用“mount〞就可以远端系统挂接在自己的档案系统之下。每次重启宿主PC机时,都须先输入命令:servicenfsrestart,以启动nfs效劳。实验七实验七通过用c语言编写的简单程序HelloWorld,测试前面几个实验是否成功配置好环境,从超级终端可以看到HelloWorld程序的运行结果。实验步骤如下:硬件连接:连接宿主PC机和一台PXA270-RP目标板。翻开宿主PC机电源,进入Linux操作系统。启动RedHat9.0的图形界面,如以下图,假设您是以root身份登陆在文本模式下,则输入命令startx启动图形界面。进入RedHat9.0图形界面后,翻开一个终端窗〔Terminal〕。输入minicom然后回车,minicim设置为1152008NI无流控。 翻开PXA270_RP目标板电源,按目标板上的BOOT键,在minicom中应该会看到如以下图:在minicom终端窗口中,如图,输入以下四条命令rootifconfigeth0upmount-onolock://mntcd/mnt此时,先将该窗口最小化,在后面的第10操作步骤中还将会回到该窗口中进行操作。宿主机上翻开一个终端窗口〔Terminal〕,点击【红帽/SystemTools/Terminal】启动终端窗口,输入以下4条命令:①cd/home②mkdirHW③cdHW④viHelloWorld.c/*请您输入程序7.1程序清单*/此时会显示一个空白的屏幕,这条命令的含义是,使用Vi编辑器,对一个名叫HelloWorld.c的文件进行编辑,我们看到的空白窗口是对文件进行编辑的窗口,如以下图。就像在Windows系统下面使用写字板等一样道理。在vi里面先单击键盘A键,然后左下角会变成—INSER。输入程序的时候和其他编辑器是一样的,如以下图。当输入程序完毕后,单击键盘Esc键,然后按“:〞〔冒号〕此时左下角会出现冒号然后输入“wq〞最后按“Enter〞确认存盘退出vi编辑器,如以下图。在上面同一个终端窗口中,输入以下2条命令交叉编译HelloWorld.c源程序,并查看生成的.o目标文件,如图7-10,图7-11:①arm-linux-gcc–oHelloWorldHelloWorld.c②ls等到再次出现提示符,代表程序已经正确编译。如果此步出现错误信息,请查看错误信息,并且重新编辑原来的C文件,修改错误。直到正确编译。重新翻开第7步最小化的开有minicom的终端窗口,即到PXA270-RP目标板的mnt目录下,请您输入以下3条命令,运行HelloWorld编译成功的HelloWorld目标程序:①cdhome/HW/*回到minicom中目标板的/mnt/home/HW目录下*/②ls③./HelloWorld/*此时会看到如以下图*/驱动程序设备驱动程序的概念设备驱动程序实际是处理和操作硬件控制器的软件,从本质上讲,是内核中具有最高特权级的、驻留内存的、可共享的底层硬件处理例程。驱动程序是内核的一局部,是操作系统内核与硬件设备的直接接口,驱动程序屏蔽了硬件的细节,完成以下功能:对设备初始化和释放;对设备进行管理,包括实时参数设置,以及提供对设备的操作接口;读取应用程序传送给设备文件的数据或者回送应用程序请求的数据;检测和处理设备出现的错误。Linux操作系统将所有的设备全部看成文件,并通过文件的操作界面进行操作。对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说,是把设备映射为一个特殊的设备文件,用户程序可以像对其他文件一样对此设备文件进行操作。这意味着:由于每一个设备至少由文件系统的一个文件代表,因而都有一个“文件名〞。应用程序通常可以通过系统调用open()翻开设备文件,建立起与目标设备的连接。翻开了代表着目标设备的文件,即建立起与设备的连接后,可以通过read()、write()、ioctl()等常规的文件操作对目标设备进行操作。设备文件的属性由三局部信息组成:第一局部是文件的类型,第二局部是一个主设备号,第三局部是一个次设备号。其中类型和主设备号结合在一起惟一地确定了设备文件驱动程序及其界面,而次设备号则说明目标设备是同类设备中的第几个。由于Linux中将设备当做文件处理,所以对设备进行操作的调用格式与对文件的操作类似,主要包括open()、read()、write()、ioctl()、close()等。应用程序发出系统调用命令后,会从用户态转到核心态,通过内核将open()这样的系统调用转换成对物理设备的操作。驱动程序结构一个设备驱动程序模块的根本框架在系统内部,I/O设备的存取通过一组固定的入口点来进行,入口点也可以理解为设备的句柄,就是对设备进行操作的根本函数。字符型设备驱动程序提供如下几个入口点:open入口点。翻开设备准备I/O操作。对字符设备文件进行翻开操作,都会调用设备的open入口点。open子程序必须对将要进行的I/O操作做好必要的准备工作,如去除缓冲区等。如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备处于忙状态。close入口点。关闭一个设备。当最后一次使用设备完成后,调用close子程序。独占设备必须标记设备方可再次使用。read入口点。从设备上读数据。对于有缓冲区的I/O操作,一般是从缓冲区里读数据。对字符设备文件进行读操作将调用read子程序。write入口点。往设备上写数据。对于有缓冲区的I/O操作,一般是把数据写入缓冲区里。对字符设备文件进行写操作将调用write子程序。ioctl入口点。执行读、写之外的操作。select入口点。检查设备,看数据是否可读或设备是否可用于写数据。select系统调用在检查与设备文件相关的文件描述符时使用select入口点。设备注册和初始化设备的驱动程序在加载的时候首先需要调用入口函数init_module(),该函数最重要的一个工作就是向内核注册该设备,对于字符设备调用register_chrdev()完成注册。register_chrdev的定义为:intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);其中,major是为设备驱动程序向系统申请的主设备号,如果为0,则系统为此驱动程序动态分配一个主设备号。name是设备名,fops是对各个调用的入口点说明。此函数返回0时表示成功;返回-EINVAL,表示申请的主设备号非法,主要原因是主设备号大于系统所允许的最大设备号;返回-EBUSY,表示所申请的主设备号正在被其他设备程序使用。如果动态分配主设备号成功,此函数将返回所分配的主设备号。如果register_chrdev()操作成功,设备名就会出现在/proc/dvices文件中。Linux在/dev目录中为每个设备建立一个文件,用ls–l命令列出函数返回值,假设小于0,则表示注册失败;返回0或者大于0的值表示注册成功。注册以后,Linux将设备名与主、次设备号联系起来。当有对此设备名的访问时,Linux通过请求访问的设备名得到主、次设备号,然后把此访问分发到对应的设备驱动,设备驱动再根据次设备号调用不同的函数。当设备驱动模块从Linux内核中卸载,对应的主设备号必须被释放。字符设备在cleanup_module()函数中调用unregister_chrdev()来完成设备的注销。unregister_chrdev()的定义为:intunregister_chrdev(unsignedintmajor,constchar*name);包括设备注册在内,设备驱动的初始化函数主要完成的功能是有以下5项。〔1〕对驱动程序管理的硬件进行必要的初始化。对硬件存放器进行设置。比方,设置中断掩码,设置串口的工作方式、并口的数据方向等。〔2〕初始化设备驱动相关的参数。一般说来,每个设备都要定义一个设备变量,用以保存设备相关的参数。在这一步骤里对设备变量中的项进行初始化。〔3〕在内核注册设备。调用register_chrdev()函数来注册设备。〔4〕注册中断。如果设备需要IRQ支持,则要使用request_irq()函数注册中断。〔5〕其他初始化工作。初始化局部一般还负责给设备驱动程序申请包括内存、时钟、I/O端口等在内的系统资源,这些资源也可以在open子程序或者其他地方申请。这些资源不用时,应该释放,以利于资源的共享。假设驱动程序是内核的一局部,初始化函数则要按如下方式声明:int__initchr_driver_init(void);其中__init是必不可少的,在系统启动时会由内核调用chr_driver_init,完成驱动程序的初始化。当驱动程序是以模块的形式编写时,则要按照如下方式声明:intinit_module(void)当运行后面介绍的insmod命令插入模块时,会调用init_module函数完成初始化工作。设备驱动程序的开发过程由于嵌入式设备由于硬件种类非常丰富,在默认的内核发布版中不一定包括所有驱动程序。所以进行嵌入式Linux系统的开发,很大的工作量是为各种设备编写驱动程序。除非系统不使用操作系统,程序直接操纵硬件。嵌入式Linux系统驱动程序开发与普通Linux开发没有区别。可以在硬件生产厂家或者Internet上寻找驱动程序,也可以根据相近的硬件驱动程序来改写,这样可以加快开发速度。实现一个嵌入式Linux设备驱动的大致流程如下。〔1〕查看原理图,理解设备的工作原理。一般嵌入式处理器的生产商提供参考电路,也可以根据需要自行设计。〔2〕定义设备号。设备由一个主设备号和一个次设备号来标识。主设备号惟一标识了设备类型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设备驱动程序解释,区分被一个设备驱动控制下的某个独立的设备。〔3〕实现初始化函数。在驱动程序中实现驱动的注册和卸载。〔4〕设计所要实现的文件操作,定义file_operations结构。〔5〕实现所需的文件操作调用,如read、write等。〔6〕实现中断效劳,并用request_irq向内核注册,中断并不是每个设备驱动所必需的。〔7〕编译该驱动程序到内核中,或者用insmod命令加载模块。〔8〕测试该设备,编写应用程序,对驱动程序进行测试。根本接口实验在完成了根本实验后,我们开始着手根本接口实验。在这些实验中,我们学习如何编写设备驱动程序,及如何用测试程序检验驱动程序是否正确,并通过改写测试程序正常地对驱动程序进行相关操作。实验十二 简单设备驱动程序本次实验的任务是编写一个字符型设备驱动程序,并学习在应用程序中调用驱动。考虑到我们初次接触驱动程序的编写,对此还十分陌生,因此指导书中提供了本次实验所要用到的程序源代码。虽然这样一个字符型设备驱动程序并没有任何实际作用,但是它让我们轻松掌握了嵌入式驱动的编写过程,因为复杂繁琐的驱动,其骨架都是相同的。因此,看懂本实验的源代码,学习并模仿其编写方法,对于后续实验有着非常重要的意义。实验十三 CPUGPIO驱动程序设计在本实验中,我们要编写第一个针对实际硬件的驱动程序。我们知道,但凡操作系统控制外部设备,即使是最简单的硬件电路,也是需要驱动的。本实验涉及的外部硬件只有电阻和发光二极管。我们使用自己编写的驱动程序与应用程序控制GPIO96的电平,通过LED的亮灭来判断,是否CPU做出了正确的响应。补充代码〔1〕//WRITEssize_tSIMPLE_GPIO_LED_write(structfile*file,constchar*buf,size_tcount,loff_t*f_ops){#ifdefOURS_GPIO_LED_DEBUGprintk("SIMPLE_GPIO_LED_write[--kernel--]\n");#endifreturncount;} 补充代码〔2〕//OPENssize_tSIMPLE_GPIO_LED_open(structinode*inode,structfile*file){#ifdefOURS_GPIO_LED_DEBUGprintk("SIMPLE_GPIO_LED_open[--kernel--]\n");#endifMOD_INC_USE_COUNT;return0;} 补充代码〔3〕//structfile_operationsGPIO_LED_ctl_ops={open:SIMPLE_GPIO_LED_open,read:SIMPLE_GPIO_LED_read,write:SIMPLE_GPIO_LED_write,ioctl:SIMPLE_GPIO_LED_ioctl,release:SIMPLE_GPIO_LED_release,};实验作业要求在目标板上LED闪烁产生亮7秒,灭2秒的效果在测试程序中有这样一段代码:while(1){ ioctl(fd,LED_OFF);sleep(1); //休眠1秒ioctl(fd,LED_ON);sleep(1); }只需将上面的代码改为如下代码即可:while(1){ ioctl(fd,LED_OFF);sleep(2); //灭2秒ioctl(fd,LED_ON);sleep(7); //亮7秒}实验十四 中断实验在理论课中,我们学习了许多中断方面的知识,包括中断向量、中断优先级、中断过程等。在PXA270系统里,中断控制器分外部设备和PXA270X处理器设备产生的两个层次的中断,前者是初级的中断源,后者是次级中断源,大量的次级中断源通常被映射为一个初级中断源。补充代码1voidshowversion(void){printk("*********************************************\n");printk("\t%s\t\n",VERSION);printk("*********************************************\n\n");}static intSimpleINT_temp_count=0;补充代码2//READssize_tSIMPLE_INT_read(structfile*file,char*buf,size_tcount,loff_t*f_ops){#ifdefOURS_INT_DEBUG printk("SIMPLE_INT_read[--kernel--]\n"); #endif returncount;} 补充代码3//WRITEssize_tSIMPLE_INT_write(structfile*file,constchar*buf,size_tcount,loff_t*f_ops){#ifdefOURS_INT_DEBUG printk("SIMPL_INT_write[--kernel--]\n"); #endif returncount;}补充代码4//structfile_operationsINT_ctl_ops={open:SIMPLE_INT_open,read:SIMPLE_INT_read,write:SIMPLE_INT_write,ioctl:SIMPLE_INT_ioctl,release:SIMPLE_INT_release,}; 解了硬件中断脚与中断的对应关系以及中断号与中断处理程对应关,对于今后编写更为复杂的中断程序打下根底。实验十五 数码管显示实验在此实验中,我们要编写针对74LV164的驱动程序,并用其串并转换功能来控制八段LED数码管的显示。补充代码1voidshowversion(void){printk("*********************************************\n");printk("\t%s\t\n",VERSION);printk("*********************************************\n\n");}补充代码2//READssize_tSERIAL_LED_read(structfile*file,char*buf,size_tcount,loff_t*f_ops){#ifdefOURS_HELLO_DEBUG printk("SERIAL_LED_read[--kernel--]\n"); #endif returncount;} 补充代码3//WRITEssize_tSERIAL_LED_write(structfile*file,constchar*buf,size_tcount,loff_t*f_ops){#ifdefOURS_HELLO_DEBUG printk("SERIAL_LED_write[--kernel--]\n"); #endif write_byte(*buf); returncount;}补充代码4//IOCTLssize_tSERIAL_LED_ioctl(structinode*inode,structfile*file,unsignedintcmd,longdata){#ifdefOURS_HELLO_DEBUG printk("SERIAL_LED_ioctl[--kernel--]\n");#endif return0;}补充代码5//OPENssize_tSERIAL_LED_open(structinode*inode,structfile*file){#ifdefOURS_HELLO_DEBUG printk("SERIAL_LED_open[--kernel--]\n");#endif MOD_INC_USE_COUNT; return0;} 补充代码6//RELEASE/CLOSEssize_tSERIAL_LED_release(structinode*inode,structfile*file){ #ifdefOURS_HELLO_DEBUG printk("SERIAL_LED_release[--kernel--]\n");#endif MOD_DEC_USE_COUNT; return0;}补充代码7//structfile_operationsSERIAL_LED_ops={open:SERIAL_LED_open,read:SERIAL_LED_read,write:SERIAL_LED_write,ioctl:SERIAL_LED_ioctl,release:SERIAL_LED_release,};补充代码8staticint__initHW_SERIAL_LED_init(void){intret=-ENODEV; ret=devfs_register_chrdev(SERIAL_LED_MAJOR,"serial_led_ctl",&SERIAL_LED_ops); showversion(); if(ret<0) { printk("pxa270init_modulefailedwith%d\n[--kernel--]",ret); returnret; } else { printk("pxa270serial_led_driverregistersuccess!!![--kernel--]\n"); } returnret;}补充代码9staticint__initpxa270_SERIAL_LED_init(void){intret=-ENODEV; #ifdefOURS_HELLO_DEBUGprintk("pxa270_SERIAL_LED_init[--kernel--]\n");#endifret=HW_SERIAL_LED_init();if(ret)returnret;return0;}补充代码10staticvoid__exitcleanup_SERIAL_LED(void){#ifdefOURS_HELLO_DEBUG printk("cleanup_SERIAL_LED[--kernel--]\n");#endif devfs_unregister_chrdev(SERIAL_LED_MAJOR,"serial_led");}补充代码11MODULE_DESCRIPTION("serial_leddrivermodule");MODULE_AUTHOR("liduo");MODULE_LICENSE("GPL");module_init(pxa270_SERIAL_LED_init);module_exit(cleanup_SERIAL_LED);使用测试程序看到的测试结果是数码管按0-9显示输出。实验作业要求在上述根底上,分别实现一下两个功能:①要求您再编写一个测试程序,实现PXA270-EP目标板上的LED数码管循环显示的数字9-0。②要求您再编写一个测试程序,实现PXA270-EP目标板上的LED数码管循环显示的数字02468。由于在测试程序中定义了数组buf[10]分别存储了0-9是个数,因此上述功能的实现方法是,分别对测试程序做如下修改:原测试程序:while(1){ for(count=0;count<10;count++){ data[0]=buf[count];ret=write(fd,data,1);sleep(1);}}实现功能①:while(1){ for(count=9;count>=0;count--) //倒序显示数字{ data[0]=buf[count];ret=write(fd,data,1);sleep(1);}}结果显示实现功能②:while(1){ for(count=0;count<9;count=count+2) //更改显数顺序{ data[0]=buf[count];ret=write(fd,data,1);sleep(1);}}结果显示通过更改显数的顺序,很容易实现实验作业里要求的功能。实验十六LED点阵驱动程序设计通过本实验的操作,我们将8X8的点阵LED驱动起来并通过编写测试程序,使其能够按照您的意图进行显示。要求您还编写更多的测试程序补充代码1voidshowversion(void){printk("*********************************************\n");printk("\t%s\t\n",VERSION);printk("*********************************************\n\n");}补充代码2//READssize_tSIMPLE_LED_read(structfile*file,char*buf,size_tcount,loff_t*f_ops){#ifdefOURS_LED_DEBUG printk("SIMPLE_LED_read[--kernel--]\n"); #endif returncount;} 补充代码3//IOCTLssize_tSIMPLE_LED_ioctl(structinode*inode,structfile*file,unsignedintcmd,longdata){ #ifdefOURS_LED_DEBUG printk("SIMPLE_LED_ioctl[--kernel--]\n");#endif return0;}补充代码4//structfile_operationsLED_ctl_ops={ open: SIMPLE_LED_open,read:SIMPLE_LED_read,write:SIMPLE_LED_write,ioctl:SIMPLE_LED_ioctl,release:SIMPLE_LED_release,};补充代码5staticint__initpxa270_LED_CTL_init(void){intret=-ENODEV; #ifdefOURS_LED_DEBUGprintk("pxa270_LED_CTL_init[--kernel--]\n");#endifret=HW_LED_CTL_init();if(ret)returnret;return0;}补充代码6staticvoid__exitcleanup_LED_ctl(void){#ifdefOURS_LED_DEBUG printk("cleanup_LED_ctl[--kernel--]\n");#endif outw(0x0000,ioremap_addr); devfs_unregister_chrdev(SIMPLE_LED_MAJOR,"led_ary_ctl");}①要求您再编写一个测试程序,实现按横的方向隔行顺序扫描LED点阵数码管。②要求您再编写一个测试程序,实现按竖的方向顺序扫描LED点阵数码管。作业一,隔行扫描: for(i=1;i<=8;i2++){ buf[0]=c; buf[1]=~r;//row for(j=1;j<=8;j++){ write(fd,buf,2); printf("buf[0],buf[1]:[%x,%x]\n",buf[0],buf[1]); usleep(200000);//sleep0.2second r=r<<1; buf[1]=~r;//column } r=1; c=c<<1;结果显示作业二,竖向扫描: for(i=1;i<=8;i++){ buf[0]=c; buf[1]=~r;//row for(j=1;j<=8;j++){ write(fd,buf,2); printf("buf[0],buf[1]:[%x,%x]\n",buf[0],buf[1]); usleep(200000);//sleep0.2second r=r<<1; buf[1]=~r;//column } r=1; c=c<<1;结果显示实验十七AD驱动实验通过本实验的操作,我们将AD转换器驱动起来并通过编写测试程序,使其能够将模拟信号量按照我们的要求转换成数字信号量。为了更加清楚地理解AD转换器的工作过程,请您再编写一个测试程序,将UCB_ADC_INP_AD0换成其他通道,来观察其他AD通道情况。补充代码1voidshowversion(void){printk("%s\n",VERSION);}structucb1x00*ad_ucb;补充代码2//READstaticssize_tadctl_read(structfile*file,char*buf,size_tcount,loff_t*offset){ #ifdefOURS_HELLO_DEBUG printk("read\n"); #endif returncount;}补充代码3//WRITEssize_tadctl_write(structfile*file,constchar*buf,size_tcount,loff_t*offset){#ifdefOURS_HELLO_DEBUGprintk("write\n");#endif returncount;}补充代码4//OPENssize_tadctl_open(structinode*inode,structfile*file){#ifdefOURS_HELLO_DEBUGprintk("open\n");#endif return0;}补充代码5//RELEASE/CLOSEssize_tadctl_release(structinode*inode,structfile*file){#ifdefOURS_HELLO_DEBUGprintk("release\n");#endif return0;}补充代码6staticstructfile_operationsadctl_ops={ read: adctl_read, write: adctl_write, ioctl: adctl_ioctl, open: adctl_open, release:adctl_release,};补充代码7//INITstaticint__initHW_AD_CTL_init(void){ intret=-ENODEV; ret=devfs_register_chrdev(ADCTL_MAJOR,"adctl",&adctl_ops); showversion(); ad_ucb=ucb1x00_get(); if(ret<0) { printk("fail%d\n",ret); return0; } else { printk("adctldriverregistersuccess!\n"); } adctl_dev_handle=devfs_register(NULL,"ad_ctl",DEVFS_FL_DEFAULT,ADCTL_MAJOR,0,S_IFCHR,&adctl_ops,NULL);returnret;}补充代码8staticint__initpxa270_AD_CTL_init(void){intret=-ENODEV; #ifdefOURS_HELLO_DEBUG printk("init\n"); #endifret=HW_AD_CTL_init();if(ret) returnret;return0;}补充代码9staticvoid__exitcleanup_AD_ctl(void){ #ifdefOURS_HELLO_DEBUG printk("cleanup\n"); #endif devfs_unregister_chrdev(ADCTL_MAJOR,"ad_ctl"); devfs_unregister(adctl_dev_handle);}实验十八DA驱动实验通过本实验的操作,我们使用示波器看到了通过DA转换而输出的波形。在此根底上,要求试写一个实现输出三角波的测试程序。补充代码1#include<linux/config.h>#include<linux/kernel.h>#include<linux/sched.h>#include<linux/timer.h>#include<linux/init.h>#include<linux/module.h>#include<asm/hardware.h>#include<asm/io.h>补充代码2voidshowversion(void){printk("*****************************\n"); printk("\t%s\t\n",VERSION); printk("*****************************\n");}staticlongioremap_addr;补充代码3//READssize_tSIMPLE_DA_read(structfile*file,char*buf,size_tcount,loff_t*f_ops){#ifdefOURS_DA_DEBUG printk("SIMPLE_DA_read[--kernel--]\n"); #endif returncount;} 补充代码4//WRITEssize_tSIMPLE_DA_write(structfile*file,constchar*buf,size_tcount,loff_t*f_ops){ #ifdefOURS_DA_DEBUGprintk("SIMPLE_DA_write[--kernel--]\n");#endif outb(buf[0],ioremap_addr);returncount;} 补充代码5//IOCTLssize_tSIMPLE_DA_ioctl(structinode*inode,structfile*file,unsignedintcmd,longdata){#ifdefOURS_DA_DEBUGprintk("SIMPLE_DA_ioctl[--kernel--]\n");#endifreturn0;}补充代码6//OPENssize_tSIMPLE_DA_open(structinode*inode,structfile*file){ #ifdefOURS_DA_DEBUG printk("SIMPLE_DA_open[--kernel--]\n");#endif MOD_INC_USE_COUNT; return0;} 补充代码7/structfile_operationsDA_ctl_ops={read:SIMPLE_DA_read, write:SIMPLE_DA_write, ioctl:SIMPLE_DA_ioctl, release:SIMPLE_DA_release,};补充代码8//INITstaticint__initHW_DA_CTL_init(void)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 土石方工程分包劳务合同范本
- 上海市购房合同范本
- 外教教学成果代理销售合同
- 租赁合同范本
- 消防工程劳务分包协议样本
- 购销合同管理的法律规定
- 保函和保证书合同履行安全的保障
- 外企合作合同
- 摩托车零部件修理协议
- 防水施工分包合同模板
- 2.0MWp屋顶太阳能分布式光伏发电项目监理大纲2
- 灌入式复合路面施工指南
- 2023级高数(上)试卷及答案
- 数控车床上下料机械手设计说明书
- 高中数学公开课优质课1.3.0探究与发现“杨辉三角”中的一些秘密【市一等奖】优质课
- 100KW分布式光伏电站设计方案
- 2010版GMP附录:计算机化系统整体及条款解读(完整精华版)
- 网吧企业章程范本
- 商业综合体、购物中心、百货商场商业运营项目收益测算模板
- 丙烯储罐毕业设计
- 水工建筑物水泥灌浆施工技术规范
评论
0/150
提交评论