和菜鳥一起學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個問題)的描述時,也全是和上述三點有關係。。。 

 

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