当前位置:文档之家› 嵌入式Linux应用程序开发实验报告期末作业

嵌入式Linux应用程序开发实验报告期末作业

软件学院大作业设计报告课程名称:题目:专业:班级:姓名学号:基于UP-CUP2440平台的驱动程序开发和QT程序开发计算机软件计算机软件111班鲁飞8000611038 卢惠民8000611021 戚成林8000611032 慕一聪8000611018 刘备8000611006李岚职称:副教授2014年6月11日嵌入式Linux应用程序开发任课教师: 完成时间:一、小组成员分工二、实验任务三、主要仪器设备及耗材四、实验步骤、驱动1. 基本知识:2. 实验原理:3. 具体实现:二、QT计算器1.QT程序设计2. 虚拟机下进行编译:3. 下载到开发板上运行:六、实验数据及处理结果10 151718七、思考讨论题或体会或对改进实验的建议1819八、参考资料:、小组成员分工分工:鲁飞:QT设计与设计报告卢惠民:QT设计与设计报告戚成琳:驱动与设计报告慕一聪、刘备:设计报告二、实验任务1•编写基于UP-CUP2440硬件平台的GPIO驱动程序必选功能:使中断按键按下后,开发板上的LED灯能作如下闪动:a)连续性闪动,跑马灯:如:1-2-3-1-2-3…或3-2-1-3-2-1b)间隔性闪动:如:1-3-2-1-3-2…或3-1-2-3-1-2…进阶功能:改变中断按键的控制功能,使中断按键按下后,LED灯不断闪亮,再次按下后,LED灯灭。

2.QT计算器三、主要仪器设备及耗材PC, Windows Xp , H-JTAG,H-Flasher,DNW,开发实验箱。

四、实验步骤、驱动思路:前后台思想:在中断模块中设置一个计数的变量,每一次中断计数器加一。

然后在GP10驱动模块的ioctIO函数中分情况使跑马灯按要求闪动或熄灭。

1. 基本知识:(3)(4)间的关联。

(5)打开设备和释放设备,没什么要特别注意的。

(6)读写设备:把内核空间的数据复制到用户空间去,或者从用户空间复制到内核空间。

read()里面使用copy_to_user()就可以将内核空间的值传到用户空间去。

这一点在本实验的驱动程序的实现中起着至关重要的作用。

(7)ioctl()则是对10寄存器的控制,在本实验中就要用ioctl()来实现不同的跑马灯亮灭。

2. 实验原理:UP-「liP2轴】开发平3个【iPM】悴制的l.HD.和I个町白搖产乍外帑砸件中啊的技犍・LEU 井别惶用S3C24HySJC2440 (JPLS GPLb, GPC7 (PXA27O 的<jPKXb GPIOI. GPIO?2)三亍GPIO,按卷接判TMT3中断£卩心2和的GPIO97 >Titf10Regilbr Adcfrwt R/用OaicrvtiQn A«t«t VilwaGPCCON Q«56000020FVW S'lgwM lhe pins of CKjrtC iQjiOGPCDAT it50OOOO£-i R/W fne dalfl reg ster fty nqrt C Uhdert,GPCJP Q>i5a0G002B R/W Pull-J p diMtrtr iifugaler feir pad C moBEservod脚500000比———GPC7[15:14]00 = Input10 = LCD'LPCREVB 01 = Output 11 = ReservedGPC6[13:12]00 = Input10 = LCD LPCREV 01 = Output 11 = Reserved[11:10]00 = Input10 = LCD_LPCOE 01 = Output 11 = Reserved设备驱动程序可以使用模块的方式动态加载到内核中去。

模块的必需组成部分:模块加载函数,insmod时调用。

模块卸载函数,rmmod时调用模块许可证LICENSE说明数据结构file_operation 中定义驱动程序会使用的函数。

在获得了系统分配的设备号之后,必须要通过注册才能实现设备号和驱动程序之Q'fllIfU Q3. 具体实现:(一)中断驱动模块:该模块只需在老师给的实例的基础上加以修改就行。

(1)模块初始化函数中,请求中断处理函数:ret = request_irq(S3C2440_IRQ5, s3c2440_IRQ3_fu n, SA_INTERRU PT,"S3C2440_IRQ5", NULL);中断处理函数为:s3c2440_IRQ3_fu n()在此中断处理函数中,用一个全局变量cou nt在每一次中断的时候加1,由于我们的开发板按一次会处理两次,所以计数到7的时候,必须使count恢复到1。

具体实现如下:int coun t=0;irqreturn_t s3c2440_IRQ3_fu n (int irq, void *dev_id, struct pt_regs *reg){prin tk("e nter interrupt 5 !\n ”);coun t++;if(co un t==7)coun t=1;}(2)设备初始化:static int __init s3c2440_interrupt_in it(void){in t ret; int flags; local_irq_save(flags);// by sprifes3c2410_g pio_cfgpin( S3C2410_G PF5, S3C2410_G PF 5_EINT5);s3c2410_g pio_pullu p(S3C2410_G PF5,1);// endset_irq_ty pe(S3C2440_IRQ5,/*IRQT_FALLING*/IRQT_LOW);local_irq_restore(flags);ret = request_irq(S3C2440_IRQ5, s3c2440_IRQ3_fu n, SA_INTERRU PT,"S3C2440_IRQ5", NULL); if (ret){printk("S3C2440_IRQ5 request_irq failure");return ret;} printk(DEVICE_NAME " int05 initialized\n"); return 0;3)设备退出:static void __exit s3c2440_interrupt_exit(void){ free_irq(S3C2440_IRQ5,NULL); printk(DEVICE_NAME " unloaded\n");}module」nit ()注册设备module_exit ()卸载设备还有LICENSE 必须要设置:( 4)( 5)( 6)MODULE_LICENSE("GPL");本模块最需要注意的地方:因为count 是要导出给其他模块用的,所以必须使用EXPORT_SYMBOL_GPL(count);这就是我出错的地方之一。

(二)GPIO 驱动:( 1)结构体file_operation 的定义:struct file_operations gpio_fops = {.owner = THIS_MODULE,.open = gpio_open, .ioctl = gpio_ioctl, .read = gpio_read, .release = gpio_release, };( 2) GPIO 的模块加载部分:必须完成字符设备的注册。

需要调用gpio_setup_cdev(),该函数用于字符设备的创建和注册函数。

首先要定义结构体变量:static struct cdev gpio_cdev;该函数的具体实现:static void gpio_setup_cdev(struct cdev *dev, int minor, struct file_operations *fops) { int err, devno = MKDEV(major, minor); cdev_init(dev, fops);dev->owner = THIS_MODULE;dev->ops = fops;err = cdev_add(dev, devno, 1); if(err) {printk(KERN_NOTICE "Error %d adding gpio %d", err, minor);}}( 3) int gpio_open(struct inode *inode, struct file *filp) 打开设备时,就要设置 GPIO 口的电平。

设置相应的 GPIO 口为输出模式。

具体代码如下:int gpio_open(struct inode *inode, struct file *filp){s3c2410_gpio_pullup(S3C2410_GPC5, 0);s3c2410_gpio_pullup(S3C2410_GPC6, 0); s3c2410_gpio_pullup(S3C2410_GPC7, 0);s3c2410_gpio_cfgpin(S3C2410_GPC5, S3C2410_GPC5_OUTP); s3c2410_gpio_cfgpin(S3C2410_GPC6, S3C2410_GPC6_OUTP); s3c2410_gpio_cfgpin(S3C2410_GPC7, S3C2410_GPC7_OUTP); return 0;}( 4) ssize_t s3c240_gpio_read(struct file *filp, char *buf, size_t cnt, loff_t *f_pos) 该函数要将count 值传到用户空间去,在用户空间里调用ioctl()函数时就需要count 值。

具体实现: ssize_t s3c240_gpio_read(struct file *filp, char *buf, size_t cnt, loff_t *f_pos) {int err;if(err = put_user(count, buf) < 0) return err; return cnt;}(5)接下来就是实现跑马灯控制的ioctl() 了, 如果count 为1时, 如果count 为3时, 如果count 为5时, 具体代码实现如下:int gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {switch(count){case 1:s3c2410_gpio_pullup(S3C2410_GPC5, 0); s3c2410_gpio_pullup(S3C2410_GPC6, 1); s3c2410_gpio_pullup(S3C2410_GPC7, 1); mdelay(200);s3c2410_gpio_pullup(S3C2410_GPC5, 1); s3c2410_gpio_pullup(S3C2410_GPC6, 0); s3c2410_gpio_pullup(S3C2410_GPC7, 1); mdelay(200);s3c2410_gpio_pullup(S3C2410_GPC5, 1); s3c2410_gpio_pullup(S3C2410_GPC6, 1); s3c2410_gpio_pullup(S3C2410_GPC7, 0); break;则实现按 1,2,3 顺序不断亮灭。

相关主题