【转】linux中断流程详解
来源:互联网 发布:淘宝店铺装修首页全屏 编辑:程序博客网 时间:2024/05/17 01:05
参考 :http://blog.csdn.net/yimu13/article/details/6803957
中断早期初始化
1. irq_desc[]
struct irq_desc { struct irq_data irq_data; struct timer_rand_state *timer_rand_state; unsigned int __percpu *kstat_irqs; irq_flow_handler_t handle_irq;#ifdef CONFIG_IRQ_PREFLOW_FASTEOI irq_preflow_handler_t preflow_handler;#endif struct irqaction *action; /* IRQ action list */ unsigned int status_use_accessors; unsigned int core_internal_state__do_not_mess_with_it; unsigned int depth; /* nested irq disables */ unsigned int wake_depth; /* nested wake enables */ unsigned int irq_count; /* For detecting broken IRQs */ unsigned long last_unhandled; /* Aging timer for unhandled count */ unsigned int irqs_unhandled; raw_spinlock_t lock;#ifdef CONFIG_SMP const struct cpumask *affinity_hint; struct irq_affinity_notify *affinity_notify;#ifdef CONFIG_GENERIC_PENDING_IRQ cpumask_var_t pending_mask;#endif#endif unsigned long threads_oneshot; atomic_t threads_active; wait_queue_head_t wait_for_threads;#ifdef CONFIG_PROC_FS struct proc_dir_entry *dir;#endif const char *name;}extern struct irq_desc irq_desc[NR_IRQS];#define NR_IRQS (GODNET_IRQ_START + 96)#define GODNET_IRQ_START (32)
GIC控制器,有PPI、SGI、SPI
SPI 共享外设中断号大于32.
2.
在内核早期初始化的时候,machine_desc会初始化gic_irq。
并且在别的函数(irq_set_handler)里设置irq_desc[]–>handle_irq。这个handle_irq后面会用得到。
==========================
下面是中断执行流程:
中断异常向量表:
1 在 arch/arm/kernel/entry-armv.S 中定义了宏 irq_handler
irq_handler里面会执行arch_irq_handler_default–》asm_do_IRQ
6 .macro arch_irq_handler_default 7 get_irqnr_preamble r5, lr 8 1: get_irqnr_and_base r0, r6, r5, lr 9 movne r1, sp 10 @ 11 @ routine called with r0 = irq number, r1 = struct pt_regs * 12 @ 13 adrne lr, BSYM(1b) 14 bne asm_do_IRQ
无论是gic 控制器,还是别的中断控制器,都会执行到asm_do_IRQ
下面分析asm_do_IRQ 不
`asmlinkage void __exception_irq_entry
asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);//18个寄存器,保存参数irq_enter();
/*
- Some hardware gives randomly wrong interrupts. Rather
- than crashing, do something sensible.
*/
if (unlikely(irq >= nr_irqs)) {
if (printk_ratelimit())
printk(KERN_WARNING “Bad IRQ%u\n”, irq);
ack_bad_irq(irq);
} else {
generic_handle_irq(irq);
}
/* AT91 specific workaround */
irq_finish(irq);irq_exit();
set_irq_regs(old_regs);
}`
int generic_handle_irq(unsigned int irq){ struct irq_desc *desc = irq_to_desc(irq); if (!desc) return -EINVAL; generic_handle_irq_desc(irq, desc); return 0;}
static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc){ desc->handle_irq(irq, desc);}
这里的desc_handle_rq就是内核早期初始化的时候设置的函数。
如有的平台是handle_level_irq
这函数会调用 handle_irq_event(desc);
irqreturn_t handle_irq_event(struct irq_desc *desc){ struct irqaction *action = desc->action; irqreturn_t ret; desc->istate &= ~IRQS_PENDING; irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); raw_spin_unlock(&desc->lock); ret = handle_irq_event_percpu(desc, action); raw_spin_lock(&desc->lock); irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS); return ret;}irqreturn_thandle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action){ irqreturn_t retval = IRQ_NONE; unsigned int random = 0, irq = desc->irq_data.irq; do { irqreturn_t res; trace_irq_handler_entry(irq, action); res = action->handler(irq, action->dev_id); trace_irq_handler_exit(irq, action, res); if (WARN_ONCE(!irqs_disabled(),"irq %u handler %pF enabled interrupts\n", irq, action->handler)) local_irq_disable(); switch (res) { case IRQ_WAKE_THREAD: /* * Catch drivers which return WAKE_THREAD but * did not set up a thread function */ if (unlikely(!action->thread_fn)) { warn_no_thread(irq, action); break; } irq_wake_thread(desc, action); /* Fall through to add to randomness */ case IRQ_HANDLED: random |= action->flags; break; default: break; } retval |= res; action = action->next; } while (action); if (random & IRQF_SAMPLE_RANDOM) add_interrupt_randomness(irq); if (!noirqdebug) note_interrupt(irq, desc, retval); return retval;}
由此找到了action->handler.
里面还会根据handler的返回值,如果是IRQ_WAKE_THREAD则唤醒中断线程。
那么这个handler是什么?
request_irq->request_threaded_irq-
if (!action) return -ENOMEM; action->handler = handler; action->thread_fn = thread_fn; action->flags = irqflags; action->name = devname; action->dev_id = dev_id; chip_bus_lock(desc); retval = __setup_irq(irq, desc, action); chip_bus_sync_unlock(desc);
在__setup_irq里添加action到desc[]的action链表中。
然后遍历这个表,最终执行的就是中断申请的时候使用的handler。
- 【转】linux中断流程详解
- linux中断流程详解
- linux中断流程详解
- linux中断流程详解
- linux中断流程详解
- linux中断流程详解
- linux中断流程详解
- Linux中断处理流程
- linux 中断处理流程
- Linux中断处理流程
- Linux中断处理流程
- Linux中断处理流程
- Linux中断处理流程
- Linux中断处理流程
- Linux中断流程分析
- linux中断流程
- Exynos4412 中断处理流程详解
- Exynos4412 中断处理流程详解
- Linux下进程通信
- codeforces809A Do you want a date?
- 1117. Eddington Number(25)[基础逻辑题]
- 丽娃河的狼人传说
- java小类型向大类型转化
- 【转】linux中断流程详解
- Spring 使用工厂方法实例化对象
- java 集合
- ACM搞得不太好,还有必要吗?
- 日你吗,JS
- Android 串口通讯-------android -serialport-api
- 使用SQLite数据库<增,删,改,查>
- LeetCode 141. Linked List Cycle
- nyoj 635 Oh, my goddess 优先队列+BFS