函数顺序
request_irq – request_threaded_irq – __setup_irq
ret = request_irq(RX_IRQ(port),w55fa93_serial_irq, 0,w55fa93_serial_portname(port), ourport);
各参数的意义 中断号 处理函数 标记 名称 可以是传递的参数可以是作为区分共享中断
request_threaded_irq 里面有对结构体struct irqaction *action;进行填充初始化。将中断处理程序赋值给这个结构体。
__setup_irq 继续将irq_desc结构体进行赋值,并将action放置在自己的irq_desc结构体中。在proc文件系统中创建相关目录。设置触发方式,并使能中断。
“arch/arm/mach-w55fa93/irq.c”文件中
void __init w55fa93_init_irq(void)
{int irqno;__raw_writel(0xFFFFFFFF, REG_AIC_MDCR);for (irqno = IRQ_WDT; irqno < NR_IRQS; irqno++) {set_irq_chip(irqno, &w55fa93_irq_chip);set_irq_handler(irqno, handle_level_irq);set_irq_flags(irqno, IRQF_VALID);}
}
屏蔽所有中断,然后统一接口赋值,chip handler flags给irq_desc结构体。
“arch/arm/mach-w55fa93/mach-w55fa93.c”
MACHINE_START(W55FA93, "W55FA93").phys_io = W55FA93_PA_UART,.io_pg_offst = (((u32)W55FA93_VA_UART) >> 18) & 0xfffc,
#ifdef CONFIG_INITRAMFS_ROOT_UID.boot_params = 0x0,
#else.boot_params = 0x100,
#endif.map_io = mach_w55fa93_map_io,.init_irq = w55fa93_init_irq,.init_machine = w55fa93_init,.timer = &w55fa93_timer,
MACHINE_END#define MACHINE_START(_type,_name)
static const struct machine_desc __mach_desc_##_type __used __attribute__((__section__(".arch.info.init"))) = { .nr = MACH_TYPE_##_type, .name = _name,#define MACHINE_END
};
将w55fa93_init_irq赋值给machine_desc结构体
void __init setup_arch(char **cmdline_p)
{struct tag *tags = (struct tag *)&init_tags;struct machine_desc *mdesc;char *from = default_command_line;unwind_init();setup_processor();mdesc = setup_machine(machine_arch_type);machine_name = mdesc->name;if (mdesc->soft_reboot)reboot_setup("s");if (__atags_pointer)tags = phys_to_virt(__atags_pointer);else if (mdesc->boot_params)tags = phys_to_virt(mdesc->boot_params);/** If we have the old style parameters, convert them to* a tag list.*/if (tags->hdr.tag != ATAG_CORE)convert_to_tag_list(tags);if (tags->hdr.tag != ATAG_CORE)tags = (struct tag *)&init_tags;if (mdesc->fixup)mdesc->fixup(mdesc, tags, &from, &meminfo);if (tags->hdr.tag == ATAG_CORE) {if (_banks != 0)squash_mem_tags(tags);save_atags(tags);parse_tags(tags);}init_mm.start_code = (unsigned long) _text;d_code = (unsigned long) _etext;d_data = (unsigned long) _edata;init_mm.brk = (unsigned long) _end;/* parse_early_param needs a boot_command_line */strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);*cmdline_p = cmd_line;parse_early_param();paging_init(mdesc);request_standard_resources(&meminfo, mdesc);#ifdef CONFIG_SMPsmp_init_cpus();
#endifcpu_init();tcm_init();/** Set up various architecture-specific pointers*/init_arch_irq = mdesc->init_irq;system_timer = mdesc->timer;init_machine = mdesc->init_machine;#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)conswitchp = &dummy_con;
#endif
#endifearly_trap_init();
}
这个函数中实现了赋值init_arch_irq = mdesc->init_irq;
void __init init_IRQ(void)
{int irq;for (irq = 0; irq < NR_IRQS; irq++)irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;init_arch_irq();
}
init_arch_irq()被init_IRQ函数调用,而init_IRQ的实现就是在start_kernel中。
当发生中断时
首先异常向量表,保存一条跳转指令,一般存放在0x00000000或者0xffff000地址,linux使用后者,中断发生后CPU进入异常模式,将跳转到相应的异常向量表处执行,异常向量表保存跳转指令,经过一段汇编,最后跳转到中断的入口asm_do_IRQ
asm_do_IRQ – generic_handle_irq – generic_handle_irq_desc – desc->handle_irq(irq, desc) – handle_IRQ_event – action->handler
最后到达此irq的desc结构体的handle_irq函数。即在w55fa93_init_irq中给desc结构体的赋值。
set_irq_handler(irqno, handle_level_irq);
handle_level_irq这个函数分析
void
handle_level_irq(unsigned int irq, struct irq_desc *desc)
{struct irqaction *action;irqreturn_t action_ret;raw_spin_lock(&desc->lock);mask_ack_irq(desc, irq); 屏蔽并清中断if (unlikely(desc->status & IRQ_INPROGRESS))goto out_unlock;desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);kstat_incr_irqs_this_cpu(irq, desc); 中断统计计数 /** If its disabled or no action available* keep it masked and get out of here*/action = desc->action; 取出action这个结构体if (unlikely(!action || (desc->status & IRQ_DISABLED)))goto out_unlock;desc->status |= IRQ_INPROGRESS; 标记中断状态raw_spin_unlock(&desc->lock);action_ret = handle_IRQ_event(irq, action); 处理中断if (!noirqdebug)note_interrupt(irq, desc, action_ret);raw_spin_lock(&desc->lock);desc->status &= ~IRQ_INPROGRESS;if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT)))unmask_irq(desc, irq);
out_unlock:raw_spin_unlock(&desc->lock);
}
EXPORT_SYMBOL_GPL(handle_level_irq);
本文发布于:2024-01-29 13:56:53,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170650781515763.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |