arm linux 下中断流程简要分析初始化
因此,在中断初始化的时候我们要做的就是在IRQ和FIQ的位置处放置我们的中断处理函数地址或跳转语句跳转到我们的中断处理函数。这个过程是在trap_init中完成的,而他由start_kernel()调用。
arch/arm/kernel/traps.c:
void __init trap_init(void)
{
unsigned long vectors = CONFIG_VECTORS_BASE;/*跳转表的存放位置(即上面那表的存放位置)*/
/*这些都在entry-armv.S下定义*/
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
extern char __kuser_helper_start[], __kuser_helper_end[];
int kuser_sz = __kuser_helper_end - __kuser_helper_start;
/*
* Copy the vectors, stubs and kuser helpers (in entry-armv.S)
* into the vector page, mapped at 0xffff0000, and ensure these
* are visible to the instruction stream.
*/
/*跳转表内容到指定的位置*/
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
/*
* Copy signal return handlers into the vector page, and
* set sigreturn to be a pointer to these.
*/
memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
sizeof(sigreturn_codes));
flush_icache_range(vectors, vectors + PAGE_SIZE);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}
上面这个函数主要就是在CONFIG_VECTORS_BASE处设置好那张跳转表,CONFIG_VECTORS_BASE在autoconf.h中定义(该文件自动成生),值为0xffff0000,而CP15下的r1[13]在系统启动的时候在汇编部分就已经设置好了。
接下来我们就看下__vectors_start,__vectors_end,__stubs_start,__stubs_end之间的内容。
arch/arm/kernel/entry-armv.S:
.globl__vectors_start
__vectors_start:
swiSYS_ERROR0
bvector_und + stubs_offset
ldrpc, .LCvswi + stubs_offset
bvector_pabt + stubs_offset
bvector_dabt + stubs_offset
bvector_addrexcptn + stubs_offset
bvector_irq + stubs_offset
bvector_fiq + stubs_offset
.globl__vectors_end
__vectors_end:
.data
看到了吧, 就是那张跳转表。vector_irq,vector_fiq等函数我们后面在分析,他们就定义在__stubs_start,__stubs_end中。
至此经过traps_init后,在0xffff0000处的跳转表就形成了。当产生IRQ时,将调用bvector_irq + stubs_offset
在系统初始化的时候还会调用init_IRQ函数(也由start_kernel调用),它初始化了一个全局中断描述符表(该表保存了每个中断的所有属性信息)。并调用特定平台的中断初始化函数。
arm/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();/*特定平台的中断初始化*/
}
系统中总共有NR_IRQS个中断,并且每个中断都有一个中断描述符,保存在irq_desc中,该描述符保存了该中断的所有属性信息。
对于平台smdk2410来说init_arch_irq()就是s3c24xx_init_irq()函数,这是在setup_arch()里面赋值的。
后面的内容我们都以中断号:IRQ_WDT为例来讲解:
arch/arm/mach-s3c2410/Irq.c:
/* s3c24xx_init_irq
*
* Initialise S3C2410 IRQ system
*/
void __init s3c24xx_init_irq(void)
{
unsigned long pend;
unsigned long last;
int irqno;
int i;
irqdbf("s3c2410_init_irq: clearing interrupt status flags/n");
/* first, clear all interrupts pending... */
/*先清掉所有的pending标志位,该位代表是否系统中触发了一个中断*/
last = 0;
for (i = 0; i < 4; i++) {
pend = __raw_readl(S3C24XX_EINTPEND);
if (pend == 0 || pend == last)
break;
__raw_writel(pend, S3C24XX_EINTPEND);
printk("irq: clearing pending ext status %08x/n", (int)pend);
last = pend;
}
last = 0;
for (i =
armlinux中断流程初始 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)