基于tx2440的led驱动

搞了两天~~还没有成功~~有待进一步研究,现在将过程及错误列出:

源码如下:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>

#define DEVICE_NAME "tx2440_led"
static int tx2440_led_Major=0;

#define LED_OFF                0
#define LED_ON                1
#define ALL_LED_OFF         3
#define ALL_LED_ON        4

//指定led所用的io引脚,这里查看原理图
static unsigned long led_table[]=                //这里的S3C2410_GPF(0)等在哪里定义的?
{
                S3C2410_GPF(0),
                S3C2410_GPF(1),
                S3C2410_GPF(2),
                S3C2410_GPF(3),
};

static int tx2440_led_open(struct inode *inode,struct file *filp)
{
        printk(KERN_INFO "TX2440_LED DRIVER OPEN CALLED!/n");
        return 0;
}

static int tx2440_led_release(struct inode *inode,struct file *filp)
{
        printk(KERN_INFO "TX2440_LED_DRIVER CLOSE CALLED!/n");
        return 0;
}

static int tx2440_led_read(struct file *filp, char *buf, size_t count, loff_t *f_ops)
{
        printk(KERN_INFO "TX2440_LED_DRIVER READ CALLED!/n");
        return 0;
}

static int tx2440_led_write(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
        printk(KERN_INFO "TX2440_LED_DRIVER WRITE CALLED!/n");
        return 0;
}

static int tx2440_led_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
        int i;
        if (arg>4)                //arg参数有什么用?
        {
                return -EINVAL;
        }
        switch(cmd)
        {
                case LED_ON:               
                        s3c2410_gpio_setpin(led_table[arg],0);        //低电平点亮
                        break;
                case LED_OFF:               
                        s3c2410_gpio_setpin(led_table[arg],1);
                        break;
                case ALL_LED_ON:       
                        for(i=0;i<4;i++)
                                s3c2410_gpio_setpin(led_table[i],0);
                        break;
                case ALL_LED_OFF:
                        for(i=0;i<4;i++)
                                s3c2410_gpio_setpin(led_table[i],1);
                        break;
                default:        return -EINVAL;               
        }
}

static struct file_operations tx2440_led_fops =
{
        .owner        =        THIS_MODULE,
        .open        =        tx2440_led_open,
        .release        =        tx2440_led_release,
        .read        =        tx2440_led_read,
        .write        =        tx2440_led_write,
        .ioctl        =        tx2440_led_ioctl,
};

static struct class *tx2440_led_class;        //这里要注意是什么东西?

static  int __init tx2440_led_init(void)
{
        printk(KERN_INFO "TX2440_LED_DRIVER MODULE INIT/n");
        tx2440_led_Major=register_chrdev(0,DEVICE_NAME,&tx2440_led_fops);
        if(tx2440_led_Major<0)
        {
                printk(KERN_WARNING "Can't register the major number/n");
                return tx2440_led_Major;
        }
        else
                printk( "Register the major number ok.Major=%d/n",tx2440_led_Major);
               
        //注册一个类,使mdev可以在"/dev/"目录下面建立设备节点
        tx2440_led_class = class_create(THIS_MODULE, DEVICE_NAME);
        if(IS_ERR(tx2440_led_class))
        {
                printk("Err: failed in tx2440_led_class. /n");
                return -1;
        }
        //创建一个设备节点,节点名为DEVICE_NAME
        else
        device_create(tx2440_led_class, NULL, MKDEV(tx2440_led_Major, 0), NULL, DEVICE_NAME);

        printk(DEVICE_NAME " initialized/n");
        return 0;
}

static void __exit tx2440_led_exit(void)
{
        printk("tx2440_led MODULE EXIT/n");
        unregister_chrdev(tx2440_led_Major, DEVICE_NAME);
        device_destroy(tx2440_led_class, MKDEV(tx2440_led_Major, 0));
        class_destroy(tx2440_led_class);
}

module_init(tx2440_led_init);
module_exit(tx2440_led_exit);

MODULE_AUTHOR("YWW");               
MODULE_DESCRIPTION("My Driver");       
MODULE_LICENSE("GPL");

Makefile文件源码如下:
#Makefile for tx2440_led

ifneq        ($(KERNELRELEASE),)
        obj-m:=tx2440_led.o
else
        KERNELDIR        ?=        /usr/local/src/linux-2.6.31
        PWD        :=        $(shell pwd)
all:
        $(MAKE)        -C        $(KERNELDIR)        M=$(PWD)        modules
endif
测试代码如下:
/******************************************************
LED驱动测试程序,在TX2440A开发板做测试

驱动用法:
                设备名称:TX2440-led
                测试程序名称:led
                如果只带一个参数,且参数为0 1
                led 0:四个灯全灭
                led 1: 四个灯全亮
                如果带两个参数,参数1表示哪盏灯,参数2表示亮灭
                led 1 0:第一盏灯灭
                led 4 1: 第四盏灯亮
*******************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>

int main(int argc, char **argv)
{
        unsigned int on;
        unsigned int led_num;
        int fd;
        fd = open("/dev/tx2440_led", 0);
        if (fd < 0)
        {
                perror("open device led");
                exit(1);
        }

        if (argc == 2)
        {
                sscanf(argv[1], "%d", &on);
                if (on < 2)
                {
                        ioctl(fd, on+3, 0);
                        sleep(5);
                }
                else
                {
                        printf("Usage: led led_num 0|1  or  led 0|1/n");
                        exit(1);
                }
        }
       
        if (argc == 3)
        {
                sscanf(argv[1], "%d", &led_num);
                sscanf(argv[2], "%d", &on);
                if ((on < 2) && (led_num>0 || led_num < 4))
                {       
                        ioctl(fd, on, (led_num-1));
                        sleep(5);
                }
                else
                {
                        printf("Usage: led led_num 0|1  or  led 0|1/n");
                        exit(1);
                }
        }

        close(fd);
        return 0;
}

通过驱动程序的Makefile编译出了tx2440_led.ko文件,下载到开发板的/lib/modules/2.6.31目录下运行的现象如下
[root@YWW-2440 2.6.31]#led 1 1
TX2440_LED DRIVER OPEN CALLED!
TX2440_LED_DRIVER CLOSE CALLED!
[root@YWW-2440 2.6.31]#led 4 1
TX2440_LED DRIVER OPEN CALLED!
TX2440_LED_DRIVER CLOSE CALLED!

显然应用程序能够调用驱动程序里的open与close函数~~
但是问题在开发板上的发光二极管没亮~
这是怎么回事~~??

今天又在在ioctl中也添加了printk打印函数,一样能够打印出信息,也就是能正确调用icotl函数,那问题就出在s3c2410_gpio_setpin()函数了~~可是,这个函数是这样调用的啊~~那问题到底出在哪里??是不是要设置S3C2410_GPFDAT这个寄存器使gpf 口作为输出??? 有高手看到可以指点小弟~~谢谢~~

你可能感兴趣的:(struct,Module,File,table,Class,makefile)