已经很久没写过驱动了,今天突然说要控制一个LED灯,闲来无事便自己写了一个,权当复习,闲话少说直接代码......

驱动代码(gpg7.c):

  1. #include <linux/module.h> 
  2. #include <linux/kernel.h> 
  3. #include <linux/fs.h> 
  4. #include <linux/init.h> 
  5. #include <linux/delay.h> 
  6. #include <asm/irq.h> 
  7. #include <linux/device.h> 
  8. #include <asm/uaccess.h> 
  9. #include <linux/ioport.h> 
  10. #include <asm/io.h> 
  11.  
  12. #define GPB_ON  1 
  13. #define GPB_OFF 0 
  14.  
  15. static unsigned int oam_major=0; 
  16. static struct class *oam_class =NULL
  17.  
  18. static volatile unsigned long   *gpfcon; 
  19. static volatile unsigned long   *gpfdat; 
  20.  
  21. /*1. 实现对硬件的操作方法*/ 
  22. static int oam_open(struct inode *inode, struct file *file) 
  23.     /*初始化硬件*/ 
  24.     /*将GPB7设置为输出管脚*/ 
  25.     *gpfcon &= ~(0x3<<14); 
  26.     *gpfcon |= (0x1<<14); 
  27.     return 0; 
  28.  
  29. ssize_t oam_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) 
  30.     //TODO 
  31.     return 0; 
  32.  
  33. static ssize_t oam_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 
  34.     char val; 
  35.     int ret; 
  36.  
  37.     /*获取用户空间传入的值*/ 
  38.     ret =copy_from_user(&val,buf,1); 
  39.     if(!val) 
  40.     { 
  41.         *gpfdat |= (0x1 << 7);  
  42.     } 
  43.     else 
  44.     { 
  45.         *gpfdat &= ~(0x1 << 7); 
  46.     } 
  47.      
  48.     return 0; 
  49.  
  50. static int oam_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg) 
  51.     switch(cmd) 
  52.     { 
  53.         case GPB_OFF:  
  54.                 *gpfdat |= (0x1 << 7);  
  55.                 break;  
  56.         case GPB_ON:  
  57.                 *gpfdat &= ~(0x1 << 7); 
  58.                 break; 
  59.         default:break; 
  60.     } 
  61.     return 0; 
  62.  
  63. /*2. 构建file_operations结构体*/ 
  64. static struct file_operations oam_fops={ 
  65.     .owner  = THIS_MODULE, 
  66.     .open   = oam_open, 
  67.     .write  = oam_write, 
  68.     .read   = oam_read, 
  69.     .ioctl  = oam_ioctl, 
  70. }; 
  71.  
  72. /*3. 实现入口函数*/ 
  73. static int __init oam_init(void) 
  74.     /*1.注册*/ 
  75.     oam_major =register_chrdev(0,"gpb7",&oam_fops); 
  76.  
  77.     /*2. 构建设备节点*/ 
  78.     oam_class =class_create(THIS_MODULE,"gpb7_class"); 
  79.     device_create(oam_class,NULL,MKDEV(oam_major,0),NULL,"gpb7"); 
  80.  
  81.     /*3.将物理地址映射为虚拟地址*/ 
  82.     gpfcon =ioremap(0x56000010,4096); 
  83.     gpfdat =gpfcon +1; 
  84.      
  85.     return 0; 
  86.  
  87. /*4.实现出口函数*/ 
  88. static void __exit oam_exit(void ) 
  89.     unregister_chrdev(oam_major,"gpb7"); 
  90.     class_destroy(oam_class); 
  91.     device_destroy(oam_class,MKDEV(oam_major,0)); 
  92.     iounmap(gpfcon); 
  93.  
  94. module_init(oam_init); 
  95. module_exit(oam_exit); 
  96. MODULE_LICENSE("GPL"); 

测试代码(gpg7_test.c):

  1. #include <stdio.h> 
  2. #include <string.h> 
  3. #include <sys/types.h> 
  4. #include <sys/stat.h> 
  5. #include <fcntl.h> 
  6. #include <sys/ioctl.h> 
  7.  
  8. #define GPB_ON  1 
  9. #define GPB_OFF 0 
  10.  
  11. void print_usage(char *str) 
  12.     printf("please input follow this!\n"); 
  13.     printf("%s <dev> <on/off> \n",str);  
  14.  
  15. int main(int argc, char **argv) 
  16.     int fd = 0; 
  17.     //char buf[1]; 
  18.     int cmd = 0; 
  19.     if(argc!=3&&argc!=2) 
  20.     { 
  21.         print_usage(argv[0]); 
  22.         return -1; 
  23.     } 
  24.     fd =open(argv[1], O_RDWR); 
  25.     if(fd <0) 
  26.     { 
  27.         printf("cannot open the dev!\n"); 
  28.         return -1; 
  29.     } 
  30.     if(strcmp(argv[2],"on")==0) 
  31.     { 
  32.         cmd=GPB_ON; 
  33.     } 
  34.     else if(strcmp(argv[2],"off")==0) 
  35.     { 
  36.         cmd=GPB_OFF; 
  37.     } 
  38.     //write(fd, buf, 1); 
  39.     ioctl(fd,cmd,NULL); 
  40.     return 0; 

Makefile:

  1. all: 
  2.     make -C /home/farsight/anyk/s3c2440/kernal/linux-2.6.30.4 M=`pwd` modules 
  3. clean: 
  4.     make -C /home/farsight/anyk/s3c2440/kernal/linux-2.6.30.4 M=`pwd` clean 
  5.  
  6. obj-m += gpb7.o 

相对而言,字符设备还是挺简单的。