Linux驱动修炼之道

module.h包含可装载模块需要的大量符号和函数定义,包含init.h的目的是指定初始化和清除代码,struct file是在<linux/fs.h>中定义的。

注册字符设备使用

int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);

移除字符设备使用

int unregister_chrdev(unsigned int major, const char *name);

init函数是在insmod时被调用的,exit函数是在rmmod时被调用的。

使用命令 cat /proc/devices 可以查看设备的主设备号。

如果内核没有为我们生成设备文件,我们需要手动生成:

mknod /dev/led_driver c 234 0

__init标记表示该函数只在初始化期间使用,在模块被装载后,模块装载器就会将初始化函数扔掉,这样可将函数占用的内存释放出来。

__exit修饰的函数只在模块卸载或系统关闭时被调用,如果模块被直接内嵌到内核中,或者内核的配置不允许卸载模块,则被标记为__exit的模块将被简单丢弃。

 驱动程序:

  1. #include <linux/module.h>  
  2. #include <linux/fs.h>  
  3. #include <linux/init.h>  
  4. #include <mach/regs-gpio.h>  
  5. #include <mach/hardware.h>  
  6.  
  7. #define LED_MAJOR 234  
  8. #define DEVICE_NAME "led_driver"   
  9.   
  10. static unsigned long led_table[]={   
  11.     S3C2410_GPF3,   
  12.     S3C2410_GPF4,   
  13.     S3C2410_GPF5,   
  14.     S3C2410_GPF6,      
  15. };   
  16.   
  17. static unsigned long led_cfg_table[]={   
  18.     S3C2410_GPF3_OUTP,   
  19.     S3C2410_GPF4_OUTP,   
  20.     S3C2410_GPF5_OUTP,   
  21.     S3C2410_GPF6_OUTP,   
  22. };   
  23.   
  24. int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg){   
  25.     switch(cmd){   
  26.         case 0:   
  27.             s3c2410_gpio_setpin(led_table[0],0);   
  28.             s3c2410_gpio_setpin(led_table[1],1);   
  29.             s3c2410_gpio_setpin(led_table[2],1);   
  30.             s3c2410_gpio_setpin(led_table[3],1);   
  31.             break;   
  32.         case 1:   
  33.             s3c2410_gpio_setpin(led_table[0],1);   
  34.             s3c2410_gpio_setpin(led_table[1],0);   
  35.             s3c2410_gpio_setpin(led_table[2],1);   
  36.             s3c2410_gpio_setpin(led_table[3],1);   
  37.             break;   
  38.         case 2:   
  39.             s3c2410_gpio_setpin(led_table[0],1);   
  40.             s3c2410_gpio_setpin(led_table[1],1);   
  41.             s3c2410_gpio_setpin(led_table[2],0);   
  42.             s3c2410_gpio_setpin(led_table[3],1);   
  43.             break;   
  44.         case 3:   
  45.             s3c2410_gpio_setpin(led_table[0],1);   
  46.             s3c2410_gpio_setpin(led_table[1],1);   
  47.             s3c2410_gpio_setpin(led_table[2],1);   
  48.             s3c2410_gpio_setpin(led_table[3],0);   
  49.             break;   
  50.         default:   
  51.             return -EINVAL;   
  52.             break;   
  53.     }   
  54.     return 0;   
  55. }     
  56.   
  57. struct file_operations led_ops = {   
  58.     .owner = THIS_MODULE,   
  59.     .ioctl = led_ioctl,   
  60. };   
  61.   
  62. static int __init init_led(void)   
  63. {   
  64.     int i, ret;   
  65.     ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&led_ops);   
  66.     if(ret < 0){   
  67.         printk(DEVICE_NAME, "can't register major number\n");   
  68.     }   
  69.     for(i = 0; i < 4; i++){   
  70.         s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);   
  71.         s3c2410_gpio_setpin(led_table[i],1);   
  72.     }   
  73.     printk(DEVICE_NAME "initialized\n");   
  74.     return 0;   
  75. }   
  76.   
  77. static void __exit exit_led(void)   
  78. {   
  79.     unregister_chrdev(LED_MAJOR,DEVICE_NAME);   
  80. }   
  81.   
  82. module_init(init_led);   
  83. module_exit(exit_led);   
  84. MODULE_LICENSE("GPL");   
  85. MODULE_AUTHOR("liwanpeng");  

测试程序:

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <fcntl.h>  
  5. #include <unistd.h>   
  6.   
  7. int main(){   
  8.     int fd, ret;   
  9.     char *i;   
  10.     fd = open("/dev/led_driver",0);   
  11.     if(fd < 0){   
  12.         printf("open device error");       
  13.     }   
  14.     else{   
  15.         while(1){   
  16.             ioctl(fd,0);   
  17.             printf("led0 is on!\n");   
  18.             sleep(1);   
  19.             ioctl(fd,1);   
  20.             printf("led1 is on!\n");   
  21.             sleep(1);   
  22.             ioctl(fd,2);   
  23.             printf("led2 is on!\n");   
  24.             sleep(1);   
  25.             ioctl(fd,3);   
  26.             printf("led3 is on!\n");   
  27.             sleep(1);   
  28.         }   
  29.         close(fd);   
  30.     }   
  31.     return 0;   
  32. }  

效果:此时LED灯也轮流闪烁。

Linux驱动修炼之道

相关推荐