Tetra 发表于 2013-12-24 16:09:53

AM3358的中断怎么设置的

看手册看了很久也没搞明白下列问题:
看手册说最多可以支持128个中断,但是这些中断怎么用那?
那些手册上已经标注了名称的中断是否还能给其他设备使用?
是不是只有DMA中断可以给其他设备使用?
另外,手册上说每组IO口有中断A和终端B,是不是说每组IO口最多可以有两个引脚被当成中断使用?
那位能给指点指点,多谢!!

天嵌技术支持01 发表于 2013-12-24 17:44:09

TQ3358提供的6个用户按键是用GPIO中断功能做的,结合源码的例子去理解

Tetra 发表于 2013-12-25 11:26:21

多谢版主回复!
但是用户按键的源码在哪里?Uboot里面?

天嵌技术支持01 发表于 2013-12-30 11:09:56

uboot里面也有的
kernel是在board-am335xevm.c源文件中添加的查找关键字key

天嵌技术支持01 发表于 2013-12-30 11:10:12

Tetra 发表于 2013-12-25 11:26
多谢版主回复!
但是用户按键的源码在哪里?Uboot里面?

uboot里面也有的
kernel是在board-am335xevm.c源文件中添加的查找关键字key

Tetra 发表于 2013-12-31 09:54:14

好的,多谢版主

taiyuankejizhu 发表于 2014-1-10 08:25:08

天嵌技术支持01 发表于 2013-12-30 11:10
uboot里面也有的
kernel是在board-am335xevm.c源文件中添加的查找关键字key

      我先在也遇到了点问题,已经看过你说的board-am335xevm.c文件了,应该是在内核启动的时候对一些内部资源进行初始化和平台设备注册,驱动程序应该是gpio_keys.c用平台设备驱动,在probe函数里读平台设备的管脚和中断资源然后申请和注册(setup_key函数)。我看它的过程顺序是gpio_request-》gpio_direction_input-》gpio_set_debounce-》gpio_to_irq-》request_threaded_irq。
   我先在的问题是,我想做一个外部中断的实验,申请的是TQ3358的gpio1_16和gpio1_17就是那两个LED灯的管脚(因为那六个按键中断好像中断不共享),我知道在board-am335xevm.c文件里,这两个管脚已经初始化为输出模式,那我还能不能在驱动中通过像gpio_keys.c中的那样申请管脚,更改管脚模式,和注册成为中断,现在的情况是申请管脚和注册中断已经成功了,但是就是进入不了中断,/proc/interrupts里面相应的中断次数一直是0。谢谢回复!

taiyuankejizhu 发表于 2014-1-10 08:28:25

/*
misc device driver ,add the extern interrupt to asy connect with
the user application.
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>

#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/sched.h>

#include <asm/uaccess.h>

#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))

#define DEVICE_NAME         "hello"
#define MAX_KEY_BUF      16
#define KEY_NUM          2

#define KEYSTATUS_UP    0
#define KEYSTATUS_DOWNX 2
#define KEYSTATUS_DOWN1

#define KEY_TIMER_DELAY 200

typedef unsigned char KEY_RET ;

static struct key_info
{
        const char *desc;
        int gpio_port;
        int key_no;
} key_info_tab =
{
        {"KEY_1",GPIO_TO_PIN(1, 16),0},
        {"KEY_2",GPIO_TO_PIN(1, 17),1},
};

static struct key_dev
{
        unsigned int keystatus;
        KEY_RET buf;
        unsigned int head ,tail;
        wait_queue_head_t wq;
        struct miscdevice miscdev;
} *keydevp;

static struct timer_list key_timer;/*按键的延时*/

int ISKEY_DOWN(int k)
{
        unsigned int gpio = key_info_tab.gpio_port;
        printk("gpio(%d)_get_value:%d\n",gpio,gpio_get_value(gpio));
        return gpio_get_value(gpio);
}
/*按键延时处理函数*/
void keyboard_timer_handler(unsigned long data)
{
        int key = data;
        printk("handler data is:%d",key);
        if (ISKEY_DOWN(key))
        {
                if (keydevp->keystatus == KEYSTATUS_DOWNX)
                {
                        keydevp->keystatus = KEYSTATUS_DOWN;
                        if(keydevp->tail<MAX_KEY_BUF)
                        {
                                keydevp->buf = key;
                                keydevp->tail++;
                        }
                        else
                        {
                                keydevp->tail=0;
                                keydevp->buf = key;
                                keydevp->tail++;
                        }
                        wake_up_interruptible(&(keydevp->wq));
                        key_timer.expires = jiffies + KEY_TIMER_DELAY;
                        add_timer(&key_timer);
                }
                else
                {
                        key_timer.expires = jiffies + KEY_TIMER_DELAY;
                        add_timer(&key_timer);
                }
        }
        else
        {
                keydevp->keystatus = KEYSTATUS_UP;
                del_timer(&key_timer);
                enable_irq(gpio_to_irq(key_info_tab.gpio_port));
        }
}

/*中断处理顶半部*/
static irqreturn_t keyboard_interrupt(int irq,void *dev_id){
        struct key_info *key;
        key = dev_id;
        disable_irq(gpio_to_irq(key->gpio_port));

        keydevp->keystatus = KEYSTATUS_DOWNX;
        key_timer.expires = jiffies + KEY_TIMER_DELAY;
        add_timer(&key_timer);
        return IRQ_HANDLED;
}

static ssize_t hello_read(struct file *filp, char __user *buf, size_t count,loff_t*ppos)
{
        int ret ;
        retry: if (keydevp->head != keydevp->tail)
        {
                if(keydevp->head<MAX_KEY_BUF)
                {
                        ret=copy_to_user(buf,&keydevp->buf,1);
                        keydevp->buf=0;
                        keydevp->head++;
                        return ret;
                }
                else
                {
                        keydevp->head=0;
                        ret=copy_to_user(buf,&keydevp->buf,1);
                        keydevp->buf=0;
                        keydevp->head++;
                        return ret;
                }
        }
        else
        {
                if (filp->f_flags &O_NONBLOCK)
                {
                        return - EAGAIN;
                }
                interruptible_sleep_on(&(keydevp->wq));
        goto retry;
        }
        return 0;
}

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

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

static struct file_operations hello_fops=
{
        .owner                        =        THIS_MODULE,
        .open                         =         hello_open,
        .release               =         hello_close,
        .read                   =       hello_read,
};

static struct miscdevice misc = {
        .minor        = MISC_DYNAMIC_MINOR,
        .name        = DEVICE_NAME,
        .fops        = &hello_fops,
};

/*注册按键中断*/
int keyboard_request_irqs(void)
{
        struct key_info *k;
        int i, ret ,irq ,irqflags;
        for(i=0;i<sizeof(key_info_tab)/sizeof(struct key_info);i++)
        {
                k = &key_info_tab;
                /*缺少外部中断状态设置*/

                ret = gpio_request(k->gpio_port,k->desc);
                if(ret < 0 )
                {       
                        printk("can't request gpio!%d error:%d\n",k->gpio_port,ret);
                        return -1;       
                }

                ret = gpio_direction_input(k->gpio_port);
                if(ret < 0)
                {
                        printk("can't config gpio!%d error:%d\n",k->gpio_port,ret);
                        return -1;
                }
        /*
                ret = gpio_set_debounce(k->gpio_port,2000);
                if(ret < 0)
                {
                        printk("can't set debounce!%d error:%d\n",k->gpio_port,ret);
                        return -1;
                }
        */
                irq = gpio_to_irq(k->gpio_port);

                irqflags = IRQF_SHARED | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
                if(irq < 0)
                {
                        printk("unable to get irq number for GPIO%d\n",k->gpio_port);
                        return -1;
                }
                else   
                        printk("get irq(%d) number for GPIO\n",irq);

                enable_irq(irq);

                ret = request_irq(irq,keyboard_interrupt,irqflags,k->desc,k);
                if(ret < 0)
                {
                        printk("can't request irq!%d error:%d\n",irq,ret);
                        return -1;               
                }

                printk("request resources ok!%d\n",i);
        }
        return 0;
}

/*释放按键中断*/
void keyboard_free_irqs(void)
{
        struct key_info *k;
        int i;
        for (i = 0; i < sizeof(key_info_tab) / sizeof(struct key_info); i++)
        {
                k = &key_info_tab;
                gpio_free(k->gpio_port);
                free_irq(gpio_to_irq(k->gpio_port), k);
                printk("free resources ok!%d\n",i);
        }
}

static int __init hello_init(void)
{
        int ret , i;

        ret=keyboard_request_irqs();
       
        /*初始化设备结构体*/
        keydevp=kmalloc(sizeof(struct key_dev),GFP_KERNEL);
        if(!keydevp)
                return - ENOMEM;
        memset(keydevp, 0, sizeof(struct key_dev));
        keydevp->head=keydevp->tail = 0;
        keydevp->miscdev=misc;
        for(i=0;i<KEY_NUM;i++)
                keydevp->keystatus = KEYSTATUS_UP;

        /*初始化等待队列*/
        init_waitqueue_head(&(keydevp->wq));
        /*初始化延时定时器*/
        for(i=0;i<KEY_NUM;i++)
                setup_timer(&key_timer,keyboard_timer_handler,i);

        /*注册misc设备*/
        ret = misc_register(&(keydevp->miscdev));
        if(ret!=0)
        {
                printk("init hello unsuccessfully!\n");
                return -1;
        }
        printk("hello init!\n");
      return 0;
}

static void __exit hello_exit(void)
{
        int i ;
        keyboard_free_irqs();
        for(i=0;i<KEY_NUM;i++)
                del_timer(&key_timer);
        kfree(keydevp);
        misc_deregister(&(keydevp->miscdev));
        printk("helloexit!\n");
}

MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
这是我的全部代码,照着一些书上的例子做的。

天嵌技术支持01 发表于 2014-1-11 16:20:31

taiyuankejizhu 发表于 2014-1-10 08:25
我先在也遇到了点问题,已经看过你说的board-am335xevm.c文件了,应该是在内核启动的时候对一些内 ...

请确认是否将我司做的led驱动例程删除
如没有删除会和你自己做的驱动例程会有冲突

taiyuankejizhu 发表于 2014-1-13 08:05:34

天嵌技术支持01 发表于 2014-1-11 16:20
请确认是否将我司做的led驱动例程删除
如没有删除会和你自己做的驱动例程会有冲突

(1)没有删除led的例程驱动删除,led的例程里也是将那两个管脚设为GPIO,不过是输出模式在board-am335xevm.c里面,led驱动加载阶段并没有申请这两个管脚,实在open()里面申请的,这样的话我想把这两个管脚作为中断输入不可以吗?相当于只改GPIO的输入输出模式,不可以的话这个gpio_direction_input()函数是干嘛的?
(2)如果要把那六个按键在am335xevm.c里配置成中断共享模式要怎么改呀?

天嵌技术支持01 发表于 2014-1-13 09:29:46

关于中断的使用,网上有很多资料。

天嵌技术支持01 发表于 2014-1-13 09:30:03

taiyuankejizhu 发表于 2014-1-13 08:05
(1)没有删除led的例程驱动删除,led的例程里也是将那两个管脚设为GPIO,不过是输出模式在board-am335xe ...

http://blog.csdn.net/droidphone/article/details/7445825
页: [1]
查看完整版本: AM3358的中断怎么设置的