实验四设备驱动.docx
- 文档编号:7390464
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:12
- 大小:1.11MB
实验四设备驱动.docx
《实验四设备驱动.docx》由会员分享,可在线阅读,更多相关《实验四设备驱动.docx(12页珍藏版)》请在冰豆网上搜索。
实验四设备驱动
实验三基于ARM92440linux系统设备驱动
一、实验内容
在ARM9系列s3c2440开发版平台上基于linux实现LED流水灯驱动的编写与实现。
首先确定所使用的Linux的内核版本以及gcc版本,然后配置交叉编译环境,最后编写实现驱动。
2、实验目的
1、了解Linux设备驱动的编写环境;
2、熟悉编写Linux设备驱动的完整流程;
3、完成Led灯驱动的编写,是基于Linux编写其他驱动程序的基础。
3、实验原理
linux系统将设备分为3类:
字符设备、块设备、网络设备。
字符设备:
是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据。
字符设备是面向流的设备,常见的字符设备有鼠标、键盘、串口、控制台和LED设备等。
块设备:
是指可以从设备的任意位置读取一定长度数据的设备。
块设备包括硬盘、磁盘、U盘和SD卡等。
每种类型的驱动程序,不管是字符设备还是块设备都为内核提供相同的调用接口,因此内核能以相同的方式处理不同的设备。
Linux为每种不同类型的设备驱动程序维护相应的数据结构,以便定义统一的接口并实现驱动程序的可装载性和动态性。
Linux设备驱动程序与外界的接口可以分为如下三个部分。
1.驱动程序与操作系统内核的接口:
通过数据结构file_operations来完成的。
2.驱动程序与系统引导的接口:
这部分利用驱动程序对设备进行初始化。
3.驱动程序与设备的接口:
这部分描述了驱动程序如何与设备进行交互,这与具体设备密切相关。
它们之间的相互关系如下图所示。
当一个模块设备驱动加载到内核,将执行一些初始的工作,如重新设置设备,reservingRAM,reservinginterrupts,reservinginput/outputports,etc.这些工作得以在内核空间执行,必须要有两个函数存在:
module_init和module_exit;它们对应于用户空间的insmod和rmmod命令。
总之,用户命令insmod和rmmod使用了内核空间的函数module_init和module_exit.
要实现GPIO控制LED的驱动,先看看电路图,实验箱使用引脚GPJ4控制LED1(D501),GPJ1控制LED2(D502),GPJ2控制LED3(D503),GPJ11控制LED4(D504)如图所示,LED分别通过两个SN74LVC245A和S3C2440引脚连接,点灯具体设置如下:
①设置245芯片方向,设置为0即可控制LED灯;②设置LED控制引脚为输出状态;③由LED电路图设置,点亮LED时令引脚输出1,熄灭LED时令引脚输出0。
图三LED模块电路图
四、实验步骤
1.准备工作:
使用串口连接把ARM9S3C2440实验箱和PC端连接起来。
然后开启虚拟机并使用命令cat/proc/version进入串口查看实验箱Linux的内核版本和内核镜像编译采用的gcc版本。
如下图所示:
从上图可以看出试验箱采用的Linux内核版本为2.6.30.4,gcc版本为4.3.3,则交叉编译环境应改为4.3.3版本。
2.使用命令解压EABI-4.3.3_EmbedSky_20091210.tar.bz2,在home目录下使用tarxvfjEABI-4.3.3_EmbedSky_20091210.tar.bz2,如图所示:
解压之后虚拟机home下面解压之后多了opt,usr两个文件夹。
进入home目录后,可以看出opt目录权限不足,使用命令chmod对其权限进行修改。
3.将解压后产生的opt/EmbedSky/4.3.3拷贝到opt/EmbedSky下,拷贝之后/opt/EmbedSky目录内容如下所示:
4.建立交叉编译环境:
在虚拟机中输入命令gedit/etc/bash.bashrc,在该文件下添加如下信息exportPATH=/opt/EmbedSky/4.3.3/bin:
$PATH,并用”#”注释掉之前配置的3.4.1的环境变量。
5.
在虚拟机中输入source/etc/bash.bashrc命令,然后再输入命令arm-linux-gcc–v,如果出现信息gccversion4.3.3(SourceryG++Lite2009q1-176),表示环境变量配置为4.3.3成功。
6.将Linux-2.6.30.4的源代码,复制到工作目录下并解压。
在根目录下用mkdirwork/EmbedSky新建路径,并进入home/opt/EmbeySky使用cp命令将内核源代码压缩包linux-2.6.30.4.tar.gz复制到新建的work/EmbedSky文件夹中,使用命令tarzxvflinux-2.6.30.4.tar.gz解压此压缩包。
然后获取权限:
接下来开始led驱动的编写。
7.根据电路和IO使用情况编写代码,然后在虚拟机中进入虚拟机内核目录:
work/EmbedSky/linux-2.6.30.4,在该目录中的driver/char文件夹中新建文件first_drv.c,并将写好的驱动程序粘贴在该文件中,驱动代码见附录1。
8.需要在内核源码中,在上述目录中找到Kconfig文件,在里面添加对Led驱动的支持,内容如下图configfirst_drv所示,添加之后保存即可
9、然后修改同目录下的“Makefile”文件,如图所示:
10.接下来配置内核。
在内核目录work/EmbedSky/linux-2.6.30.4下,输入makemenuconfig,会发现运行报错。
因为makemenuconfig需要ncurse的库,这时需要下载这个库,输入命令:
apt-getinstall–libncurses5-dev,选择Y即可。
11.配置内核,在内核目录下,输入makemenuconfig,然后配置如下图所示。
(1)上下键选择DeviceDrivers--->,Enter进入。
(2)选择Characterdevices--->
(3)选择LEDsDriver,在括号内输入M,将其选择为“M”(模块),然后左右键切换选择Exit三次,最后选择Yes,然后保存配置。
内核配置就完成了。
(4)使用命令#makeSUBDIR=drivers/char/modules,然后编译出驱动模块,在内核目录下面的“drivers/char/”目录下面,可以看到编译后生成的驱动文件first_drv.ko
编译成功的结果如下图所示:
13.将驱动文件first_drv.ko复制到NFS共享目录下,通过NFS共享到开发板。
若没有配置好NFS,请拷贝到U盘插到实验箱上。
本电脑没有配置好NFS直接用U盘拷贝到实验箱上。
14.编写LED灯控制程序。
在/work目录下,新建文件夹first_drv,在该文件夹下新建文件firstdrvtest.c,并将写好的控制程序粘贴在该文件中。
15.编译测试程序,将程序直接拷贝到U盘。
在实验箱上测试实验结果。
五、总结
将U盘插在实验箱上,在securecrt中输入以下命令:
[root@EmbedHENKE/mnt]#./firstdrvteston,这时LED1,LED2,LED3亮;[root@EmbedHENKE/mnt]#./firstdrvtestoff,这时LED1,LED2,LED3灭。
Led测试程序运行完毕之后,运行以下命令:
[root@EmbedHENKE/mnt]#rmmodfirst_drv.ko卸载模块,到此整个驱动编写过程完成。
本次实验我了解了基于linux驱动编写的整个流程,驱动程序编写需要的环境,配置交叉编译环境,以及掌握了怎么实现驱动程序的代码编写。
在这次实验过程中,到最后使用命令#makeSUBDIR=drivers/char/modules,然后编译出驱动模块的时候一直报错,最后发现是由于文件保存的路径不对,所以在我们今后的编程过程中,一定要细心,否则会浪费一些不必要的时间。
看书百遍,不如实践。
附录
first_drv.c的源程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineDEVICE_NAME"leds"
/*加载模式后,执行”cat/proc/devices”命令看到的设备名称*/
staticstructclass*firstdrv_class;
staticstructclass_device*firstdrv_class_dev;
volatileunsignedlong*gpjcon=NULL;
volatileunsignedlong*gpjdat=NULL;
staticintfirst_drv_open(structinode*inode,structfile*file)
{
//printk("first_drv_open\n");
/*配置GPJ4,GPJ1,GPJ2,其中GPJ5,GPJ7为245输出*/
*gpjcon&=~((0x3<<(4*2))|(0x3<<(1*2))|(0x3<<(2*2))|(0x3<<(5*2))|(0x3<<(7*2)));
*gpjcon|=((0x1<<(4*2))|(0x1<<(1*2))|(0x1<<(2*2))|(0x1<<(5*2))|(0x1<<(7*2)));
return0;
}
staticssize_tfirst_drv_write(structfile*file,constchar__user*buf,size_tcount,loff_t*ppos)
{
intval;
//printk("first_drv_write\n");
copy_from_user(&val,buf,count);//copy_to_user();
if(val==0)
{
//点灯,GPJ5,GPJ7=0设置245为方向
*gpjdat&=~((1<<4)|(1<<1)|(1<<2)|(1<<5)|(1<<7));
}
else
{
//灭灯
*gpjdat&=~((1<<5)|(1<<7));//GPJ5,GPJ7=0设置245为方向
*gpjdat|=(1<<4)|(1<<1)|(1<<2);
}
return0;
}
staticstructfile_operationsfirst_drv_fops={
.owner=THIS_MODULE,
/*这是一个宏,推向编译模块时自动创建的__this_module变量*/
.open=first_drv_open,
.write=first_drv_write,
};
intmajor;
staticintfirst_drv_init(void)
{
major=register_chrdev(0,"first_drv",&first_drv_fops);//注册,告诉内核
firstdrv_class=class_create(THIS_MODULE,"firstdrv");
firstdrv_class_dev=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"leds");/*/dev/xyz*/
gpjcon=(volatileunsignedlong*)ioremap(0x560000D0,16);
gpjdat=gpjcon+1;
printk(DEVICE_NAME"driverby506labouratory,allrightsreserved.\n");
printk(DEVICE_NAME"initialized\n");
return0;
}
staticvoidfirst_drv_exit(void)
{
unregister_chrdev(major,"first_drv");//卸载
device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
iounmap(gpjcon);
}
module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");
2.firstdrvtest.c的源程序:
#include
#include
#include
#include
/*firstdrvteston
*firstdrvtestoff
*/
intmain(intargc,char**argv)
{
intfd;
intval=1;
fd=open("/dev/leds",O_RDWR);
if(fd<0)
{
printf("can'topen!
\n");
}
if(argc!
=2)
{
printf("Usage:
\n");
printf("%s
return0;
}
if(strcmp(argv[1],"on")==0)
{
val=1;
}
else
{
val=0;
}
write(fd,&val,4);
return0;
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 设备 驱动
![提示](https://static.bdocx.com/images/bang_tan.gif)