ARM-Linux s3c2440 之中断分析(三)
时间:11-19
来源:互联网
点击:
Linux通过以下函数来注册中断以及中断相关的入口函数handle,只有先注册IRQ,才能正常使用。
在s3cirq_maskack中多了以下代码:
- intset_irq_chip(unsignedintirq,structirq_chip*chip)
- staticinlinevoidset_irq_handler(unsignedintirq,irq_flow_handler_thandle)
- staticinlinevoidset_irq_chained_handler(unsignedintirq,irq_flow_handler_thandle)
实现的代码如下:
- 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);//电平触发型
- break;
- caseIRQ_RESERVED6:
- caseIRQ_RESERVED24:
- /*noIRQhere*/
- break;
- default:
- //irqdbf("registeringirq%d(s3cirq)\n",irqno);
- set_irq_chip(irqno,&s3c_irq_chip);
- set_irq_handler(irqno,handle_edge_irq);//边缘触发型
- set_irq_flags(irqno,IRQF_VALID);
- }
- /*级联中断的注册*/
- 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;irqno<=IRQ_EINT3;irqno++){
- irqdbf("registeringirq%d(extint)\n",irqno);
- set_irq_chip(irqno,&s3c_irq_eint0t4);
- set_irq_handler(irqno,handle_edge_irq);
- set_irq_flags(irqno,IRQF_VALID);
- }
- for(irqno=IRQ_EINT4;irqno<=IRQ_EINT23;irqno++){
- irqdbf("registeringirq%d(extendeds3cirq)\n",irqno);
- set_irq_chip(irqno,&s3c_irqext_chip);
- set_irq_handler(irqno,handle_edge_irq);
- set_irq_flags(irqno,IRQF_VALID);
- }
- /*registertheuartinterrupts*/
- irqdbf("s3c2410:registeringexternalinterrupts\n");
- for(irqno=IRQ_S3CUART_RX0;irqno<=IRQ_S3CUART_ERR0;irqno++){
- irqdbf("registeringirq%d(s3cuart0irq)\n",irqno);
- set_irq_chip(irqno,&s3c_irq_uart0);
- set_irq_handler(irqno,handle_level_irq);
- set_irq_flags(irqno,IRQF_VALID);
- }
- for(irqno=IRQ_S3CUART_RX1;irqno<=IRQ_S3CUART_ERR1;irqno++){
- irqdbf("registeringirq%d(s3cuart1irq)\n",irqno);
- set_irq_chip(irqno,&s3c_irq_uart1);
- set_irq_handler(irqno,handle_level_irq);
- set_irq_flags(irqno,IRQF_VALID);
- }
- for(irqno=IRQ_S3CUART_RX2;irqno<=IRQ_S3CUART_ERR2;irqno++){
- irqdbf("registeringirq%d(s3cuart2irq)\n",irqno);
- set_irq_chip(irqno,&s3c_irq_uart2);
- set_irq_handler(irqno,handle_level_irq);
- set_irq_flags(irqno,IRQF_VALID);
- }
- for(irqno=IRQ_TC;irqno<=IRQ_ADC;irqno++){//具体注册IRQ_TC、IRQ_ADC
- irqdbf("registeringirq%d(s3cadcirq)\n",irqno);
- set_irq_chip(irqno,&s3c_irq_adc);
- set_irq_handler(irqno,handle_edge_irq);
- set_irq_flags(irqno,IRQF_VALID);
- }
从以上代码中可以看出,注册中断主要是注册中断服务程序入口。Linux中将所有的中断号用一个stuctirq_desc数据结构进行统一管理,每个中断号或者一组中断号(如级联的中断),对应一个structirq_desc, 所以根据相应的中断号,可以获取对应的中断描述结构irq_desc:
- structirq_desc*desc=irq_to_desc(irq);
- irq_desc数据结构如下:
- structirq_desc{
- unsignedintirq;//中断号
- …
- irq_flow_handler_thandle_irq;//系统中断处理的入口函数
- structirq_chip*chip;//对应的irq_chip结构,定义了与中断处理有关的函数
- …
- structirqaction*action;//用户的中断处理函数,调用request_irq时添加
- unsignedintstatus;//IRQ的状态
- …
- spinlock_tlock;
- …
- constchar*name;
- }____cacheline_internodealigned_in_smp;
irq_chip结构定义了各种中断相关的处理行为,如开启或禁止中断以及中断服务完成的之后对相关的中断寄存器进行处理。关于电平触发型和边缘型触发中断入口函数可以从irq_chip结构中的看出只有ack函数的处理不同:
- structirq_chips3c_irq_level_chip={
- .name="s3c-level",
- .ack=s3c_irq_maskack,
- .mask=s3c_irq_mask,
- .unmask=s3c_irq_unmask,
- .set_wake=s3c_irq_wake
- };
- structirq_chips3c_irq_chip={
- .name="s3c",
- .ack=s3c_irq_ack,
- .mask=s3c_irq_mask,
- .unmask=s3c_irq_unmask,
- .set_wake=s3c_irq_wake
- };
在s3cirq_maskack中多了以下代码:
mask = __raw_readl(S3C2410_INTMSK);
__raw_writel(mask|bit
ARMLinuxs3c2440中 相关文章:
- ARM-Linux s3c2440 之中断分析(一)(11-19)
- ARM-Linux s3c2440 之中断分析(二)(11-19)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)