分享

memdev驱动试验

 lchjczw 2012-12-12

memdev驱动试验 

     今天开始驱动的学习,根据国嵌驱动开发视频一边学习,一边试验。国嵌视频上首先讲述字符驱动开发过程,memdev就是最好的例子。首先在看懂源码的基础上学习怎么将驱动装载到开发板。下面是memdev源码:

[c-sharp] view plaincopy
  1. #ifndef _MEMDEV_H_  
  2. #define _MEMDEV_H_  
  3.  
  4. #ifndef MEMDEV_MAJOR  
  5. #define MEMDEV_MAJOR  260    
  6. //memdev采用静态分配设备号,不要和其它设备重复  
  7. #endif  
  8.  
  9. #ifndef MEMDEV_NR_DEVS  
  10. #define MEMDEV_NR_DEVS  2  
  11. #endif  
  12.  
  13. #ifndef MEMDEV_SIZE  
  14. #define MEMDEV_SIZE  4096  
  15. #endif  
  16.   
  17. struct mem_dev  
  18. {  
  19.     char *data;  
  20.     unsigned long size;  
  21. };  
  22.  
  23. #endif  

 

[c-sharp] view plaincopy
  1. /********************************************* 
  2. *memdev.c 
  3. *********************************************/  
  4. #include <linux/module.h>  
  5. #include <linux/types.h>  
  6. #include <linux/fs.h>  
  7. #include <linux/errno.h>  
  8. #include <linux/mm.h>  
  9. #include <linux/sched.h>  
  10. #include <linux/init.h>  
  11. #include <linux/cdev.h>  
  12. #include <asm/io.h>  
  13. #include <asm/system.h>  
  14. #include <asm/uaccess.h>  
  15.  
  16. #include "memdev.h"  
  17.   
  18. static int mem_major = MEMDEV_MAJOR;  
  19.   
  20. module_param(mem_major,int,S_IRUGO);  
  21.   
  22. struct mem_dev *mem_devp;  
  23.   
  24. struct cdev cdev;  
  25.   
  26. int mem_open(struct inode *inode,struct file *filp)  
  27. {  
  28.     struct mem_dev *dev;  
  29.       
  30.     int num = MINOR(inode->i_rdev);  
  31.       
  32.     if(num >=MEMDEV_NR_DEVS)  
  33.         return -ENODEV;  
  34.     dev = &mem_devp[num];  
  35.   
  36.     filp->private_data = dev;  
  37.   
  38.     return 0;  
  39. }  
  40.   
  41. int mem_release(struct inode *inode,struct file *filp)  
  42. {  
  43.     return 0;  
  44. }  
  45.   
  46. static ssize_t mem_read(struct file *filp,char __user *buf,size_t size,loff_t *poss)  
  47. {  
  48.     unsigned long p = *poss;  
  49.     unsigned int count = size;  
  50.     int ret = 0;  
  51.     struct mem_dev *dev = filp->private_data;  
  52.   
  53.     if(p >= MEMDEV_SIZE)  
  54.         return 0;  
  55.     if(count > MEMDEV_SIZE-p)  
  56.         count = MEMDEV_SIZE-p;  
  57.   
  58.     if(copy_to_user(buf,(void*)(dev->data+p),count))  
  59.     {  
  60.         ret = -EFAULT;  
  61.     }  
  62.     else  
  63.     {  
  64.         *poss +=count;  
  65.         ret = count;  
  66.         printk(KERN_INFO "read %d bytes from %lu/n",count,p);  
  67.     }  
  68.   
  69.     return ret;  
  70. }  
  71.   
  72. static ssize_t mem_write(struct file *filp,const char __user *buf,size_t size,loff_t *poss)  
  73. {  
  74.     unsigned long p = *poss;  
  75.     unsigned int count = size;  
  76.     int ret=0;  
  77.     struct mem_dev *dev = filp->private_data;  
  78.   
  79.     if(p>=MEMDEV_SIZE)  
  80.         return 0;  
  81.     if(count>MEMDEV_SIZE-p)  
  82.         count = MEMDEV_SIZE-p;  
  83.   
  84.     if(copy_from_user(dev->data+p,buf,count))  
  85.     {  
  86.         ret = -EFAULT;  
  87.     }  
  88.     else  
  89.     {  
  90.         *poss += count;  
  91.         ret = count;  
  92.         printk(KERN_INFO "write %d bytes from %lu/n",count,p);  
  93.     }  
  94.       
  95.     return ret;  
  96. }  
  97.   
  98. static loff_t mem_llseek(struct file *filp,loff_t offset,int whence)  
  99. {  
  100.     loff_t newpos;  
  101.       
  102.     switch(whence)  
  103.     {  
  104.         case 0:  
  105.             newpos = offset;  
  106.             break;  
  107.         case 1:  
  108.             newpos = filp->f_pos + offset;  
  109.             break;  
  110.         case 2:  
  111.             newpos = MEMDEV_SIZE - 1 + offset;  
  112.             break;  
  113.         default:  
  114.             return -EINVAL;  
  115.     }  
  116.     if((newpos<0) || (newpos>MEMDEV_SIZE))  
  117.         return -EINVAL;  
  118.   
  119.     filp->f_pos = newpos;  
  120.     return newpos;  
  121. }  
  122.   
  123. static const struct file_operations mem_fops =  
  124. {  
  125.     .owner = THIS_MODULE,  
  126.     .llseek = mem_llseek,  
  127.     .read = mem_read,  
  128.     .write = mem_write,  
  129.     .open = mem_open,  
  130.     .release = mem_release,  
  131. };  
  132.   
  133. static int memdev_init(void)  
  134. {  
  135.     int result;  
  136.     int i;  
  137.     dev_t devno = MKDEV(mem_major,0);  
  138.   
  139.     if(mem_major)  
  140.         result = register_chrdev_region(devno,2,"memdev");  
  141.     else  
  142.     {  
  143.         result = alloc_chrdev_region(&devno,0,2,"memdev");  
  144.         mem_major = MAJOR(devno);  
  145.     }  
  146.   
  147.     if(result < 0)  
  148.         return result;  
  149.       
  150.     cdev_init(&cdev,&mem_fops);  
  151.     cdev.owner = THIS_MODULE;  
  152.     cdev.ops = &mem_fops;  
  153.   
  154.     cdev_add(&cdev,MKDEV(mem_major,0),MEMDEV_NR_DEVS);  
  155.   
  156.     mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev),GFP_KERNEL);  
  157.     if(!mem_devp)  
  158.     {  
  159.         result = -ENOMEM;  
  160.         goto fail_malloc;  
  161.     }  
  162.       
  163.     memset(mem_devp,0,MEMDEV_NR_DEVS * sizeof(struct mem_dev));  
  164.   
  165.     for(i=0;i<MEMDEV_NR_DEVS;i++)  
  166.     {  
  167.         mem_devp[i].size = MEMDEV_SIZE;  
  168.         mem_devp[i].data = kmalloc(MEMDEV_SIZE,GFP_KERNEL);  
  169.         memset(mem_devp[i].data,0,MEMDEV_SIZE);  
  170.     }  
  171.   
  172.     return 0;  
  173.   
  174. fail_malloc:  
  175.     unregister_chrdev_region(devno,2);  
  176.     return result;  
  177. }  
  178.   
  179. static void memdev_exit(void)  
  180. {  
  181.     cdev_del(&cdev);  
  182.     kfree(mem_devp);  
  183.     unregister_chrdev_region(MKDEV(mem_major,0),2);  
  184. }  
  185.   
  186. MODULE_AUTHOR("Zechin Liao");  
  187. MODULE_LICENSE("GPL");  
  188.   
  189. module_init(memdev_init);  
  190. module_exit(memdev_exit);  

 

[c-sharp] view plaincopy
  1. ifneq ($(KERNELRELEASE),)  
  2. obj-m:=memdev.o  
  3. else  
  4. KERNELDIR:=/home/liao/image/linux-2.6.24  
  5. PWD:=$(shell pwd)  
  6. all:  
  7.     make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-  
  8. clean:  
  9.     rm -rf *.ko *.o *.mod.c *.mod.o *.symvers  
  10. endif  

执行make就会生成memdev.ko驱动文件,将编译好的驱动memdev.ko拷贝至开发板/lib/modules目录。

注意:驱动程序的编译依赖内核源代码,并且内核源代码(KERNELDIR指明)要与目标板运行的内核一致。

 

编写应用程序,对驱动程序测试

[c-sharp] view plaincopy
  1. /*********************************************   
  2. *memdevapp.c   
  3. *********************************************/   
  4. #include <stdio.h>    
  5. #include <stdlib.h>    
  6. #include <unistd.h>    
  7. #include <fcntl.h>     
  8.     
  9. int main()     
  10. {     
  11.     int fd;     
  12.     char buf[4096];     
  13.     
  14.     strcpy(buf,"This is a example of charactar devices driver");     
  15.     printf("buf:%s/n",buf);     
  16.          
  17.     fd=open("/dev/memdev0",O_RDWR);     
  18.     if(fd == -1)     
  19.     {     
  20.         printf("open memdev failed!/n");     
  21.         return -1;               
  22.     }     
  23.          
  24.     write(fd,buf,sizeof(buf));     
  25.     lseek(fd,0,SEEK_SET);     
  26.     strcpy(buf,"nothing");     
  27.     read(fd,buf,sizeof(buf));     
  28.     printf("buf:%s/n",buf);     
  29.     
  30.     return 0;     
  31. }  

 arm-linux-gcc –o memdevapp memdevapp.c编译应用程序,将其下载至开板

 

 

 

添加模块:

# cd /lib/modules

# insmod memdev.ko 

 

添加设备节点:

# cd /dev

# cat /proc/devices 查看设备号

# mknod memdev0 c 260 0

 

运行应用程序

# ./memdevapp

 

以上方法采用的动态编译驱动,也可以静态方式将驱动编译进内核

1.将memdev.h和memdev.c两个驱动源文件拷贝至内核linux-2.6.24/drivers/char目录

 

2.修改该目录下Kconfig文件,添加如下内容

config MEMDEV_DRIVER

             tristate "memdev driver"

             depends on MACH_SMDK2440

             default y if MACH_SMDK2440

             help

                 this option enables support for memdev experiment

 

3.修改该目录下Makefile,添加如下内容

obj-$(CONFIG_MEMDEV_DRIVER)      +=memdev.o

 

4.在make menuconfig时在字符设备中找到菜单项“memdev drinver”,选择为Y或M,编译进内核还是模块。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多