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

#ifndef __IRQ_H__

#define __IRQ_H_

#include

#include

#include

#include

#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

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#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 ");

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值