牛棚

--拥有的远比想象的多...
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

第六篇:将LED驱动编译到内核

Posted on 2009-06-23 12:04  Moi  阅读(658)  评论(0)    收藏  举报
第六篇:将LED驱动编译到内核

日期:2009-3-12



内核的drivers目录里提供了LED的驱动文件,查看后,发现管脚定义也和我板子上的定义一致(呵呵)

于是就把内核提供的LED例子弄的我存放文件的目录,想编译下,主要是测试下看是否有错误。



编译内核提供的 LED 例子,操作如下;

arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c example-leds.c



example-leds.c文件内容如下:



#include <linux/config.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>



#include <linux/miscdevice.h>

#include <linux/sched.h>

#include <linux/delay.h>

#include <linux/poll.h>

#include <linux/spinlock.h>

#include <linux/irq.h>

#include <linux/delay.h>



#include <asm/hardware.h>



#define DEVICE_NAME "leds"

#define example_led_MAJOR 231



static unsigned long example_led_table [] = {

    GPIO_F7,//GPIO_B7,

    GPIO_F6,//GPIO_B8,

    GPIO_F5,//GPIO_B9,

    GPIO_F4,//GPIO_B10,

};



static int example_leds_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

    switch(cmd) {

    case 0:

    case 1:

        if (arg > 4) {

            return -EINVAL;

        }

        write_gpio_bit(example_led_table[arg], !cmd);

    default:

        return -EINVAL;

    }

}

static struct file_operations example_leds_fops = {

    owner:  THIS_MODULE,

    ioctl:  example_leds_ioctl,

};



static devfs_handle_t devfs_handle;

static int __init example_leds_init(void)

{

    int ret;

    int i;



    ret = register_chrdev(example_led_MAJOR, DEVICE_NAME, &example_leds_fops);

    if (ret < 0) {

      printk(DEVICE_NAME " can't register major number\n");

      return ret;

    }

    devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,

                example_led_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &example_leds_fops, NULL);

    for (i = 0; i < 8; i++) {

        set_gpio_ctrl (example_led_table[i] | GPIO_PULLUP_EN | GPIO_MODE_OUT);

        write_gpio_bit(example_led_table[i], 1);

    }



    printk(DEVICE_NAME " initialized\n");

    return 0;

}



static void __exit example_leds_exit(void)

{

    devfs_unregister(devfs_handle);

    unregister_chrdev(example_led_MAJOR, DEVICE_NAME);

}



module_init(example_leds_init);

module_exit(example_leds_exit);



哀。

错误太多了,,,,列出来的话,真的很吓人的。。。

于是又把自己之前编译没有错误的led.c文件,拿出来测试下,看是否编译环境有问题??

操作如下:

arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c led.c

编译没问题



led.c文件内容:



#ifndef __KERNEL__

#define __KERNEL__

#endif

#ifndef MODULE

#define MODULE

#endif



#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/version.h>

#include <linux/fs.h>

#include <linux/init.h>

#include <asm-arm/arch-s3c2410/hardware.h>

#define DEVICE_NAME "leds"

#define LED_MAJOR 232



static unsigned long led_table[]={GPIO_F4,GPIO_F5,GPIO_F6,GPIO_F7};

static int leds_ioctl(struct inode *inode,struct file *file,unsigned int cmd,

    unsigned long arg){

switch(cmd){

    case 0:

    case 1:

    if(arg>4){

        return -EINVAL;

    }

    write_gpio_bit(led_table[arg],!cmd);

    printk("pin ");

    break;

    default:

        return -EINVAL;

    }

}



static struct file_operations leds_fops={

    owner:THIS_MODULE,

    ioctl:leds_ioctl,



};



static int __init leds_init(void){

int ret;

int i;

ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&leds_fops);

if(ret<0)

{

    printk(DEVICE_NAME"can't register major number");

    return ret;

}

for(i=0;i<4;i++)

{

    set_gpio_ctrl(led_table[i]|GPIO_PULLUP_EN|GPIO_MODE_OUT);

    write_gpio_bit(led_table[i],1);

}

printk(DEVICE_NAME "initialized\n");

return 0;

}



static void __exit leds_exit(void){

    unregister_chrdev(LED_MAJOR,DEVICE_NAME);

}



module_init(leds_init);

module_exit(leds_exit);





很纳闷,为什么编译内核提供的LED测试程序时,错误非常多??

而编译 阿南教程上的没有错??

编译时参数选项一样,就文件名不同而已,,,



想来想去,也就觉得在两个文件中的最大区别是:

led.c文件的开始有如下声明:



#ifndef __KERNEL__

#define __KERNEL__

#endif

#ifndef MODULE

#define MODULE

#endif

后来在 example-leds.c(系统提供的文件)中也加了如下声明:

再次编译没有问题了,(上述声明,加入文件的开头处)

操作如下:

arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c example-leds.c



为啥会出现上述的问题呢???

目前我的猜测就是:

内核提供的例子是将驱动程序直接编译到内核去的,所以不需要加上述的声明

而驱动程序用加载到内核的方法时(即insmod动态加载时),就需要加上述的声明

也不知道说的对不对?呵呵



就目前的情况看

led.c文件与 example-leds.c文件的区别:

1 前者是insmod方式加载的,后者是直接编译到内核。

2 前者有关于内核、模块的宏定义,后者没有

3 前者在驱动初始化和退出时,没有使用设备文件系统,后者在驱动源文件中使用了

  如:static devfs_handle_t devfs_handle;(其他没列出 呵呵)

看教程中关于出现问题(教程有3个问题)的描述时,也全是和上述三点有关系。。。