ARM Linux中断分析以s3c2410为例Word文档下载推荐.docx
《ARM Linux中断分析以s3c2410为例Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《ARM Linux中断分析以s3c2410为例Word文档下载推荐.docx(11页珍藏版)》请在冰豆网上搜索。
![ARM Linux中断分析以s3c2410为例Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2022-11/25/4edb2e3d-00dc-42e6-ba5e-37ce3e936429/4edb2e3d-00dc-42e6-ba5e-37ce3e9364291.gif)
*setsigreturntobeapointertothese.
memcpy((void*)KERN_SIGRETURN_CODE,sigreturn_codes,
sizeof(sigreturn_codes));
flush_icache_range(vectors,vectors+PAGE_SIZE);
modify_domain(DOMAIN_USER,DOMAIN_CLIENT);
init_IRQ对irq进行初始化时,又调用了init_arch_irq对于具体平台体系的中断进行初始化。
而init_arch_irq是在start_kernel里调用setup_arch函数设定的
/*arch/arm/kernel/irq.cn*/
void__initinit_IRQ(void)
intirq;
for(irq=0;
irq<
NR_IRQS;
irq++)
irq_desc[irq].status|=IRQ_NOREQUEST|IRQ_NOPROBE;
#ifdefCONFIG_SMP
bad_irq_desc.affinity=CPU_MASK_ALL;
bad_irq_desc.cpu=smp_processor_id();
#endif
init_arch_irq();
setup_arch里指定了具体平台体系的中断初始化函数,其中mdesc是一个machine_desc结构体指针
/*arch/arm/kernel/setup.c*/
void__initsetup_arch(char**cmdline_p)
init_arch_irq=mdesc->
init_irq;
machine_desc是用于描述平台体系(处理器芯片)的结构体,其定义如下:
/*include/asm/mach/arch.h*/
structmachine_desc{
*Note!
Thefirstfourelementsareused
*byassemblercodeinhead-armv.S
unsignedintnr;
/*architecturenumber*/
unsignedintphys_io;
/*startofphysicalio*/
unsignedintio_pg_offst;
/*byteoffsetforio
*pagetabeentry*/
constchar*name;
/*architecturename*/
unsignedlongboot_params;
/*taggedlist*/
unsignedintvideo_start;
/*startofvideoRAM*/
unsignedintvideo_end;
/*endofvideoRAM*/
unsignedintreserve_lp0:
1;
/*neverhaslp0*/
unsignedintreserve_lp1:
/*neverhaslp1*/
unsignedintreserve_lp2:
/*neverhaslp2*/
unsignedintsoft_reboot:
/*softreboot*/
void(*fixup)(structmachine_desc*,
structtag*,char**,
structmeminfo*);
void(*map_io)(void);
/*IOmappingfunction*/
void(*init_irq)(void);
structsys_timer*timer;
/*systemticktimer*/
void(*init_machine)(void);
};
*Setofmacrostodefinearchitecturefeatures.Thisisbuiltinto
*atablebythelinker.
#defineMACHINE_START(_type,_name)\
staticconststructmachine_desc__mach_desc_##_type\
__used\
__attribute__((__section__("
.arch.info.init"
)))={\
.nr=MACH_TYPE_##_type,\
.name=_name,
#defineMACHINE_END\
对于s3c2410处理器芯片,其machine_desc变量的定义如下:
/*arch/arm/mach-s3c2410/mach-smdk2410.c*/
MACHINE_START(SMDK2410,"
SMDK2410"
)/*@TODO:
requestanewidentifierandswitch
*toSMDK2410*/
/*Maintainer:
JonasDietsche*/
.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=smdk2410_init,
.timer=&
s3c24xx_timer,
MACHINE_END
接下来,我们看看s3c2410处理器芯片的irq初始化函数
/*arch/arm/plat-s3c24xx/irq.c*/
/*s3c24xx_init_irq
*
*InitialiseS3C2410IRQsystem
/*s3c24xx系列芯片中断初始化函数*/
void__inits3c24xx_init_irq(void)
unsignedlongpend;
unsignedlonglast;
intirqno;
inti;
irqdbf("
s3c2410_init_irq:
clearinginterruptstatusflags\n"
);
/*first,clearallinterruptspending...*/
/*清空各个中断请求信号*/
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:
clearingpendingextstatus%08x\n"
(int)pend);
last=pend;
pend=__raw_readl(S3C2410_INTPND);
__raw_writel(pend,S3C2410_SRCPND);
__raw_writel(pend,S3C2410_INTPND);
clearingpendingstatus%08x\n"
pend=__raw_readl(S3C2410_SUBSRCPND);
clearingsubpendingstatus%08x\n"
__raw_writel(pend,S3C2410_SUBSRCPND);
/*registerthemaininterrupts*/
/*注册主要中断*/
registerings3c2410interrupthandlers\n"
for(irqno=IRQ_EINT4t7;
irqno<
=IRQ_ADCPARENT;
irqno++){
/*setallthes3c2410internalirqs*/
switch(irqno){
/*dealwiththespecialIRQs(cascaded)*/
caseIRQ_EINT4t7:
caseIRQ_EINT8t23:
caseIRQ_UART0:
caseIRQ_UART1:
caseIRQ_UART2:
caseIRQ_ADCPARENT:
set_irq_chip(irqno,&
s3c_irq_level_chip);
/*设置中断操作函数集(电平)*/
set_irq_handler(irqno,handle_level_irq);
/*设置中断的高层流处理函数(电平)*/
caseIRQ_RESERVED6:
caseIRQ_RESERVED24:
/*noIRQhere*/
default:
//irqdbf("
registeringirq%d(s3cirq)\n"
irqno);
s3c_irq_chip);
/*默认中断为边缘触发*/
set_irq_handler(irqno,handle_edge_irq);
set_irq_flags(irqno,IRQF_VALID);
/*setupthecascadeirqhandlers*/
/*设置中断的高层流处理函数*/
set_irq_chained_handler(IRQ_EINT4t7,s3c_irq_demux_extint4t7);
set_irq_chained_handler(IRQ_EINT8t23,s3c_irq_demux_extint8);
set_irq_chained_handler(IRQ_UART0,s3c_irq_demux_uart0);
set_irq_chained_handler(IRQ_UART1,s3c_irq_demux_uart1);
set_irq_chained_handler(IRQ_UART2,s3c_irq_demux_uart2);
set_irq_chained_handler(IRQ_ADCPARENT,s3c_irq_demux_adc);
/*externalinterrupts*/
for(irqno=IRQ_EINT0;
=IRQ_EINT3;
registeringirq%d(extint)\n"
s3c_irq_eint0t4);
for(irqno=IRQ_EINT4;
=IRQ_EINT23;
registeringirq%d(extendeds3cirq)\n"
s3c_irqext_chip);
/*registertheuartinterrupts*/
s3c2410:
registeringexternalinterrupts\n"
for(irqno=IRQ_S3CUART_RX0;
=IRQ_S3CUART_ERR0;
registeringirq%d(s3cuart0irq)\n"
s3c_irq_uart0);
for(irqno=IRQ_S3CUART_RX1;
=IRQ_S3CUART_ERR1;
registeringirq%d(s3cuart1irq)\n"
s3c_irq_uart1);
for(irqno=IRQ_S3CUART_RX2;
=IRQ_S3CUART_ERR2;
registeringirq%d(s3cuart2irq)\n"
s3c_irq_uart2);
for(irqno=IRQ_TC;
=IRQ_ADC;
registeringirq%d(s3cadcirq)\n"
s3c_irq_adc);
registeredinterrupthandlers\n"
接着,我们来看一下中断处理过程
/*arch/arm/kernel/irq.c*/
*do_IRQhandlesallhardwareIRQ'
s.DecodedIRQsshouldnot
*comeviathisfunction.Instead,theyshouldprovidetheir
*own'
handler'
asmlinkagevoid__exceptionasm_do_IRQ(unsignedintirq,structpt_regs*regs)
structpt_regs*old_regs=set_irq_regs(regs);
/*保存寄存器中的内容*/
structirq_desc*desc=irq_desc+irq;
/*获取中断源*/
*Somehardwaregivesrandomlywronginterrupts.Rather
*thancrashing,dosomethingsensible.
if(irq>
=NR_IRQS)
desc=&
bad_irq_desc;
irq_enter();
desc_handle_irq(irq,desc);
/*调用已安装的中断高层流处理函数*/
/*AT91specificworkaround*/
irq_finish(irq);
irq_exit();
set_irq_regs(old_regs);
接下来,我们以IRQ_UART2(s3c2410串口2中断)为例,看看中断是如何分流到我们通过request_irq注册的中断处理函数
在s3c24xx_init_irq里IRQ_S3CUART_TX2中断的中断高层流处理函数被设置为s3c_irq_demux_uart2。
s3c_irq_demux_uart2主要工作是调用s3c_irq_demux_uart对串口中断进行分流处理,因为串口中断包含Rx(接收)中断、Tx(发送)中断和Rxerror(接收错误)中断
/*arch/arm/plat-s3c2410/irq.c*/
staticvoids3c_irq_demux_uart2(unsignedintirq,structirq_desc*desc)
irq=irq;
s3c_irq_demux_uart(IRQ_S3CUART_RX2);
s3c_irq_demux_uart通过副中断源引脚寄存器的值,判断中断源并执行相应的中断处理函数
/*start:
标示发出该中断信号的是哪个uart,即其值应为
*IRQ_S3CUART_RX0、IRQ_S3CUART_RX1或IRQ_S3CUART_RX2
staticvoids3c_irq_demux_uart(unsignedintstart)
unsignedintsubsrc,submsk;
unsignedintoffset=start-IRQ_S3CUART_RX0;
/*获取该UART中断源在副中断屏蔽寄存器中的偏移量*/
structirq_desc*desc;
/*readthecurrentpendinginterrupts,andthemask
*forwhatitisavailable*/
subsrc=__raw_readl(S3C2410_SUBSRCPND);
/*读取副中断源引脚寄存器*/
submsk=__raw_readl(S3C2410_INTSUBMSK);
/*读取副中断屏蔽寄存器*/
irqdbf2("
s3c_irq_demux_uart:
start=%d(%d),subsrc=0x%08x,0x%08x\n"
start,offset,subsrc,submsk);
subsrc&
=~submsk;
/*只留下已使能(未屏蔽)的中断源*/
subsrc>
=offset;
/*截取发送中断的uart源到subsrc低3位*/
=7;
if(subsrc!
=0)
desc=irq_desc+start;
if(subsrc&
1)/*Rx中断*/
desc_handle_irq(start,desc);
desc++;
2)/*Tx中断*/
desc_handle_irq(start+1,desc);
4)/*Rxerror中断*/
desc_handle_irq(start+2,desc);
desc_handle_irq实际上只是调用了de