ARM-Linux s3c2440 之中断分析(二)

====本文系本站原创,欢迎转载! 转载请注明出处:http://blog.csdn.net/yyplc====

软件篇:

       上一篇文章回顾了s3c2440的中断控制器原理的相关硬件知识,有了这个基础再来分析Linux中的软件分析方式,心里就有底了。面对浩瀚如海的Linux源代码,s3c2440的中断到底是怎样呢,如何处理,如何实现的呢?一步一步来揭开它神秘的面纱吧,当然需要从Linux内核源码入手!

 

在Linux中start_kernel()时会进行体系结构的初始化:init_IRQ(), 故名思议,其源代码如下:

void __init init_IRQ(void)
{
       intirq;
 
       for(irq = 0; irq < NR_IRQS; irq++)
              irq_desc[irq].status|= IRQ_NOREQUEST | IRQ_NOPROBE;
 
#ifdef CONFIG_SMP
       cpumask_setall(bad_irq_desc.affinity);
bad_irq_desc.cpu= smp_processor_id();
#endif
init_arch_irq();    //这里是系统初始化irq的入口
}

init_arch_irq()初始值为:void (*init_arch_irq)(void)__initdata = NULL; 相当于一个变量函数(函数就像变量一样,被赋值),默认值为NULL,那么在其他地方应该被再次赋值。其实在setup_arch()中init_arch_irq()已经有所指向了,在arch/arm/kernel/setup.c中setup_arch进行体系平台相关初始化:

void __init setup_arch(char **cmdline_p)
{
       structtag *tags = (struct tag *)&init_tags;
       structmachine_desc *mdesc;
       char*from = default_command_line;
 
       unwind_init();
 
       setup_processor();
       mdesc= setup_machine(machine_arch_type);
       machine_name= mdesc->name;
…
       cpu_init();
…
       init_arch_irq= mdesc->init_irq;   //这里是init_arch_irq()指向的函数
       system_timer= mdesc->timer;
       init_machine= mdesc->init_machine;
…
early_trap_init()   //初始化中断向量表
}

mdesc是一个struct machine_desc的数据结构,msdesc 通过 setup_machine(machine_arch_type) 获取平台体系的MACHINE_START相关参数。

#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                            \
};

这个参数如下:

MACHINE_START(S3C2440, "SMDK2440")
       /*Maintainer: Ben Dooks <[email protected]> */
       .phys_io         = S3C2410_PA_UART,
       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) &0xfffc,
       .boot_params  = S3C2410_SDRAM_PA + 0x100,
 
       .init_irq          = s3c24xx_init_irq,    //这里是目标CPU的irq初始化函数
       .map_io          = smdk2440_map_io,
       .init_machine  = smdk2440_machine_init,
       .timer             = &s3c24xx_timer,
MACHINE_END

可见s3c24xx_init_irq()才是所要找得中断初始化入口程序,所以执行init_arch_irq()实际是执行s3c24xx_init_irq()程序。中断的初始化工作:首先,清空各interrupt pending的值,然后再向系统注册主要的中断,从上篇中我们知道s3c2440有60个中断,但系统中主要用了58个中断,

注册中断主要用下面三个函数:

int set_irq_chip(unsigned int irq, structirq_chip *chip)
static inline void set_irq_handler(unsigned intirq, irq_flow_handler_t handle)
static inline void set_irq_chained_handler(unsignedint irq, irq_flow_handler_t handle)

至此,中断的初始化过程完成了,那么它是怎样工作的,具体的流程由如何,各中断函数的回调函数怎么理解,下文将继续深入探讨。。。


你可能感兴趣的:(数据结构,c,linux,timer,struct,linux内核)