linux中断处理体系结构分析(一),linux中断处理体系结构

重要的数据结构

struct irq_desc {

irq_flow_handler_t    handle_irq;

/*

当前中断处理函数入口

*/

struct irq_chip        *chip;

/*

底层的硬件访问

*/

struct irqaction①    *action;

/*

用户提供的中断处理函数链表

*/

unsigned

int        status;

/*

IRQ status

*/

const

char        *name;

/*

中断名称

*/

} ____cacheline_internodealigned_in_smp;

struct irqaction ①{

irq_handler_t handler;

//

中断处理函数

unsigned

long flags;

/*

中断标志:是否共享中断,电平触发,边缘触发。。。

*/

const

char *name;

/*

/pro/interrupts 下显示

*/

void *dev_id;

struct irqaction *next;

/*

链表  指向下一个

*/

int irq;

/*

中断号

*/

struct proc_dir_entry *dir;

irq_handler_t thread_fn;

struct task_struct *thread;

unsigned

long thread_flags;

};

void __init start_kernel(

void)

//

linux c语言入口

{

setup_arch(

char **cmdline_p);

init_IRQ();

{

//

初始化状态

for (irq =

0; irq 

irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;

init_arch_irq();

{

1.ask:    不同架构的处理器中断初始化函数是不一样的,该函数中怎么去处理?

1.answer: 在arch\arm\kernel\Setup.c中

struct machine_desc * mdesc = setup_machine(machine_arch_type);

init_arch_irq = mdesc->init_irq;

mdesc->init_irq在哪里定义?

架构相关: arch\arm\mach-s3c2440\mach-smdk2440.c

MACHINE_START(TCT_HAMMER,

"

TCT_HAMMER

")

.phys_io    = S3C2410_PA_UART,

.io_pg_offst    = (((u32)S3C24XX_VA_UART) >>

18) &

0xfffc,

.boot_params    = S3C2410_SDRAM_PA +

0x100,

.map_io        = tct_hammer_map_io,

.init_irq    = s3c24xx_init_irq,

//

.init_machine    = tct_hammer_init,

.timer        = &s3c24xx_timer,

MACHINE_END

2.ask:    s3c24xx_init_irq 做了什么处理?

2.answer: arch\arm\plat-s3c24xx\Irq.c

for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {

//

(1)设置芯片

set_irq_chip(irqno, &s3c_irq_chip);

{

struct irq_desc *desc = irq_to_desc(irq);

desc->chip = chip;

//

填充chip

}

//

(2)设置处理函数

set_irq_handler(irqno, handle_edge_irq);

{

__set_irq_handler(irq, handle,

0, NULL);

__set_irq_handler(unsigned

int irq, irq_flow_handler_t handle,

int is_chained,

const

char *name)

{

desc->handle_irq = handle;

//

处理函数

desc->name = name;

//

NULL

}

}

//

(3)IRQF_VALID表示可以使用它们了

set_irq_flags(irqno, IRQF_VALID);

}

set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);

{

__set_irq_handler(irq, handle,

1, NULL);

}

set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);

set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);

set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);

set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);

set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);

}

}

}

用户注册中断过程分析

include\linux\Interrupt.h

static inline

int __must_check

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

}

request_threaded_irq 分析

kernel\irq\Manage.c

/*

*

*    request_threaded_irq - allocate an interrupt line

*    @irq: Interrupt line to allocate

*    @handler: Function to be called when the IRQ occurs.

*          Primary handler for threaded interrupts

*          If NULL and thread_fn != NULL the default

*          primary handler is installed

*    @thread_fn: Function called from the irq handler thread

*            If NULL, no irq thread is created

*    @irqflags: Interrupt type flags

*    @devname: An ascii name for the claiming device

*    @dev_id: A cookie passed back to the handler function

*/

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;

//

中断描述数组

action = kzalloc(

sizeof(

struct irqaction), GFP_KERNEL);

action->handler = handler;

//

中断处理程序

action->thread_fn = thread_fn;

action->flags = irqflags;

action->name = devname;

action->dev_id = dev_id;

desc = irq_to_desc(irq);

//

获取到相应的中断描述

__setup_irq(irq, desc, action);

__setup_irq(unsigned

int irq,

struct irq_desc *desc,

struct irqaction *

new)

{

old_ptr = &desc->action;

old = *old_ptr;

do {

old_ptr = &old->next;

old = *old_ptr;

}

while (old);

//

找到用户中断处理函数的最后一个

*old_ptr =

new;

irq_chip_set_defaults(desc->chip);

//

设置触发方式

__irq_set_trigger(desc, irq,

new->flags & IRQF_TRIGGER_MASK);

new->irq = irq;

//

启动中断

desc->chip->startup(irq);

}

}

当IRQ中断发生时:C语言入口函数asm_do_IRQ

void __exception asm_do_IRQ(unsigned

int irq,

struct pt_regs *regs)

{

generic_handle_irq(irq);

{

generic_handle_irq_desc(irq, irq_to_desc(irq));

{

//

irq 中断号 , irq_to_desc(irq)中断描述

desc->handle_irq(irq, desc);

1.ask 这是怎么处理的?

2.answer 例子: desc初始化的时候

set_irq_handler(irqno, handle_edge_irq);

//

执行的是handle_edge_irq

void handle_edge_irq(unsigned

int irq,

struct irq_desc *desc)

{

do {

struct irqaction *action = desc->action;

handle_IRQ_event(irq, action);

{

do {

//

★ 逐个调用用户在action链表中注册的处理函数

ret = action->handler(irq, action->dev_id);

action = action->next;

}

while (action);

}

}

while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);

}

}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值