和菜鸟一起学linux:第六篇:将LED驱动编译到内核

 

第六篇:将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个问题)的描述时,也全是和上述三点有关系。。。 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章