1、 2、IO驱动程序和测试程序的编写和下载(1)、利用vi编辑器,编写一个用于编译xsb_seg.c驱动架构Makefile文件见附录II Makefile1,运行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所在路径位置,INCLUD
2、EDIR=/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键,退出
3、串口传输,返回目标平台界面。在目标平台终端利用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
4、.c的Makefile文件 # Makefile for the 8Segment_Led Driver. #CFLAGS +=$(DEBFLAGS) Wall /隐含规则中的变量ifneq ($(KERNELRELEASE),) / 如果KERNELRELEASE宏被定义 obj-m :=xsb_seg.o /生成目标文件else/如果KERNELRELEASE没有被定义 KERNELDIR ?=/exam/linux-2.6.22.10 /内核文件所在目录 PWD :=$(shell pwd) /驱动程序xsb_seg.c所在目录ALL: /以KERNELDIR目录下的内核为基础,编译PW
5、D目录下的驱动程序 $(MAKE) $(CFLAGS) -C $(KERNELDIR) M=$(PWD) modulesendifclean: /删除生成的中间文件 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$
6、(INCLUDEDIR) /隐含规则变量TARGET_TEST=led_testOBJ_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实际上为数码管显示驱动模块的初始化函数st
7、atic int _init XSB_Seg_init(void),该函数主要完成将产生数码显示的片选控制信号的BA22BA20通过void * ioremap(unsigned long offset, unsigned long size)函数为I/O内存区域分配虚拟地址,这样设备驱动程序就能访问I/O内存地址。static int _init XSB_Seg_init(void) int ret; printk(KERN_EMERG The Module is Init,XSB_Seg_initn); CS1_Address=ioremap(SEG_CS1, 4); CS2_Addres
8、s=ioremap(SEG_CS2, 4); ret = register_chrdev(61, DEVICE_NAME, &Emdoor_fops); if (ret 0) printk(DEVICE_NAME cant get major numbern return ret; return 0; 2、模块的卸载:模块的卸载module_exit(XSB_Seg_exit)函数中参数XSB_Seg_exit实际上是模块的从内核卸载时所调用的static void _exit XSB_Seg_exit(void);设备在卸载时需要回收相应的资源,并利用unregister_chrdev()函
9、数从内核中将设备注销。 static void _exit XSB_Seg_exit(void)The Module is Exit,XSB_Seg_exitn 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.liMODULE_DESCRIPTION(This is a 8 Segment Led driver demo3、同时更新
10、所有七段数码光驱动管显示函数/参见附录Istatic void Updateled(struct seg *seg_7) 4、写具体某位七段数码光驱动管显示函数/参见附录Ivoid value_seting(struct seg *seg_7, char position, char value) 5、实现七段数码光驱动写操作函数/参见附录Istatic ssize_t XSB_Seg_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)6、实现七段数码管驱动IOCTL操作函数/参见附录Istatic
11、 int XSB_Seg_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)7、实现七段数码管驱动打开操作函数/参见附录Istatic int XSB_Seg_open(struct inode *inode, struct file *filp)8、实现七段数码管驱动释放函数/参见附录Istatic int XSB_Seg_release(struct inode *inode, struct file *filp)9、七段数码管驱动文件结构体定义/参见附录Istatic struct f
12、ile_operations Emdoor_fops 五、总结 通过本次实验我了解了关于设备驱动的动态加载过程,设备驱动在加载时首先调用入口函数init_module(),该函数完成设备驱动的初始化工作,比如寄存器置位、结构体赋值等一系列工作,其中最重要的一个工作就是向内核注册该设备,对于字符设备调用register_chrdev()完成注册,对于块设备需要调用register_blkdev()完成注册。注册成功后,该设备获得了系统分配的主设备号、自定义的次设备号,并建立起于文件系统的关联。设备在卸载时需要回收相应的资源,令设备的响应寄存器复位并从系统中注销该设备,字符设备调用unregist
13、er_chrdev()、块设备调用unregister_blkdev()。系统调用部分则是对设备的操作过程,比如open、read、write、ioctl等。设备驱动程序负责将应用程序如读、写等操作正确无误的传递给相关的硬件,并使硬件能够做出正确反应的代码,因此在编写设备驱动程序时,必须要了解相应的硬件设备的寄存器、IO口及内存的配置参数。此外,我还学会了编写驱动程序和测试程序的Makefile文件,并可以成功的下载到实验箱上,实现功能。附录(驱动程序代码):#include linux/kernel.hasm/io.hasm/uaccess.hlinux/fs.hMODULE_LICENSE
14、(GPLchar LED_MODULE=0;#define DEVICE_NAME xsb_seg#define SEG_CS1 0x10300000 #define SEG_CS2 0x10400000 static char LED10=0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7F, 0x6F;unsigned long *CS1_Address, *CS2_Address;struct seg char LED1_Val; char LED2_Val; char LED3_Val; char LED4_Val; char neg
15、ative;static void Updateled(struct seg *seg_7) unsigned short buff=0x00; buff=seg_7-LED1_Val; buff=buff|( seg_7-LED2_Val 8); writew(buff,CS1_Address); buff=0x00;LED3_Val;LED4_Valnegative=0) value=value & (0x17); else value=(0x1LED1_Val=value; else if(position=2)LED2_Val=value; else if(position=3)LED
16、3_Val=value; else if(position=4)LED4_Val=value; int i; struct seg *seg_7=file-private_data; char led_forall4;The Module is written,XSB_Seg_writen if(count!=4) printk(KERN_EMERG the count of input is not 4! return 0; if(copy_from_user(led_forall, buffer, 4) for(i=1;i if (!arg) return -EINVAL; if (cop
17、y_from_user(&val, (int *)arg, sizeof(char) return -EFAULT; switch(cmd) case 1: value_seting(seg_7, 1, val); break; case 2: value_seting(seg_7, 2, val); case 3: value_seting(seg_7, 3, val); case 4: value_seting(seg_7, 4, val); case 0: seg_7-negative = LED_MODULE; default: printk(KERN_EMERGioctl param
18、eter input error,please input number 0-4 Updateled( seg_7 ); struct seg *seg_7;The Module is open,XSB_Seg_openn seg_7=kmalloc(sizeof(struct seg), GFP_KERNEL);/在内核空间分配内存 seg_7-negative=LED_MODULE; filp-private_data=seg_7;The Module is release,XSB_Seg_releasen kfree(filp-private_data);static struct fi
19、le_operations Emdoor_fops = open: XSB_Seg_open, write: XSB_Seg_write, release:XSB_Seg_release, ioctl: XSB_Seg_ioctl, owner: THIS_MODULE,static void _exit XSB_Seg_exit(void)附录(Makefile代码):Makefile1# Makefile for the emdoor 8 seg driver. #CFLAGS +=$(DEBFLAGS) -Wallifneq ($(KERNELRELEASE),) obj-m :=xsb
20、_seg.oelse KERNELDIR ?=/exam/linux-2.6.22.10 PWD :=$(shell pwd) $(MAKE) $(CFLAGS) -C $(KERNELDIR) M=$(PWD) modules rm -fr *.o *.ko * core .depend .*.cmd *.mod.c .tmp_versionsMakefile2CC = /usr/local/arm/xscalev1/bin/arm-linux-gccINCLUDEDIR = /usr/local/arm/xscalev1/arm-linux/includeCFLAGS = -I. -I$(
21、INCLUDEDIR)TARGET_TEST=IO_test $(CC) $(CFLAGS) -o $(OBJ_TEST) $(SOURCE_TEST) rm -rf $(OBJ_TEST)附录(测试程序代码):stdio.hfcntl.hunistd.htypedef unsigned char u8;#define SEG_DEV /dev/xsb_segchar number=0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7F, 0x6F;void clear_led(int fd) char val=0; for(i=1; ioctl(fd, i, &val); sleep(1);void display_led(int fd) char val=0x7f;void appear_same(int fd) char i,j,base=0; for (j=0, base=0 ;j=9; j+, base+) i i+) ioctl(fd, i, number+base);void appear_roll(int fd) char i, j, base=0; for (j=0
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1