Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1138038
  • 博文数量: 254
  • 博客积分: 1242
  • 博客等级: 少尉
  • 技术积分: 1581
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-03 21:49
文章分类

全部博文(254)

文章存档

2017年(16)

2016年(4)

2013年(94)

2012年(140)

分类:

2012-10-23 11:20:41

makefile 文件
模式一:
obj-m += my_led.o

# specify flags for the module compilation
# EXTRA_CFLAGS=-g -O0

KERNEL_DIR = /work/linuxkernel/linux-2.6.25
PWD = $(shell pwd)

build:kernel_modules

kernel_modules:
    make -C  $(KERNEL_DIR) M=$(PWD) modules

clean:
    make  -C $(KERNEL_DIR) M=$(PWD) clean
    $(RM) *.o *.ko *.mod.c Module.symvers Module.markers modules.order
============================================================================
模式二:
ifeq ($(KERNEL_DIR),)
    KERNEL_DIR ?= /work/linuxkernel/linux-2.6.25
    PWD := $(shell pwd)
modules:
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
modules_install:
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_install
clean:
    rm -rf *.o *~ *.ko *.mod.c Module.*
else
    obj-m := my_led.o
endif
(ps:make modules_install 命令可以将模块安装的操作系统)
============================================================================

.h 文件:
#ifndef  MY_LED_H
#define  MY_LED_H
#include 

//*the  cmd of leds
#define  MY_LED_TYPE 'g'
#define  CMD_LED_OFF  _IO(MY_LED_TYPE,0)
#define  CMD_LED_ON  _IO(MY_LED_TYPE,1)
#define  CMD_BLINK  _IO(MY_LED_TYPE,2)

//the name of device
#define     DEVICE_NAME "hyy_led"
//the state of LED
#define     LED_OFF 1
#define     LED_ON 0
//error processing
#define  error(...) do {\
    printk("********************************************************\n");\
    printk("error located %s : %d :%s\n",__FILE__,__LINE__,__FUNCTION__);\
    printk(__VA_ARGS__);\
    printk("********************************************************\n");\
}while(0)

#define  DEBUG_MSG
//debug message print
#ifdef  DEBUG_MSG
#define  pdeg(...) printk(__VA_ARGS__),printk("(function:%s  line: %d) \n",__FUNCTION__,__LINE__);  
#else
#define  pdeg(...) NULL
#endif

#endif  /*MY_LED_H*/
============================================================================
.c文件:

/*
 *  this is just a led driver test
 *  just for fun and train
 *
 *  author : hyy
 *  time : 2012-08-31 11:21:20
 *
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include  "my_led.h"


static int led_major = 0;
static int led_minor = 0;
static int b_flg = 0;
struct cdev *led_device;
struct class *myclass;
static struct tast_struct * led_th=NULL;
unsigned int GpioId;
static unsigned long led_table[] =
{
    ((0x02DC << 16) | (2)),//GPIO2_2_GPIO,//MFP_PIN_GPIO2_2,//blue
    ((0x02E0 << 16) | (3)),//GPIO3_2_GPIO,//MFP_PIN_GPIO3_2,//yellow
    ((0x02E4 << 16) | (4)),//GPIO4_2_GPIO,//MFP_PIN_GPIO4_2,//green
    ((0x02E8 << 16) | (5)),//GPIO5_2_GPIO,//MFP_PIN_GPIO5_2,//red
    ((0x04E0 << 16) | (83)),//GPIO83_GPIO,//MFP_PIN_GPIO83,//keypad backlight
};

static int blink_led(int i)
{
    GpioId = mfp_to_gpio(led_table[i]);
    gpio_direction_output(GpioId,LED_ON);
    msleep(125);
    gpio_direction_output(GpioId,LED_OFF);
    msleep(125);
    gpio_direction_output(GpioId,LED_ON);
    msleep(125);
    gpio_direction_output(GpioId,LED_OFF);
    msleep(125);
}

// kthread exce function
static int led_abcd(void *data)
{
    int i=0;
    while(!kthread_should_stop()){
        for (i=0 ; i<5 ; i++ ) {
            blink_led(i);
        }
    }
    return 0;
}

int light_release(struct inode *inode, struct file *filp)
{
    return 0;
}

int light_open(struct inode *inode, struct file *filp)
{
    
    return 0;
}

int light_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
    int i = 0;
    if (arg > 5 && arg < 0 ) {
        error("arg must in 0 ~ 5\n");
        return -EINVAL;
    }

   switch(cmd) {
    case CMD_LED_OFF:
        if (arg == 5 ) {
            for (i = 0 ; i <5 ; i++ ) {
                GpioId = mfp_to_gpio(led_table[i]);
                gpio_direction_output(GpioId,LED_OFF);
            }
        }else {
            GpioId = mfp_to_gpio(led_table[arg]);
            gpio_direction_output(GpioId,LED_OFF);
        }
        break;
    case CMD_LED_ON:
        if (arg == 5 ) {
            for (i = 0 ; i <5 ; i++ ) {
                GpioId = mfp_to_gpio(led_table[i]);
                gpio_direction_output(GpioId,LED_ON);
            }
        }else {
            GpioId = mfp_to_gpio(led_table[arg]);
            gpio_direction_output(GpioId,LED_ON);
        }
        break;
    case CMD_BLINK:
        if (arg == 5 ) {
            if (!b_flg){
                led_th = kthread_run(&led_abcd,NULL,"led kernel thread");
                if (led_th == NULL ) {
                    error("create kernel thread failed!\n");
                    return -1;
                }
                b_flg = 1;
            }else {
                if (led_th ) {
                    kthread_stop(led_th);
                    led_th = NULL;
                }
                error("b_flg = %d\t led_th = %d\n",b_flg,led_th);
                b_flg = 0;
            }
        } else {
            blink_led(arg);
        }
        break;
    default:
        printk("error argument!\n");
        return -EINVAL;
    }
   return 0;
}

struct file_operations light_fops = {
    .owner = THIS_MODULE,
    .ioctl = light_ioctl,
    .open = light_open,
    .release = light_release,
};

static void __exit light_exit (void)
{
    dev_t devno = MKDEV(led_major,led_minor);

    if (led_device){
        cdev_del(led_device);

        kfree(led_device);
        led_device = NULL;
    }
    device_destroy(myclass,devno);
    class_destroy(myclass);
    unregister_chrdev_region(devno,1);

    // free the kthread
    if (led_th ) {
        kthread_stop(led_th);
        led_th = NULL;
    }

    return;
}

static int __init light_init(void)
{
    int result = 0;
    int i, GpioId ;

    dev_t dev = 0;
    result = alloc_chrdev_region(&dev,led_minor,1,DEVICE_NAME);
    led_major = MAJOR(dev);
    if (result < 0){
        error(KERN_WARNING "wfet_kb:can`t get major %d\n",led_major);
        return result;
    }
    
    led_device = kmalloc(sizeof(struct cdev), GFP_KERNEL);
    if (!led_device) {
        result = -ENOMEM;
        unregister_chrdev_region(dev, 1);
        return result;
    }
    memset(led_device, 0, sizeof(struct cdev));

    cdev_init(led_device, &light_fops);
    led_device->owner = THIS_MODULE;
    result = cdev_add(led_device,dev,1);
    if (result) {
        error(KERN_NOTICE "Error %d adding LED device, major_%d",result, MAJOR(dev));
        kfree(led_device);
        led_device = NULL;
        unregister_chrdev_region(dev, 1);
        return result;
    }

    /*create device file*/
    myclass = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(myclass) ) {
        error("Err: failed in in creating class\n");
        return -1;
    }
    device_create(myclass,NULL,MKDEV(led_major,led_minor),DEVICE_NAME);


    for (i = 0 ; i <5 ; i++ ) {
        GpioId =  mfp_to_gpio(led_table[i]);
        gpio_direction_output(GpioId,LED_OFF);
    }

    return 0;
}

module_init(light_init);
module_exit(light_exit);
MODULE_AUTHOR("hyy");
MODULE_LICENSE("GPL");                                  //任意版本的GUN公共许可权
  /*
MODULE_LICENSE("GPL V2");                       //GPL版本2许可权
MODULE_LICENSE("GPL and additional rights");    //GPL及其附加许可权
MODULE_LICENSE("Dual BSD/GPL");                 //BSD/GPL双重许可权
MODULE_LICENSE("Dual MPL/GPL");                 //MPL/GPL双重许可权
MODULE_LICENSE("Proprietary");                  //专有许可权
*/


 Makefile.txt    my_led.h.txt    my_led.c.txt  

阅读(1590) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~