Chinaunix首页 | 论坛 | 博客
  • 博客访问: 951666
  • 博文数量: 113
  • 博客积分: 7235
  • 博客等级: 少将
  • 技术积分: 2101
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-14 11:24
文章分类

全部博文(113)

文章存档

2013年(7)

2012年(5)

2011年(6)

2010年(8)

2009年(15)

2008年(72)

分类: LINUX

2009-03-25 21:32:14

本模块是基于s3c2440 ARM开发板编写的,功能是控制开发板上的4个led灯,可以单个点亮或者熄灭,也可以全体点亮或者熄灭,内核模块代码如下:
led.h

#ifndef _LED_H
#define _LED_H

#define LED1 5
#define LED2 6
#define LED3 7
#define LED4 8

#define LED_CTRL_ON 0
#define LED_CTRL_OFF 1
#define LEDS_CTRL_ON 2
#define LEDS_CTRL_OFF 3
#endif

mini2440_niutao_led.c

#include<linux/module.h>
#include<linux/types.h>
#include<linux/fs.h>
#include<linux/errno.h>
#include<linux/mm.h>
#include<linux/sched.h>
#include<linux/init.h>
#include<linux/cdev.h>
#include<asm/io.h>
#include <asm/system.h>
#include<asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include "led.h"

#define LED_NUM 4
#define LED_ON 0
#define LED_OFF (!LED_ON)
#define IS_LEDS(led) ((led) >= LED1 && (led) <= LED4)
#define IS_CTRL(cmd) ((cmd) >= LED_CTRL_ON && (cmd) <= LEDS_CTRL_OFF)


#define LED_MAJOR 212 /*预设的led的主设备号*/

#define led_print(num) printk("%s = 0x%x\n", #num, num)
#define led_printk() printk(KERN_INFO"func %s line = %d\n", __FUNCTION__, __LINE__)

static int led_major = LED_MAJOR;
struct led_dev {
    struct cdev cdev;
    struct semaphore sem;
};
struct led_dev *led_devp;
static unsigned int led_port[LED_NUM] = {
    S3C2410_GPB5,
    S3C2410_GPB6,
    S3C2410_GPB7,
    S3C2410_GPB8
};
static unsigned int led_out[LED_NUM] = {
    S3C2410_GPB5_OUTP,
    S3C2410_GPB6_OUTP,
    S3C2410_GPB7_OUTP,
    S3C2410_GPB8_OUTP
};
int led_open(struct inode *inode,struct file *filp)
{
    int i;

    for (i = 0; i < LED_NUM; i++)
        s3c2410_gpio_cfgpin(led_port[i], led_out[i]);
    for (i = 0; i < LED_NUM; i++)
        s3c2410_gpio_setpin(led_port[i], LED_OFF);
    filp->private_data = led_devp;
    printk(KERN_INFO"led open driver\n");
    return 0;
}

int led_release(struct inode *inode,struct file *filp)
{
    int i;

    for (i = 0; i < LED_NUM; i++)
        s3c2410_gpio_setpin(led_port[i], LED_ON);
    filp->private_data = NULL;
    return 0;
}

static int led_ioctl(struct inode *inodep,struct file *filp, unsigned int cmd,unsigned long arg)
{
    struct led_dev *dev = filp->private_data;
    int i;
    printk(KERN_INFO"cmd = %d arg = %ld\n", cmd, arg);
    if (!IS_CTRL(cmd))
        return -1;
    down(&dev->sem);
    switch (cmd) {
    case LED_CTRL_ON:
    case LED_CTRL_OFF:
        if (!IS_LEDS(arg))
            return -1;
        s3c2410_gpio_setpin(led_port[arg - 5], cmd);
        for (i = 0; i < LED_NUM; i++)
            if (i != arg - 5)
                s3c2410_gpio_setpin(led_port[i], !cmd);
        break;
    case LEDS_CTRL_ON:
        for (i = 0; i < LED_NUM; i++)
            s3c2410_gpio_setpin(led_port[i], LED_ON);
        break;
    case LEDS_CTRL_OFF:
        for (i = 0; i < LED_NUM; i++)
            s3c2410_gpio_setpin(led_port[i], LED_OFF);
        break;
    }
    up(&dev->sem);
    return 0;
}

static ssize_t led_read(struct file *filp,char __user *buf, size_t size,loff_t *ppos)
{
    struct led_dev *dev =filp->private_data;
    char tmp[4];
    int i;
    down(&dev->sem);
    for (i = 0; i < LED_NUM; i++)
        tmp[i] = s3c2410_gpio_getpin(led_port[i]);
    up(&dev->sem);
    if (copy_to_user(buf, (void *)tmp, 4))
        return -EFAULT;
    return 4;
}

static ssize_t led_write(struct file *filp,const char __user *buf, size_t size,loff_t *ppos)
{
    struct led_dev *dev = filp->private_data;
    char tmp[5];
    int i;

    if (copy_from_user(tmp, buf, 5))
        return -EFAULT;
    down(&dev->sem);
    for (i = 0; i < LED_NUM; i++)
        s3c2410_gpio_setpin(led_port[i], !!(int)(tmp[i] - '0'));
    up(&dev->sem);
    return size;
}

static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .read = led_read,
    .write = led_write,
    .ioctl = led_ioctl,
    .open = led_open,
    .release = led_release
};

static void led_setup_cdev(struct led_dev *dev,int index)
{
    int err,devno = MKDEV(led_major,index);

    cdev_init(&dev->cdev,&led_fops);
    dev->cdev.owner = led_fops.owner;
    err = cdev_add(&dev->cdev,devno,1);
    if (err)
        printk(KERN_NOTICE"Error %d adding LED %d\n",err,index);
}

int led_init(void)
{
    int result;
    dev_t devno = MKDEV(led_major,0);
    led_printk();
    if (led_major)
        result = register_chrdev_region(devno,1,"led");
    else {
        result = alloc_chrdev_region(&devno,0,1,"led");
        led_major = MAJOR(devno);
    }
    if(result < 0)
        return result;
    led_devp=kmalloc(sizeof(struct led_dev),GFP_KERNEL);
    if(!led_devp)
    {
        result=-ENOMEM;
        goto fail_malloc;
    }
    memset(led_devp ,0,sizeof(struct led_dev));
    led_setup_cdev(led_devp,0);
    init_MUTEX(&led_devp->sem);
    led_printk();
    return 0;
fail_malloc:
    unregister_chrdev_region(devno,1);
    return result;
}

void led_exit(void)
{
    cdev_del(&led_devp->cdev);
    kfree(led_devp);
    unregister_chrdev_region(MKDEV(led_major,0),1);
    led_printk();
}

MODULE_AUTHOR("Niu Tao");
MODULE_LICENSE("Dual BSD/GPL");

module_param(led_major,int,S_IRUGO);

module_init(led_init);
module_exit(led_exit);

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

niutao.linux2009-05-08 15:56:40

niutao@niutao:~/mini2440$ arm-linux-gcc -v Reading specs from /opt/Mini2440/gcc-3.4.1/bin/../lib/gcc/arm-linux/3.4.1/specs Configured with: /opt/crosstool/crosstool-0.28/build/arm-linux/gcc-3.4.1-glibc-2.3.2/gcc-3.4.1/configure --target=arm-linux --host=i686-host_pc-linux-gnu --prefix=/opt/crosstool/arm-linux/gcc-3.4.1-glibc-2.3.2 --with-float=soft --with-headers=/opt/crosstool/arm-linux/gcc-3.4.1-glibc-2.3.2/arm-linux/include --with-local-prefix=/opt/crosstool/arm-linux/gcc-3.4.1-glibc-2.3.2/

chinaunix网友2009-05-08 03:16:08

我改了一些编译才成功。不然这个文件asm/arch/regs-gpio.h找不到。。

chinaunix网友2009-05-07 21:14:34

请问,你这个是怎么编译的,用哪个版本的交叉编译器?