嵌入式实验 IO drivers.docx
- 文档编号:8218697
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:27
- 大小:561.95KB
嵌入式实验 IO drivers.docx
《嵌入式实验 IO drivers.docx》由会员分享,可在线阅读,更多相关《嵌入式实验 IO drivers.docx(27页珍藏版)》请在冰豆网上搜索。
嵌入式实验IOdrivers
实验五IO驱动
【实验目的】
Ø掌握IO驱动的编写,编译,加载过程。
Ø掌握驱动测试的方法。
【实验仪器】
1、装有Ubuntu操作系统的PC机一台;
2、XSBase270ARM实验开发平台一套
【实验环境】
使用移植好的内核代码/home/ustb/usefule/linux-2.6.22.10和光盘提供的文件系统。
【实验步骤】
用模块加载的方式添加四位八段数码管驱动:
1,利用vim编辑器或者gedit编写驱动代码(见xsb_seg.c文件);
(1)增加驱动所需的头文件和变量
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
charLED_MODULE=0;
#defineDEVICE_NAME"xsb_seg"
#defineSEG_CS10x10300000
#defineSEG_CS20x10400000
staticcharLED[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,0x6F};
unsignedlong*CS1_Address,*CS2_Address;
structseg
{
charLED1_Val;
charLED2_Val;
charLED3_Val;
charLED4_Val;
charnegative;
};
(2)同时更新所有七段数码光驱动管显示函数
staticvoidUpdateled(structseg*seg_7)
{
unsignedshortbuff=0x00;
buff=seg_7->LED1_Val;
buff=buff|(seg_7->LED2_Val<<8);
writew(buff,CS1_Address);
buff=0x00;
buff=seg_7->LED3_Val;
buff=buff|(seg_7->LED4_Val<<8);
writew(buff,CS2_Address);
return;
}
(3)写具体某位七段数码光驱动管显示函数
voidvalue_seting(structseg*seg_7,charposition,charvalue)
{
if(seg_7->negative==0)
value=~value&~(0x1<<7);
else
value=(0x1<<7)|value;
if(position==1)
seg_7->LED1_Val=value;
elseif(position==2)
seg_7->LED2_Val=value;
elseif(position==3)
seg_7->LED3_Val=value;
elseif(position==4)
seg_7->LED4_Val=value;
}
(4)实现七段数码光驱动写操作函数
staticssize_tXSB_Seg_write(structfile*file,constchar*buffer,size_tcount,loff_t*ppos)
{
inti;
structseg*seg_7=file->private_data;
charled_forall[4];
printk(KERN_EMERG"TheModuleiswritten,XSB_Seg_write\n");
if(count!
=4)
{
printk(KERN_EMERG"thecountofinputisnot4!
!
");
return0;
}
if(copy_from_user(led_forall,buffer,4))
{
for(i=1;i<=4;i++)
{
value_seting(seg_7,i,LED[led_forall[i-1]]);
}
Updateled(seg_7);
}
return0;
}
(5)实现七段数码管驱动IOCTL操作函数
staticintXSB_Seg_ioctl(structinode*ip,structfile*fp,unsignedintcmd,unsignedlongarg)
{
charval=0x00;
structseg*seg_7=fp->private_data;
if(!
arg)
return-EINVAL;
if(copy_from_user(&val,(int*)arg,sizeof(char)))
return-EFAULT;
switch(cmd){
case1:
value_seting(seg_7,1,val);
break;
case2:
value_seting(seg_7,2,val);
break;
case3:
value_seting(seg_7,3,val);
break;
case4:
value_seting(seg_7,4,val);
break;
case0:
seg_7->negative=LED_MODULE;
break;
default:
printk(KERN_EMERG"ioctlparametererror,pleaseinputnumber0-4");
break;
}
Updateled(seg_7);
return0;
}
(6)实现七段数码管驱动打开操作函数
staticintXSB_Seg_open(structinode*inode,structfile*filp)
{
structseg*seg_7;
printk(KERN_EMERG"TheModuleisopen,XSB_Seg_open\n");
seg_7=kmalloc(sizeof(structseg),GFP_KERNEL);
filp->private_data=seg_7;
return0;
}
(7)实现七段数码管驱动释放函数
staticintXSB_Seg_release(structinode*inode,structfile*filp)
{
printk(KERN_EMERG"TheModuleisrelease,XSB_Seg_release\n");
kfree(filp->private_data);
return0;
}
(8)七段数码管驱动文件结构体定义
staticstructfile_operationsEmdoor_fops={
open:
XSB_Seg_open,
write:
XSB_Seg_write,
release:
XSB_Seg_release,
ioctl:
XSB_Seg_ioctl,
owner:
THIS_MODULE,
};
(9)实现七段数码管驱动初始化函数
staticint__initXSB_Seg_init(void)
{
intret;
printk(KERN_EMERG"TheModuleisInit,XSB_Seg_init\n");
CS1_Address=ioremap(SEG_CS1,4);
CS2_Address=ioremap(SEG_CS2,4);
ret=register_chrdev(61,DEVICE_NAME,&Emdoor_fops);
if(ret<0){
printk(DEVICE_NAME"can'tgetmajornumber\n");
returnret;
}
return0;
}
(10)实现七段数码管驱动模块退出函数与模块描述
staticvoid__exitXSB_Seg_exit(void)
{
printk(KERN_EMERG"TheModuleisExit,XSB_Seg_exit\n");
iounmap(CS1_Address);
iounmap(CS2_Address);
unregister_chrdev(61,DEVICE_NAME);
}
module_init(XSB_Seg_init);
module_exit(XSB_Seg_exit);
MODULE_AUTHOR("Ben.li,ben.li@");
MODULE_DESCRIPTION("Thisisa8SegmentLeddriverdemo");
2,编写用于编译xsb_seg.c驱动架构Makefile文件
#Makefileforthe8Segment_LedDriver.#
CFLAGS+=$(DEBFLAGS)-Wall
ifneq($(KERNELRELEASE),)
obj-m:
=xsb_seg.o
else
KERNELDIR?
=~/useful/linux-2.6.22.10
PWD:
=$(shellpwd)
ALL:
$(MAKE)$(CFLAGS)-C$(KERNELDIR)M=$(PWD)modules
endif
clean:
rm–fr*.o*.ko*~core.depend.*.cmd*.mod.c.tmp_versions
3,运行Make命令编译驱动,用ls命令查看编译后的结果,在该目录中应该生成xsb_seg.ko模块文件,利用file命令查看xsb_seg.ko文件的格式,应为ARM格式的ELF文件。
ustb@ustb-desktop:
~/workspace/driver$sudomake
4,编写用于测试驱动的程序代码(见seg_test.c文件);
/************************************************
*************************************************/
#include
#include
#include
#include
typedefunsignedcharu8;
#defineSEG_DEV"/dev/xsb_seg"
charnumber[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,0x6F};
voidclear_led(intfd)
{
inti;
charval=0;
for(i=1;i<=4;i++)
ioctl(fd,i,&val);
sleep
(1);
}
voiddisplay_led(intfd)
{
inti;
charval=0x7f;
for(i=1;i<=4;i++)
ioctl(fd,i,&val);
sleep
(1);
}
voidappear_same(intfd)
{
chari,j,base=0;
for(j=0,base=0;j<=9;j++,base++){
for(i=1;i<=4;i++)
ioctl(fd,i,number+base);
sleep
(1);
}
}
voidappear_roll(intfd)
{
chari,j,base=0;
for(j=0,base=0;j<=9;j++,base++){
for(i=1;i<=4;i++)
ioctl(fd,i,number+(base+i-1)%10);
sleep
(1);
}
}
voiddisplay_menu()
{
printf("*****ChoiceMenu*********\n");
printf("[0]OpenDevice\n");
printf("[1]DisplaySame\n");
printf("[2]RollDisplay\n");
printf("[3]AllDisplay\n");
printf("[4]ClearDisplay\n");
printf("[5]WriteDisplay\n");
printf("[C]CloseDevice\n");
printf("[x]ExitTest\n");
printf("***********************\n");
printf("Pleaseinputyourchoise:
");
}
intmain(intargc,char**argv)
{
intfd=-1;
charch=0x00;
unsignedcharled[4]={2,0,0,8};
display_menu();
while
(1){
ch=getchar();
switch(ch)
{
case'0':
if(fd>0)
printf("##SEGDevicehasbeenopen##%d\n",fd);
else{
fd=open(SEG_DEV,O_RDWR);
if(fd<0)
printf("####SEGDeviceopenFail####\n");
else
printf("####SEGDeviceopenSuccess####%d\n",fd);
}
display_menu();
break;
case'1':
if(fd>0){
appear_same(fd);
clear_led(fd);
}
else
printf("##SEGDeviceisNOTopen##\n");
display_menu();
break;
case'2':
if(fd>0){
appear_roll(fd);
clear_led(fd);
}
else
printf("##SEGDeviceisNOTopen##\n");
display_menu();
break;
case'3':
if(fd>0)
display_led(fd);
else
printf("##SEGDeviceisNOTopen##\n");
display_menu();
break;
case'4':
if(fd>0)
clear_led(fd);
else
printf("##SEGDeviceisNOTopen##\n");
display_menu();
break;
case'5':
if(fd>0)
write(fd,led,4);
else
printf("##SEGDeviceisNOTopen##\n");
display_menu();
break;
case'c':
case'C':
if(fd>0){
clear_led(fd);
sleep
(1);
close(fd);
printf("##SEGDeviceisclosedsuccess##\n");
fd=-1;
}
display_menu();
break;
case'x':
case'X':
if(fd>0){
clear_led(fd);
sleep
(1);
close(fd);
}
exit(0);
break;
}
}
return(0);
}
5,编写一个用于编译seg_test.c的Makefile文件;其中CC=/opt/arm-linux-4.2.1/bin/arm-linux-gcc为交叉编译工具所在的路径位置,INCLUDEDIR=/opt/arm-linux-4.2.1/arm-linux/include为头文件所在的路径
CC=/opt/arm-linux-4.2.1/bin/arm-linux-gcc
INCLUDEDIR=/opt/arm-linux-4.2.1/arm-linux/include
CFLAGS=-I..-I$(INCLUDEDIR)
TARGET_TEST=seg_test
OBJ_TEST=$(TARGET_TEST)
SOURCE_TEST=$(TARGET_TEST).c
ALL:
$(CC)$(CFLAGS)-o$(OBJ_TEST)$(SOURCE_TEST)
clean:
rm-rf$(OBJ_TEST)
注:
上述五步骤所需代码可从实验目录中拷贝到工作区。
ustb@ustb-desktop:
~$sudocp-fr/mnt/hgfs/sysc/lab5/driver/~/workspace/
ustb@ustb-desktop:
~$sudocp-fr/mnt/hgfs/sysc/lab5/test/~/workspace/
6,用make命令对seg_test.c进行编译,编译后应该会生成一个名为seg_test的文件,利用file命令查看seg_test文件格式,应为ARM格式的ELF文件。
ustb@ustb-desktop:
~/workspace/test$sudomake
7,配置内核,在内核源代码根目录/home/ustb/useful/linux-2.6.22.10运行makemenuconfig命令,进入Loadablemodulesupport选项,选上Enableloadablemodulesuport和module_unloading,然后退出,运行makezImage编译内核。
8,将编译好的内核映像zImage和光盘提供的文件系统下载。
9,在minicom终端下,用串口传输方式将编译好的驱动模块xsb_seg.ko和测试驱动的程序seg_test下载到实验箱上;
10,在目标平台终端利用利用insmod命令动态加载驱动模块,然后运行cat/proc/devices命令查看设备号,并用mknod命令建立设备文件节点,然后利用lsmod命令查看驱动模块的加载情况;
11,在目标平台终端运行八段数码驱动测试程序seg_test,在平台终端将显示驱动测试程序菜单。
12,在平台终端显示驱动测试程序菜单输入提示输入数字“0”。
驱动测试程序将通过open函数打开设备文件,同时内核调用驱动程序的xxx_open函数,在平台终端可以查看驱动和测试程序调试输出信息。
如上图。
13,在平台终端显示驱动测试程序菜单输入提示分别输入数字“1”、“2”、“3”、“4”,查看平台4个7段数码管的显示情况,并分析测试程序通过调用什么函数与驱动进行通信?
14,在平台终端显示驱动测试程序菜单输入提示分别输入数字“5”、查看平台4个7段数码管的显示情况,并分析测试程序通过调用什么函数与驱动进行通信?
15,在平台终端显示驱动测试程序菜单输入提示分别英文字符“C”或“c”,然后再输入“1~5”任何数字,查看测试程序的输出情况,并分析测试程序通过调用什么函数与驱动进行通信?
16,在平台终端显示驱动测试程序菜单输入提示分别英文字符“X”或“x”,退出测试程序。
17,在平台终端输入dmesg命令,查看驱动程序在加载和测试过程中输出消息,并分析驱动代码,查看输出信息。
用直接编译进内核的方式加载LED灯驱动:
1,利用vi编辑器或者gedit编写驱动代码(见/mnt/hgfs/sysc/lab5/driver/xsb_led.c文件);
(1)增加驱动所需的头文件和变量
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineDEVICE_NAME"xsb_Led"
#defineSEG_LED0x10500000
#defineLed_MAJOR60
staticcharLed_Buff=0x0;
unsignedlong*Led_Address;
(2)控制LED点亮函数
staticvoidUpdateled(void)
{
writew(Led_Buff,Led_Address);
return;
}
(3)实现LED驱动写操作函数
staticssize_tLed_write(structfile*file,constchar*buffer,size_tcount,loff_t*ppos)
{
if(count!
=1)
{
printk(KERN_EMERG"thecountofinputisnotone!
!
");
return0;
}
copy_from_user(&Led_Buff,buffer,1);
Updateled();
return1;
}
(4)实现LED驱动的打开、释放函数以及文件操作结构体
staticintLed_open(structinode*inode,structfile
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式实验 IO drivers 嵌入式 实验