keke870429 发表于 2012-03-28 13:46

关于驱动的I/O中断响应一些的问题请教,跪求高手解答

我大概描述一下我的 sensor_drive_char.c 文件的主要内容。我的实验平台是S3C2440ARM板。我的目的是希望对GPG13 和 GPG14 两个I/O口,连接一个传感器两个信号线,均发送的是脉冲信号,即1ms脉宽的方波一次,至于硬件电器件性能暂不考虑的情况下,能够使得驱动每来一个脉冲,无论GPG13还是GPG14,就用全局变量计数加一。暂时是想 通过中断方式。关于用这两个引脚,还有待考虑,请问是否有更好的建议。然后两个引脚连接中断   
s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_EINT21);
s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_EINT22);
这么写对么,我是看2440中文手册是这样的
GPG14 00:input 01:output 10:ENIT 11:Reserved
GPG13 00:input 01:output 10:ENIT 11:Reserved
但是结果就编译器报错,



本人所了解到这个错误是因为移植内核代码时,S3C2410_GPG13_EINT21这些没有配置的原因。
但是我主要还是不清楚,到底要改哪些文件,来配置这个中断!!望请不吝赐教

最后附源代码如下,希望高手能多多指正,感激不尽!!谢谢

#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/device.h>
#include <linux/gpio.h>

MODULE_AUTHOR("kelun");
MODULE_LICENSE("Dual BSD/GPL");

static int g_irq = 0;

struct tasklet_struct sensor_taslet;

//定义模块结构体
static struct cdev sensor_cdev;

//定义一个设备class
static struct class *sensor_class=NULL;

static struct device *sensor_device = NULL;

//设备号
static dev_t devno;

//主设备号
static uint devno_major = 0;

//次设备号
static uint devno_minor = 0;


static long int mycount_gpg13 = 0;
static long int mycount_gpg14 = 0;

module_param (mycount_gpg13,long, 0660);
MODULE_PARM_DESC (mycount_gpg13, "A long integer");

module_param (mycount_gpg14,long, 0660);
MODULE_PARM_DESC (mycount_gpg14, "A long integer");

void sensor_tasklet_fn(unsigned long arg)
{
        /*deferrable part. 中断的下半部*/
        mycount_gpg13++;
        mycount_gpg14++;
        printk("GPG13=%ld   GPG14=%ld \n",mycount_gpg13,mycount_gpg14);
}

static irqreturn_t sensor_handler(int irq, void *dev_id)
{
//        printk("Debug ++ %s ++ irq = %d\n", __func__, irq);

        /*....   do something urgent , 中断的上半部*/
        //execute urgent part ....

        sensor_taslet.data=irq;
        tasklet_schedule(&sensor_taslet);

        return IRQ_HANDLED;
}

void sensor_gpio_init(void)
{
       
/*设置GPG 13,14为中断引脚 ,寄存器与中断引脚的联结*/
            s3c2410_gpio_cfgpin(S3C2410_GPG(13), (0x02 << 26)); //错误主要就在这里
        s3c2410_gpio_cfgpin(S3C2410_GPG(14), (0x02 << 28)); //写成S3C2410_GPG13_EINT21 和22也错


/*中断类型的设置,为高电平触发*/
        set_irq_type(S3C2410_GPG13_EINT21, IRQ_TYPE_LEVEL_HIGH);
        set_irq_type(S3C2410_GPG13_EINT22, IRQ_TYPE_LEVEL_HIGH);

       
}

static int sensor_open (struct inode *inode, struct file *file)
{
        return 0;
}


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

//接口函数填充
struct file_operations sensor_fops = {
.owner = THIS_MODULE,
.open= sensor_open,
.release = sensor_release,
};


static int sensor_init(void)
{
        int result;
        int ret;


        sensor_gpio_init();       
        result = request_irq (IRQ_EINT21, sensor_handler,IRQF_SAMPLE_RANDOM, "sensor", NULL);       
        if (result) {
                printk(KERN_INFO "button: can't get assigned irq\n");
        }

        result = request_irq (IRQ_EINT22, sensor_handler,IRQF_SAMPLE_RANDOM, "sensor", NULL);       
        if (result) {
                printk(KERN_INFO "button: can't get assigned irq\n");
        }


        tasklet_init(&sensor_taslet, sensor_tasklet_fn, (unsigned long)g_irq);

        //动态申请设备号
        ret = alloc_chrdev_region(&devno, 0, 1, "char_key");//成功返回0,不成功返回-1
        if (ret < 0) //判断是否成功
        {
                printk(KERN_INFO "can't register char device driver\n");
                return -1;
        }

        //提取主设备号
        devno_major = MAJOR(devno);
        //提取次设备号
        devno_minor = MINOR(devno);
       
        //初始化cdev->ops=file_operatins
        cdev_init(&sensor_cdev, &sensor_fops);
       
        //设置当前模块指针填充
        sensor_cdev.owner = THIS_MODULE;
       
        //加载模块到内核
        ret = cdev_add(&sensor_cdev, devno, 1);//成功返回0,失败返回-1
        if(ret<0)//判断是否成功
        {
                printk(KERN_INFO "can't register char device\n");
                return -1;
        }

        //创建设备节点,使用udev
        //调用class_create创建一个设备类
        sensor_class=class_create(THIS_MODULE, "key_class");

        //
        if (IS_ERR(sensor_class))
        {
                printk(KERN_ERR "failed to create device class \n");
                cdev_del(&sensor_cdev);//从系统中移除一个字符设备
                unregister_chrdev_region(devno , 1);//释放设备号,first为第一个设备号,count为申请的设备数量
                return -1;
        }
        //创建设备节点
        sensor_device = device_create(sensor_class,NULL,devno,NULL,"key_dev");
       
        return 0;

}


static void sensor_cleanup(void)
{
        printk("simple device uninstalled\n");

        free_irq(IRQ_EINT21,NULL);
        free_irq(IRQ_EINT22,NULL);


       cdev_del(&sensor_cdev);//卸载字符设备
        unregister_chrdev_region(devno , 1);//释放设备号
       
        /*
        函数device_destroy()用于从linux内核系统设备驱动程序模型中移除一个设备,
        并删除/sys/devices/virtual目录下对应的设备目录及/dev/目录下对应的设备文件
        */
        device_destroy(sensor_class, devno);

        class_destroy(sensor_class);//销毁类
}

module_init(sensor_init);
module_exit(sensor_cleanup);

keke870429 发表于 2012-03-28 16:12

关于报错的问题我解决了,sensor_gpio_init(void)函数里
修改宏的两个地方就能编过了,但是 希望高手能帮忙指点下
这样做的驱动是否可行,能否达到记录脉冲的功效?
页: [1]
查看完整版本: 关于驱动的I/O中断响应一些的问题请教,跪求高手解答