yiffer的个人空间 https://blog.eetop.cn/edesign [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

Kernel硬件中断的初始化流程

已有 1036 次阅读| 2010-7-21 22:15 |个人分类:Linux移植

Porting kernel到一个全新的开发板时,通常hardware irq的初始化函数是要我们自己实现的。
那我们实现了自己硬件的中断初始化函数之后,内核是如何调用到它的呢?内核有自己的一套支持多平台的架构。

下面我们分析内核中断初始化的过程以及如何调用到一个新平台的irq初始化函数。
这里我们以s3c2410平台为例,他的中断初始化函数定义在:
/* arch/arm/mach-s3c2410/irq.c */
void __init s3c24xx_init_irq(void)
{
……
}
 
在arch/arm/mach-s3c2410/mach-smdk2410.c内通过MACHINE_START宏将s3c24xx_init_irq赋值给mach_desc结构体的.init_irq成员。
 

MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
        * to SMDK2410 */

 /* Maintainer: Jonas Dietsche */
 .phys_io = S3C2410_PA_UART,
 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 .boot_params = S3C2410_SDRAM_PA + 0x100,
 .map_io = smdk2410_map_io,
 .init_irq = s3c24xx_init_irq,
 .init_machine = smdk_machine_init,
 .timer = &s3c24xx_timer,
MACHINE_END


注:MACHINE_START宏的作用是对mach_desc结构体进行初始化。mach_desc里定义了一些关键的体系架构相关的函数。Porting kernel到新平台时,这个结构体是非常关键的。
 
init_irq这个成员在系统初始化的时候会被赋值给init_arch_irq全局变量,如下:

/* arch/arm/kernel/setup.c */
void __init setup_arch(char **cmdline_p)
{
 ……
 cpu_init();
 
/*
  * Set up various architecture-specific pointers
  */

 init_arch_irq = mdesc->init_irq;
 system_timer = mdesc->timer;
 init_machine = mdesc->init_machine;
 ……
}


注:可以看到这里不仅初始化了init_arch_irq 全局变量,同时初始化了system_timer,init_machine等全局变量。这是kernel支持多平台的一种机制。当然这里system_timer和init_machine我不多描述,有兴趣的可以大家自己去看。机制和init_arch_irq大同小异。
 
init_arch_irq函数指针定义在体系架构无关的arch/arm/kernel/irq.c内
/* arch/arm/kernel/irq.c */
void (*init_arch_irq)(void) __initdata = NULL;
 
并且在init_IRQ函数内会去执行它。

/* arch/arm/kernel/irq.c */
void __init init_IRQ(void)
{
 int irq;
 for (irq = 0; irq < NR_IRQS; irq++)
  irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_DELAYED_DISABLE |
   IRQ_NOPROBE;
#ifdef CONFIG_SMP
 bad_irq_desc.affinity = CPU_MASK_ALL;
 bad_irq_desc.cpu = smp_processor_id();
#endif
 init_arch_irq();
}

 
那init_IRQ在哪里被调用呢? 我们猜想肯定是在系统初始化的时会调用它。
实际结果也正是,init_IRQ会在init/main.c里的start_kernel函数内被调用:
asmlinkage void __init start_kernel(void)
{
 ……
 trap_init();
 rcu_init();
 init_IRQ();
 pidhash_init();
 clockevents_init();
 init_timers();
 ……
}
这样,我们定义的新平台irq初始化函数就会在系统启动时被调用,对我们的硬件中断进行初始化后再去使用它。这里搞清楚了,再porting其他东西如GP Timer Driver等到新平台就变得清晰多了。

点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 3

    粉丝
  • 0

    好友
  • 19

    获赞
  • 69

    评论
  • 3705

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-3-29 00:16 , Processed in 0.014430 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部