====本文系本站原創,歡迎轉載! 轉載請註明出處: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();#endifinit_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 <ben@fluff.org> */ .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)
至此,中斷的初始化過程完成了,那麼它是怎樣工作的,具體的流程由如何,各中斷函數的回呼函數怎麼理解,下文將繼續深入探討。。。