打印

临时中断irq测试tasklet和workqueue的版本

[复制链接]
187|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Spikess|  楼主 | 2018-10-3 16:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Queue, ev, ic, ST, vi
#ifndef __IRQ_H__

#define __IRQ_H_



#include <linux/fs.h>

#include <linux/semaphore.h>

#include <linux/wait.h>

#include <linux/cdev.h>



#define IRQ_MAJOR 0

#define DEVICE_NAME "key"



struct key{

//    struct cdev cdev;

//    struct semaphore* sem;

    const char* name;

    unsigned long flags;

    unsigned int irq;

    unsigned int val;

};



struct irq_dev{

    struct cdev cdev;

    struct semaphore sem;

    wait_queue_head_t key_queue;

    struct key* pkey;

};



#endif



#include <linux/module.h>

#include <linux/slab.h>

#include <linux/device.h>

#include <mach/map.h>

#include <mach/regs-gpio.h>

#include <mach/gpio-bank-n.h>

#include <asm/io.h>

#include <asm/uaccess.h>

#include <linux/sched.h>

#include <linux/interrupt.h>

#include <mach/irqs.h>

#include <linux/irq.h>

#include <linux/time.h>

#include <linux/delay.h>

#include <linux/workqueue.h>



#include "irq.h"



#define IRQ_DEBUG

#ifdef IRQ_DEBUG

#define dprintk(fmt, arg...)     printk("###IRQ DEBUG###%s():"fmt, __func__, ##arg)

#else

#define dprintk(fmt, arg...)

#endif



static int irq_major = IRQ_MAJOR;

struct irq_dev* irq;

static struct key key={

    .name = "key0",

    .flags = IRQ_TYPE_EDGE_RISING,

    .irq = IRQ_EINT(0),

    .val = 0,

};



void tasklet(unsigned long data)

{

    dprintk("data=%d\n", data);

    dprintk("key!\n");

    dprintk("S3C64XX_EINT0PEND=0x%x\n", __raw_readl(S3C64XX_EINT0PEND));

    dprintk("S3C64XX_EINT0CON0=0x%x\n", __raw_readl(S3C64XX_EINT0CON0));

    dprintk("S3C64XX_EINT0CON1=0x%x\n", __raw_readl(S3C64XX_EINT0CON1));

    dprintk("S3C64XX_EINT0FLTCON0=0x%x\n", __raw_readl(S3C64XX_EINT0FLTCON0));

    dprintk("S3C64XX_EINT0FLTCON1=0x%x\n", __raw_readl(S3C64XX_EINT0FLTCON1));

    dprintk("S3C64XX_EINT0FLTCON2=0x%x\n", __raw_readl(S3C64XX_EINT0FLTCON2));

    dprintk("S3C64XX_EINT0FLTCON3=0x%x\n", __raw_readl(S3C64XX_EINT0FLTCON3));

    dprintk("S3C64XX_EINT0MASK=0x%x\n", __raw_readl(S3C64XX_EINT0MASK));

    dprintk("S3C64XX_SERVICEPEND=0x%x\n", __raw_readl(S3C64XX_SERVICEPEND));

   

    dprintk("VIC0IRQSTATUS=0x%x\n", __raw_readl(VA_VIC0));

    dprintk("VIC0FIQSTATUS=0x%x\n", __raw_readl(VA_VIC0 + 0x4));

    dprintk("VIC0VECTADDR0 =0x%x\n", __raw_readl(VA_VIC0 + 0x100));

    dprintk("VICxADDRESS =0x%x\n", __raw_readl(VA_VIC0 + 0xf00));

    dprintk("1:%x 2:%x 3:%x 4:%x\n", __raw_readl(VA_VIC0+0x008), __raw_readl(VA_VIC0+0x00c),

                                        __raw_readl(VA_VIC0+0x010),__raw_readl(VA_VIC0+0x014));

}



DECLARE_TASKLET(irq_tasklet, tasklet, 0);

static struct work_struct key_work;

void work_func(struct work_struct* data)

{

   

    dprintk("VIC0IRQSTATUS=0x%x\n", __raw_readl(VA_VIC0));

    dprintk("VIC0FIQSTATUS=0x%x\n", __raw_readl(VA_VIC0 + 0x4));

    dprintk("VIC0VECTADDR0 =0x%x\n", __raw_readl(VA_VIC0 + 0x100));

    dprintk("VICxADDRESS =0x%x\n", __raw_readl(VA_VIC0 + 0xf00));

    dprintk("work");

}



static irqreturn_t interrupt_handler(int irq, void* dev)

{

    writel(IRQ_EINT0_3, S3C64XX_EINT0PEND);  //clear interrupt flag

    tasklet_schedule(&irq_tasklet);

    return IRQ_HANDLED;

}



static irqreturn_t interrupt_handl(int irq, void* dev)

{

//    writel(IRQ_EINT0_3, S3C64XX_EINT0PEND);  //clear interrupt flag

    schedule_work(&key_work);

    return IRQ_HANDLED;

}



static int irq_open(struct inode* inode, struct file* filp)

{

    int err;

    dprintk("open!\n");

    filp->private_data = irq;

   

    dprintk("VIC0IRQSTATUS=0x%x\n", __raw_readl(VA_VIC0));

    dprintk("VIC0FIQSTATUS=0x%x\n", __raw_readl(VA_VIC0 + 0x4));

    dprintk("VIC0VECTADDR0 =0x%x\n", __raw_readl(VA_VIC0 + 0x100));

    dprintk("VICxADDRESS =0x%x\n", __raw_readl(VA_VIC0 + 0xf00));

   

    err = request_irq(irq->pkey->irq, interrupt_handler, irq->pkey->flags,

                               irq->pkey->name, (void*)irq);

    if(err)

        free_irq(irq->pkey->irq, (void*)irq);

    err = request_irq(IRQ_EINT(1), interrupt_handl, IRQ_TYPE_EDGE_FALLING,

                               "key1", NULL);

    if(err)

        free_irq(IRQ_EINT(1), NULL);

    return 0;

}



static int irq_close(struct inode* inode, struct file* filp)

{

    dprintk("close!\n");

    filp->private_data = irq;

    free_irq(irq->pkey->irq, (void*)irq);

    free_irq(IRQ_EINT(1), NULL);

    return 0;

}



static ssize_t irq_read(struct file* filp, char __user* buff, size_t count, loff_t* offp)

{

    struct irq_dev* irq = filp->private_data;

    if(down_interruptible(&irq->sem))

        return -ERESTARTSYS;

note:此处要实现阻塞,并在中断服务程序唤醒或者在中断服务中发出一个信号。

    up(&irq->sem);

    return count;

}





static const struct file_operations irq_fops = {

    .open           = irq_open,

    .release        = irq_close,

    .read              = irq_read,

};



static void irq_setup_cdev(struct irq_dev* dev, int index)

{

    int err, devno = MKDEV(irq_major, 0);

    cdev_init(&dev->cdev, &irq_fops);

    dev->cdev.owner = THIS_MODULE;

    err = cdev_add(&dev->cdev, devno, 1);

    if(err)

        printk("error add cdev!\n");

}



struct class* irq_class;

int irq_init(void)

{

    int result;

    dev_t devno = MKDEV(irq_major, 0);

    if(irq_major)

        result = register_chrdev_region(devno, 1, DEVICE_NAME);

    else{

        dprintk("alloc_chrdev_region\n");

        result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);

        irq_major = MAJOR(devno);

    }

    if(result < 0)

        return result;

    irq = kmalloc(sizeof(struct irq_dev), GFP_KERNEL);

    if(!irq){

        result = -ENOMEM;

        goto malloc_error;

    }

    memset(irq, 0, sizeof(struct irq_dev));

    irq_setup_cdev(irq, 0);

    init_MUTEX(&irq->sem);

    init_waitqueue_head(&irq->key_queue);

    irq->pkey = &key;

    INIT_WORK(&key_work, work_func);



    irq_class = class_create(THIS_MODULE, "irq_class");

    device_create(irq_class, NULL, MKDEV(irq_major, 0), NULL, "%s", DEVICE_NAME);

    return 0;

malloc_error:

    unregister_chrdev_region(devno, 1);

    return result;

}



void irq_exit(void)

{

    cdev_del(&irq->cdev);

    device_destroy(irq_class, MKDEV(irq_major, 0));

    class_destroy(irq_class);

    kfree(irq);

    unregister_chrdev_region(MKDEV(irq_major, 0), 1);

}



module_init(irq_init);

module_exit(irq_exit);



MODULE_LICENSE("GPL");

MODULE_AUTHOR("jf.s <jingfeng.shi@emdoor.com>");

这是一个临时irq测试tasklet和workqueue的版本,并测试了s3c6410的vic reg ,6410的vic reg貌似问题一大堆,等双休日再研究研究。

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

417

主题

421

帖子

0

粉丝