Chinaunix首页 | 论坛 | 博客
  • 博客访问: 204341
  • 博文数量: 32
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 850
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-22 15:50
文章存档

2014年(16)

2013年(16)

分类: 嵌入式

2013-12-10 11:32:22

                    MINI2440驱动程序编译进内核
开发环境    
                SYSTEM       :  Ubuntu-12.04

                Board        :  Mini2440-t35
                Bootloader   :  u-boot-1.1.6
                Kernel       :  Linux-2.6.22.6
                CROSS_COMPILE: arm-linux-gcc v3.4.5

一、驱动程序编译进内核的步骤

在 linux 内核中增加程序需要完成以下三项工作:

    1. 将编写的源代码复制到 Linux 内核源代码的相应目录;

    2. 在目录的 Kconfig 文件中增加新源代码对应项目的编译配置选项;

    3. 在目录的 Makefile 文件中增加对新源代码的编译条目。

二、将前面MINI2440的LED驱动程序编译进内核
     1.  将led_drv.c文件拷入内核的drivers/char目录下。
     2.  修改drivers/char目录下的Kconfig文件,加入如下条目
        

点击(此处)折叠或打开

  1. config MINI2440_LED_MODULE
  2.         tristate "LED Support for Mini2440 GPIO LEDs"
  3.         depends on ARCH_S3C2410
  4.         help
  5.                 This option enables support for LEDs
       3.  执行make menuconfig,在Device Drivers  --->Character devices  ---><*> LED Support for Mini2440 GPIO LEDs 加入MINI2440_LED_MODULE的编译选项。    
    4. 修改drivers/char目录下的Makefile文件增加如下内容     

点击(此处)折叠或打开

  1. obj-$(CONFIG_MINI2440_LED_MODULE) += led_drv.o
    5. 执行make uImage即可得到带有LED驱动的内核。

三、将内核重新烧入开发板
    
启动开发板,执行cat /proc/devices即可看到MINI2440_LEDS驱动程序。

至此,我们只是将驱动加入了内核,但是在/dev目录下并没有该驱动对应的设备节点,原因是我们的驱动程序中并没有加入自动创建设备节点的相应代码。

四、自动创建设备节点

    在刚开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点,实际上Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/dev目录下创建相应设备节点,并在卸载模块时删除该节点,当然前提条件是用户空间移植了udev。
    内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。
    我们就是使用这种方式自动创建设备节点,修改后的led_drv.c完整代码如下
    

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>
  4. #include <linux/init.h>
  5. #include <linux/device.h>        //提供class_create、class_device_create等函数
  6. #include <asm/arch/regs-gpio.h>
  7. #include <asm/hardware.h>

  8. #define        DEVICE_NAME        "MINI2440_LEDS"        //设备名称

  9. #define IOCTL_LED_ON 0
  10. #define IOCTL_LED_OFF 1

  11. static struct class *led_drv_class;
  12. static struct class_device    *led_drv_class_dev;

  13. static unsigned long led_table[] = {
  14.     S3C2410_GPB5,
  15.     S3C2410_GPB6,
  16.     S3C2410_GPB7,
  17.     S3C2410_GPB8,
  18. };

  19. static unsigned long led_cfg_table[] = {
  20.     S3C2410_GPIO_OUTPUT,
  21.     S3C2410_GPIO_OUTPUT,
  22.     S3C2410_GPIO_OUTPUT,
  23.     S3C2410_GPIO_OUTPUT,
  24. };
  25. static int led_drv_open(struct inode *inode, struct file *file)
  26. {
  27.     int i;
  28.     for(i=0;i<4;i++)
  29.     {
  30.         s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
  31.     }
  32.     return 0;
  33. }
  34. static int led_drv_ioctl(
  35.     struct inode *inode,
  36.     struct file *file,
  37.     unsigned int cmd,
  38.     unsigned long arg)
  39. {
  40.     if(arg > 4)
  41.         return -EINVAL;
  42.     switch(cmd){
  43.         case IOCTL_LED_ON:
  44.             s3c2410_gpio_setpin(led_table[arg],0);
  45.             return 0;
  46.         case IOCTL_LED_OFF:
  47.             s3c2410_gpio_setpin(led_table[arg],1);
  48.             return 0;
  49.         default:
  50.             return -EINVAL;
  51.     }
  52. }
  53. static struct file_operations led_drv_fops = {
  54.     .owner = THIS_MODULE,
  55.     .open = led_drv_open,
  56.     .ioctl = led_drv_ioctl,
  57. };

  58. int major;
  59. static int __init led_drv_init(void)
  60. {
  61.     major = register_chrdev(0, DEVICE_NAME, &led_drv_fops);
  62.     if(major < 0)
  63.     {
  64.         printk(DEVICE_NAME "\tcan't register major number!\n");
  65.     }
  66.     led_drv_class = class_create(THIS_MODULE, DEVICE_NAME);
  67.     led_drv_class_dev = class_device_create(led_drv_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); /* /dev/buttons */

  68.     printk(DEVICE_NAME"\tinitialized!\n");
  69.     return 0;
  70. }
  71. static void __exit led_drv_exit(void)
  72. {
  73.     unregister_chrdev(major, DEVICE_NAME);
  74.     class_device_unregister(led_drv_class_dev);
  75.     class_destroy(led_drv_class);
  76. }

  77. module_init(led_drv_init);
  78. module_exit(led_drv_exit);
  79. MODULE_LICENSE("GPL");
阅读(2114) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~