实验五嵌入式Linux设备驱动开发试验文档格式.docx
- 文档编号:7973439
- 上传时间:2023-05-09
- 格式:DOCX
- 页数:12
- 大小:764.58KB
实验五嵌入式Linux设备驱动开发试验文档格式.docx
《实验五嵌入式Linux设备驱动开发试验文档格式.docx》由会员分享,可在线阅读,更多相关《实验五嵌入式Linux设备驱动开发试验文档格式.docx(12页珍藏版)》请在冰点文库上搜索。
voids3c2410_gpio_cfgpin(unsignedintpin,unsignedintfunction)
{
void__iomem*base=S3C24XX_GPIO_BASE(pin);
unsignedlongmask;
unsignedlongcon;
unsignedlongflags;
if(pin<
S3C2410_GPIO_BANKB){
mask=1<
<
S3C2410_GPIO_OFFSET(pin);
}else{
mask=3<
S3C2410_GPIO_OFFSET(pin)*2;
}
switch(function){
caseS3C2410_GPIO_LEAVE:
mask=0;
function=0;
break;
caseS3C2410_GPIO_INPUT:
caseS3C2410_GPIO_OUTPUT:
caseS3C2410_GPIO_SFN2:
caseS3C2410_GPIO_SFN3:
function-=1;
function&
=1;
function<
=S3C2410_GPIO_OFFSET(pin);
=3;
=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<
linux/miscdevice.h>
linux/delay.h>
asm/irq.h>
mach/regs-gpio.h>
mach/hardware.h>
linux/kernel.h>
linux/module.h>
linux/init.h>
linux/mm.h>
linux/fs.h>
linux/types.h>
linux/moduleparam.h>
linux/slab.h>
linux/errno.h>
linux/ioctl.h>
linux/cdev.h>
linux/string.h>
linux/list.h>
linux/pci.h>
linux/gpio.h>
asm/uaccess.h>
asm/atomic.h>
asm/unistd.h>
#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,
/*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:
/*
*设备函数操作集,在此只有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(&
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文件,内容如下:
stdio.h>
stdlib.h>
unistd.h>
sys/ioctl.h>
intmain(intargc,char**argv)
inton;
intled_no;
intfd;
if(argc!
=3||sscanf(argv[1],"
%d"
&
led_no)!
=1||sscanf(argv[2],"
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){
/dev/leds"
perror("
opendeviceleds"
ioctl(fd,on,led_no);
close(fd);
将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 设备 驱动 开发 试验
![提示](https://static.bingdoc.com/images/bang_tan.gif)