实验五嵌入式Linux设备驱动开发试验.docx
- 文档编号:6257156
- 上传时间:2023-05-09
- 格式:DOCX
- 页数:12
- 大小:764.58KB
实验五嵌入式Linux设备驱动开发试验.docx
《实验五嵌入式Linux设备驱动开发试验.docx》由会员分享,可在线阅读,更多相关《实验五嵌入式Linux设备驱动开发试验.docx(12页珍藏版)》请在冰点文库上搜索。
实验五嵌入式Linux设备驱动开发试验
合肥学院
嵌入式系统设计实验报告
(2013-2014第二学期)
专业:
11自动化卓越班
实验项目:
实验五Linux设备驱动开发实验
实验时间:
2014年5月20
实验成员:
、
_____
指导老师:
干开峰
电子信息与电气工程系
2014年4月制
一、实验目的
1、熟悉嵌入式Linux下设备驱动程序的设计的进本方法。
2、掌握字符设备驱动程序的设计和调试方法。
3、熟悉设备驱动的测试和使用。
二、实验内容
本实验要求学生熟悉嵌入式Linux下设备驱动程序的设计的基本方法,掌握字符设备驱动程序的设计和调试方法,完成LED驱动程序的编写和调试,并在目标开发板上测试。
3、实验步骤
1、在linux-2.6.32.2/arch/arm/plat-s3c24x文件夹中打开gpio.c文件,查看s3c2410_gpio_cfgpin函数,
voids3c2410_gpio_cfgpin(unsignedintpin,unsignedintfunction)
{
void__iomem*base=S3C24XX_GPIO_BASE(pin);
unsignedlongmask;
unsignedlongcon;
unsignedlongflags;
if(pin mask=1< }else{ mask=3< } switch(function){ caseS3C2410_GPIO_LEAVE: mask=0; function=0; break; caseS3C2410_GPIO_INPUT: caseS3C2410_GPIO_OUTPUT: caseS3C2410_GPIO_SFN2: caseS3C2410_GPIO_SFN3: if(pin function-=1; function&=1; function<<=S3C2410_GPIO_OFFSET(pin); }else{ function&=3; function<<=S3C2410_GPIO_OFFSET(pin)*2; } } /*modifythespecifiedregisterwwithIRQsoff*/ local_irq_save(flags); con=__raw_readl(base+0x00); con&=~mask; con|=function; __raw_writel(con,base+0x00); local_irq_restore(flags); } 2、在drivers/char目录下,我们建立一个驱动程序文件mini2440_leds.c,内容如下: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #defineDEVICE_NAME"leds"//设备名(/dev/leds) //LED对应的GPIO端口列表 staticunsignedlongled_table[]={ S3C2410_GPB(5), S3C2410_GPB(6), S3C2410_GPB(7), S3C2410_GPB(8), }; //LED对应端口将要输出的状态列表 staticunsignedintled_cfg_table[]={ S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, }; /*ioctl函数的实现 *在应用/用户层将通过ioctl函数向内核传递参数,以控制LED的输出状态 */ staticintsbc2440_leds_ioctl( structinode*inode, structfile*file, unsignedintcmd, unsignedlongarg) { switch(cmd){ case0: case1: if(arg>4){ return-EINVAL; } //根据应用/用户层传递来的参数(取反),通过s3c2410_gpio_setpin函数设置LED对应的端口寄存 器, s3c2410_gpio_setpin(led_table[arg],! cmd); return0; default: return-EINVAL; } } /* *设备函数操作集,在此只有ioctl函数,通常还有read,write,open,close等,因为本LED驱动在下面已经 *注册为misc设备,因此也可以不用open/close */ staticstructfile_operationsdev_fops={ .owner=THIS_MODULE, .ioctl=sbc2440_leds_ioctl, }; /* *把LED驱动注册为MISC设备 */ staticstructmiscdevicemisc={ .minor=MISC_DYNAMIC_MINOR,//动态设备号 .name=DEVICE_NAME, .fops=&dev_fops, }; /* *设备初始化 */ staticint__initdev_init(void) { intret; inti; for(i=0;i<4;i++){ //设置LED对应的端口寄存器为输出(OUTPUT) s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]); //设置LED对应的端口寄存器为低电平输出,在模块加载结束后,四个LED应该是全部都是发光 状态 s3c2410_gpio_setpin(led_table[i],0); } ret=misc_register(&misc);//注册设备 printk(DEVICE_NAME"\tinitialized\n");//打印初始化信息 returnret; } staticvoid__exitdev_exit(void) { misc_deregister(&misc); } module_init(dev_init);//模块初始化,仅当使用insmod/podprobe命令加载时有用,如果设备不是通过模块方 式加载,此处将不会被调用 module_exit(dev_exit);//卸载模块,当该设备通过模块方式加载后,可以通过rmmod命令卸载,将调用此函 数 MODULE_LICENSE("GPL");//版权信息 MODULE_AUTHOR("FriendlyARMInc.");//开发者信息 3、我们添加LED设备的内核配置选项,打开drivers/char/Kconfig文件,添加如 下部分内容: configLEDS_MINI2440 tristate"LEDSupportforMini2440GPIOLEDs" dependsonMACH_MINI2440 defaultyifMACH_MINI2440 help ThisoptionenablessupportforLEDsconnectedtoGPIOlines onMini2440boards. 4、把对应的驱动目标文件加入内核中,打开 linux-2.6.32.2/drivers/char/Makefile文件,添加如下部分内容: obj-$(CONFIG_LEDS_MINI2440)+=mini2440_leds.o 这样,我们就在内核中添加做好了LED驱动。 5、输入makemenuconfig命令重新配置内核 DeviceDrivers--->Characterdevices--->进入LED驱动配置菜单。 并退出保存内核配置。 5、在内核源代码根目录下执行;makezImage,把生成的新内核烧写到开发板中。 6、测试LED 为了测试该驱动程序,需要编写一个简单的测试程序,用来调用驱动程序中的ioctl函数,已达到通过应用程序控制LED的目的。 新建一个leds-test.c文件,内容如下: #include #include #include #include intmain(intargc,char**argv) { inton; intled_no; intfd; if(argc! =3||sscanf(argv[1],"%d",&led_no)! =1||sscanf(argv[2],"%d",&on)! =1|| on<0||on>1||led_no<0||led_no>3){ fprintf(stderr,"Usage: ledsled_no0|1\n"); exit (1); } fd=open("/dev/leds0",0); if(fd<0){ fd=open("/dev/leds",0); } if(fd<0){ perror("opendeviceleds"); exit (1); } ioctl(fd,on,led_no); close(fd); return0; } 将leds-test.c文件放在内核目录下、drivers/char/目录下,并在drivers/char/下执行arm-linux-gcc-oleds_testleds-test.c命令, 将生成可执行目标文件leds-test, 四、实验小结 本次实验做的是关于嵌入式Linux设备驱动开发试验,要在嵌入式Linux上开发应用程序,通过LED控制电路设备驱动(前面实验中已开发)的能力操作LED控制电路,实现四个LED灯点亮与熄灭的功能。 老师在课堂上也详细演示了PWM控制蜂鸣器的功能,对此我们也有了大致思路,跟着Mini2440Linux移植开发实战指南及实验指导书后面,我们知道通过编写添加驱动程序mini2440_leds.c、把驱动程序加入内核、配置编译新内核并测试LED,这样就可以实现对LED的驱动开发。 相对前几次实验而言,本次试验遇到的问题就很少了,通过查找资料,不断排错,本次实验完成的很成功。 五、思考题 思考题 1、简述驱动程序主要功能。 答: 对设备初始化和释放。 检测和处理设备出现的错误。 为应用程序提供统一的接口,用于数据传送。 2、简述驱动程序的组成。 答: 自动配置和初始化子程序。 服务于I/O请求的子程序,又称驱动程序的上半部分。 中断服务子程序,又称驱动程序的下半部分。 3、简述设备文件、驱动程序、主设备号和次设备号之间的关系? 答: 如下图所示: 此外主设备号和次设备号之间的关系: 主设备号用于标识设备对应的驱动程序,主设备号相同的设备使用相同的设备驱动程序(主设备号用于区分设备的类型)。 次设备号是用来区分具体设备的实例(次设备号用于区分同类型的设备)。 4、简述设备驱动程序和应用程序的区别。 答: 主动与被动的区别。 应用程序有一个main函数,总是从些函数开始主动执行一个任务,而驱动程序安装之后,便停止工作,并等待被应用程序调用。 使用的库函数不同。 程序运行的区域不同。 驱动程序工作在内核态;应用程序工作在用户态。 5、简述字符设备驱动程序提供的常用入口点以及各自的功能。 答: open入口点。 打开设备准备I/O操作。 对字符特别设备文件进行打开操作,都会调用设备的open入口点。 open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除Unix系统缓冲区等。 如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备处于忙状态。 close入口点。 关闭一个设备。 当最后一次Unix系统使用设备终结后,调用close子程序。 独占设备必须标记设备可再次使用。 read入口点。 从设备上读数据。 对于有缓冲区的I/O操作,一般是从缓冲区里读数据。 对字符特别设备文件进行读操作将调用read子程序。 write入口点。 往设备上写数据。 对于有缓冲区的I/O操作,一般是把数据写入缓冲区里。 对字符特别设备文件进行写操作将调用write子程序。 ioctl入口点。 执行读、写之外的操作。 select入口点。 检查Unix系统设备,看数据是否可读或设备是否可用于写数据。 select系统调用在检查与设备特别文件相关的文件描述符时使用select入口点。 如果设备驱动程序没有提供上述入口点中的某一个,系统会用缺省的子程序来代替。 对于不同的系统,也还有一些其它的入口点。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 嵌入式 Linux 设备 驱动 开发 试验