微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux中断机制之中断的申请

ARM Linux中断机制之中断的申请

时间:11-10 来源:互联网 点击:
底层硬件操作方法

每一条中断线都有一个底层硬件操作函数集struct irq_chip 。大多数控制方法都是重复的 ,基本上只要有中断响应 、 中断屏蔽 、 中断开启 、 中断触发类型设置等方法就可以满足要求了。其他各种方法基本上和这些相同。

这些操作方法的实现在文件linux/arch/arm/plat-s3c24xx/irq.c中。

例如外部中断 IRQ_EINT0 ~ IRQ_EINT3都用以下操作函数集:

static struct irq_chip s3c_irq_eint0t4 = {
.name= "s3c-ext0",
.ack= s3c_irq_ack,
.mask= s3c_irq_mask,
.unmask= s3c_irq_unmask,
.set_wake= s3c_irq_wake,
.set_type= s3c_irqext_type,
};

/********************中断响应******************************/

static inline void
s3c_irq_ack(unsigned int irqno)
{
unsigned long bitval = 1UL < (irqno - IRQ_EINT0);

__raw_writel(bitval, S3C2410_SRCPND);
__raw_writel(bitval, S3C2410_INTPND);
}

/********************中断屏蔽******************************/

static void
s3c_irq_mask(unsigned int irqno)
{
unsigned long mask;

irqno -= IRQ_EINT0;

mask = __raw_readl(S3C2410_INTMSK);
mask |= 1UL < irqno;
__raw_writel(mask, S3C2410_INTMSK);
}

/********************中断开启******************************/

static void
s3c_irq_unmask(unsigned int irqno)
{
unsigned long mask;

if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
irqdbf2("s3c_irq_unmask %d\n", irqno);

irqno -= IRQ_EINT0;

mask = __raw_readl(S3C2410_INTMSK);
mask &= ~(1UL < irqno);
__raw_writel(mask, S3C2410_INTMSK);
}

/********************中断触发类型设置******************************/

int
s3c_irqext_type(unsigned int irq, unsigned int type)
{
void __iomem *extint_reg;
void __iomem *gpcon_reg;
unsigned long gpcon_offset, extint_offset;
unsigned long newvalue = 0, value;

if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
{
gpcon_reg = S3C2410_GPFCON;
extint_reg = S3C24XX_EXTINT0;
gpcon_offset = (irq - IRQ_EINT0) * 2;
extint_offset = (irq - IRQ_EINT0) * 4;
}
。。。。。。

__raw_writel(value, gpcon_reg);//将对应管脚配置成中断功能

switch (type)
{
case IRQ_TYPE_NONE:
printk(KERN_WARNING "No edge setting!\n");
break;

case IRQ_TYPE_EDGE_RISING:
newvalue = S3C2410_EXTINT_RISEEDGE;
break;

case IRQ_TYPE_EDGE_FALLING:
newvalue = S3C2410_EXTINT_FALLEDGE;
break;

case IRQ_TYPE_EDGE_BOTH:
newvalue = S3C2410_EXTINT_BOTHEDGE;
break;

case IRQ_TYPE_LEVEL_LOW:
newvalue = S3C2410_EXTINT_LOWLEV;
break;

case IRQ_TYPE_LEVEL_HIGH:
newvalue = S3C2410_EXTINT_HILEV;
break;

default:
printk(KERN_ERR "No such irq type %d", type);
return -1;
}

value = __raw_readl(extint_reg);
value = (value & ~(7 < extint_offset)) | (newvalue < extint_offset);
__raw_writel(value, extint_reg);//设置中断的触发方式。

return 0;
}

中断申请函数

//中断申请函数request_irq()只是函数request_threaded_irq()的包装而已
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id)
{
struct irqaction *action;
struct irq_desc *desc;
int retval;

//中断类型标识IRQF_SHARED和IRQF_DISABLED不应当被同时设置。
if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) ==
(IRQF_SHARED|IRQF_DISABLED)) {
pr_warning(
"IRQ %d/%s: IRQF_DISABLED is not guaranteed on shared IRQs\n",
irq, devname);
}

#ifdef CONFIG_LOCKDEP
/*
* Lockdep wants atomic interrupt handlers:
*/
irqflags |= IRQF_DISABLED;
#endif
/*
* Sanity-check: shared interrupts must pass in a real dev-ID,
* otherwise well have trouble later trying to figure out
* which interrupt is which (messes up the interrupt freeing
* logic etc).
*/
if ((irqflags & IRQF_SHARED) && !dev_id)
return -EINVAL;

desc = irq_to_desc(irq);//根据中断号获取中断线描述符结构体
if (!desc)
return -EINVAL;

if (desc->status & IRQ_NOREQUEST)
return -EINVAL;
if (!handler)
return -EINVAL;

上一篇:stm32之NVIC
下一篇:arm和armel的差异

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top