驱动的MAKEFILE编写报告文档格式.docx

上传人:b****4 文档编号:16501615 上传时间:2022-11-24 格式:DOCX 页数:17 大小:110.80KB
下载 相关 举报
驱动的MAKEFILE编写报告文档格式.docx_第1页
第1页 / 共17页
驱动的MAKEFILE编写报告文档格式.docx_第2页
第2页 / 共17页
驱动的MAKEFILE编写报告文档格式.docx_第3页
第3页 / 共17页
驱动的MAKEFILE编写报告文档格式.docx_第4页
第4页 / 共17页
驱动的MAKEFILE编写报告文档格式.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

驱动的MAKEFILE编写报告文档格式.docx

《驱动的MAKEFILE编写报告文档格式.docx》由会员分享,可在线阅读,更多相关《驱动的MAKEFILE编写报告文档格式.docx(17页珍藏版)》请在冰豆网上搜索。

驱动的MAKEFILE编写报告文档格式.docx

2、IO驱动程序和测试程序的编写和下载

(1)、利用vi编辑器,编写一个用于编译xsb_seg.c驱动架构Makefile文件见附录IIMakefile1,运行make编译命令,用ls命令查看编译后的结果,在该目录中应生成xsb_seg.ko模块文件,利用file命令查看xsb_seg.ko文件的格式,应为ARM格式的ELF文件。

(2)、利用vi编辑器,编写一个用于编译IO_test.c驱动架构Makefile文件见附录二Makefile2,其中CC=/usr/local/arm/xscalev1/bin/arm-linux-gcc就是交叉编译工具xscalev1所在路径位置,INCLUDEDIR=/usr/local/arm/xscalev1/arm-linux/include为头文件所在的路径;

运行make命令对IO_test.c源代码进行编译,用ls命令查看编译后的结果,利用file命令查看IO_test文件的格式,应为ARM格式的ELF文件。

(3)、在Linux操作系统下输入minicom,配置串口参数,然后打开EELiod目标平台电源,平台启动后,按CTRL+A,然后按Z,启动串口命令界面,按S键,选择zmodem传输方式;

按回车;

选择PC平台中驱动模块文件xsb_seg.ko和驱动测试文件IO_test,并按回车键。

下载选中的文件,文件下载完毕后按ESC键,退出串口传输,返回目标平台界面。

在目标平台终端利用mknod命令建立设备文件节点;

并利用insmod命令动态加载驱动模块,同时利用lsmod命令查看驱动模块的加载情况。

(4)、在目标平台终端运行八段数码驱动测试程序IO_test,输入命令./IO_test,在平台终端将显示驱动测试程序菜单。

分别输入0、1、2、3、4、5、c、x观察实验箱4位数码管的现象,显然输入1,数码管显示0000-9999;

输入2,数码管显示0123-9012;

输入3,数码管显示8888;

输入4,数码管清0;

输入5,可以从键盘输入数据;

输入c,设备关闭;

输入x,退出。

三、【Makefile文件分析】

1、驱动程序xsb_seg.c的Makefile文件

#Makefileforthe8Segment_LedDriver.#

CFLAGS+=$(DEBFLAGS)–Wall//隐含规则中的变量

ifneq($(KERNELRELEASE),)//如果KERNELRELEASE宏被定义

obj-m:

=xsb_seg.o//生成目标文件

else//如果KERNELRELEASE没有被定义

KERNELDIR?

=/exam/linux-2.6.22.10//内核文件所在目录

PWD:

=$(shellpwd)//驱动程序xsb_seg.c所在目录

ALL:

//以KERNELDIR目录下的内核为基础,编译PWD目录下的驱动程序

$(MAKE)$(CFLAGS)-C$(KERNELDIR)M=$(PWD)modules

endif

clean:

//删除生成的中间文件

rm–fr*.o*.ko*~core.depend.*.cmd*.mod.c.tmp_versions

2、测试程序IO-test.c的Makefile文件

CC=/usr/local/arm/xscalev1/bin/arm-linux-gcc//交叉编译工具目录

INCLUDEDIR=/usr/local/arm/xscalev1/arm-linux/include//头文件目录

CFLAGS=-I..-I$(INCLUDEDIR)//隐含规则变量

TARGET_TEST=led_test

OBJ_TEST=$(TARGET_TEST)

SOURCE_TEST=$(TARGET_TEST).c

//执行OBJ_TEST目录下的SOURCE_TEST程序

$(CC)$(CFLAGS)-o$(OBJ_TEST)$(SOURCE_TEST)

rm-rf$(OBJ_TEST)

四、【驱动程序分析】

我们对驱动程序分几个模块进行分析:

1、模块初始化和驱动初始化:

模块初始化module_init(XSB_Seg_init)函数中的参数XSB_Seg_init实际上为数码管显示驱动模块的初始化函数staticint__initXSB_Seg_init(void),该函数主要完成将产生数码显示的片选控制信号的BA22~BA20通过void*ioremap(unsignedlongoffset,unsignedlongsize)函数为I/O内存区域分配虚拟地址,这样设备驱动程序就能访问I/O内存地址。

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;

}

2、模块的卸载:

模块的卸载module_exit(XSB_Seg_exit)函数中参数XSB_Seg_exit实际上是模块的从内核卸载时所调用的staticvoid__exitXSB_Seg_exit(void);

设备在卸载时需要回收相应的资源,并利用unregister_chrdev()函数从内核中将设备注销。

staticvoid__exitXSB_Seg_exit(void)

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"

3、同时更新所有七段数码光驱动管显示函数//参见附录I

staticvoidUpdateled(structseg*seg_7)

4、写具体某位七段数码光驱动管显示函数//参见附录I

voidvalue_seting(structseg*seg_7,charposition,charvalue)

5、实现七段数码光驱动写操作函数//参见附录I

staticssize_tXSB_Seg_write(structfile*file,constchar*buffer,size_tcount,loff_t*ppos)

6、实现七段数码管驱动IOCTL操作函数//参见附录I

staticintXSB_Seg_ioctl(structinode*ip,structfile*fp,unsignedintcmd,unsignedlongarg)

7、实现七段数码管驱动打开操作函数//参见附录I

staticintXSB_Seg_open(structinode*inode,structfile*filp)

8、实现七段数码管驱动释放函数//参见附录I

staticintXSB_Seg_release(structinode*inode,structfile*filp)

9、七段数码管驱动文件结构体定义//参见附录I

staticstructfile_operationsEmdoor_fops

五、总结

通过本次实验我了解了关于设备驱动的动态加载过程,设备驱动在加载时首先调用入口函数init_module(),该函数完成设备驱动的初始化工作,比如寄存器置位、结构体赋值等一系列工作,其中最重要的一个工作就是向内核注册该设备,对于字符设备调用register_chrdev()完成注册,对于块设备需要调用register_blkdev()完成注册。

注册成功后,该设备获得了系统分配的主设备号、自定义的次设备号,并建立起于文件系统的关联。

设备在卸载时需要回收相应的资源,令设备的响应寄存器复位并从系统中注销该设备,字符设备调用unregister_chrdev()、块设备调用unregister_blkdev()。

系统调用部分则是对设备的操作过程,比如open、read、write、ioctl等。

设备驱动程序负责将应用程序如读、写等操作正确无误的传递给相关的硬件,并使硬件能够做出正确反应的代码,因此在编写设备驱动程序时,必须要了解相应的硬件设备的寄存器、IO口及内存的配置参数。

此外,我还学会了编写驱动程序和测试程序的Makefile文件,并可以成功的下载到实验箱上,实现功能。

 

附录Ⅰ(驱动程序代码):

#include<

linux/module.h>

linux/kernel.h>

asm/io.h>

asm/uaccess.h>

linux/fs.h>

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;

};

staticvoidUpdateled(structseg*seg_7)

unsignedshortbuff=0x00;

buff=seg_7->

LED1_Val;

buff=buff|(seg_7->

LED2_Val<

<

8);

writew(buff,CS1_Address);

buff=0x00;

LED3_Val;

LED4_Val<

writew(buff,CS2_Address);

return;

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)

LED2_Val=value;

elseif(position==3)

LED3_Val=value;

elseif(position==4)

LED4_Val=value;

inti;

structseg*seg_7=file->

private_data;

charled_forall[4];

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);

charval=0x00;

structseg*seg_7=fp->

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);

case3:

value_seting(seg_7,3,val);

case4:

value_seting(seg_7,4,val);

case0:

seg_7->

negative=LED_MODULE;

default:

printk(KERN_EMERG"

ioctlparameterinputerror,pleaseinputnumber0-4"

Updateled(seg_7);

structseg*seg_7;

TheModuleisopen,XSB_Seg_open\n"

seg_7=kmalloc(sizeof(structseg),GFP_KERNEL);

//在内核空间分配内存

seg_7->

negative=LED_MODULE;

filp->

private_data=seg_7;

TheModuleisrelease,XSB_Seg_release\n"

kfree(filp->

private_data);

staticstructfile_operationsEmdoor_fops={

open:

XSB_Seg_open,

write:

XSB_Seg_write,

release:

XSB_Seg_release,

ioctl:

XSB_Seg_ioctl,

owner:

THIS_MODULE,

staticvoid__exitXSB_Seg_exit(void)

附录Ⅱ(Makefile代码):

Makefile1

#Makefilefortheemdoor8segdriver.#

CFLAGS+=$(DEBFLAGS)-Wall

ifneq($(KERNELRELEASE),)

obj-m:

=xsb_seg.o

else

KERNELDIR?

=/exam/linux-2.6.22.10

PWD:

=$(shellpwd)

$(MAKE)$(CFLAGS)-C$(KERNELDIR)M=$(PWD)modules

rm-fr*.o*.ko*~core.depend.*.cmd*.mod.c.tmp_versions

Makefile2

CC=/usr/local/arm/xscalev1/bin/arm-linux-gcc

INCLUDEDIR=/usr/local/arm/xscalev1/arm-linux/include

CFLAGS=-I..-I$(INCLUDEDIR)

TARGET_TEST=IO_test

$(CC)$(CFLAGS)-o$(OBJ_TEST)$(SOURCE_TEST)

rm-rf$(OBJ_TEST)

附录Ⅲ(测试程序代码):

stdio.h>

fcntl.h>

unistd.h>

typedefunsignedcharu8;

#defineSEG_DEV"

/dev/xsb_seg"

charnumber[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,0x6F};

voidclear_led(intfd)

charval=0;

for(i=1;

ioctl(fd,i,&

val);

sleep

(1);

voiddisplay_led(intfd)

charval=0x7f;

voidappear_same(intfd)

chari,j,base=0;

for(j=0,base=0;

j<

=9;

j++,base++)

{

i<

i++)

ioctl(fd,i,number+base);

voidappear_roll(intfd)

chari,j,base=0;

for(j=0

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1