微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM-Linux s3c2440 之中断分析(三)

ARM-Linux s3c2440 之中断分析(三)

时间:11-19 来源:互联网 点击:
Linux通过以下函数来注册中断以及中断相关的入口函数handle,只有先注册IRQ,才能正常使用。

  1. intset_irq_chip(unsignedintirq,structirq_chip*chip)
  2. staticinlinevoidset_irq_handler(unsignedintirq,irq_flow_handler_thandle)
  3. staticinlinevoidset_irq_chained_handler(unsignedintirq,irq_flow_handler_thandle)

实现的代码如下:

  1. for(irqno=IRQ_EINT4t7;irqno<=IRQ_ADCPARENT;irqno++){
  2. /*setallthes3c2410internalirqs*/
  3. switch(irqno){
  4. /*dealwiththespecialIRQs(cascaded)*/
  5. caseIRQ_EINT4t7:
  6. caseIRQ_EINT8t23:
  7. caseIRQ_UART0:
  8. caseIRQ_UART1:
  9. caseIRQ_UART2:
  10. caseIRQ_ADCPARENT:
  11. set_irq_chip(irqno,&s3c_irq_level_chip);
  12. set_irq_handler(irqno,handle_level_irq);//电平触发型
  13. break;
  14. caseIRQ_RESERVED6:
  15. caseIRQ_RESERVED24:
  16. /*noIRQhere*/
  17. break;
  18. default:
  19. //irqdbf("registeringirq%d(s3cirq)\n",irqno);
  20. set_irq_chip(irqno,&s3c_irq_chip);
  21. set_irq_handler(irqno,handle_edge_irq);//边缘触发型
  22. set_irq_flags(irqno,IRQF_VALID);
  23. }
  24. /*级联中断的注册*/
  25. set_irq_chained_handler(IRQ_EINT4t7,s3c_irq_demux_extint4t7);
  26. set_irq_chained_handler(IRQ_EINT8t23,s3c_irq_demux_extint8);
  27. set_irq_chained_handler(IRQ_UART0,s3c_irq_demux_uart0);
  28. set_irq_chained_handler(IRQ_UART1,s3c_irq_demux_uart1);
  29. set_irq_chained_handler(IRQ_UART2,s3c_irq_demux_uart2);
  30. set_irq_chained_handler(IRQ_ADCPARENT,s3c_irq_demux_adc);
  31. /*externalinterrupts*/
  32. for(irqno=IRQ_EINT0;irqno<=IRQ_EINT3;irqno++){
  33. irqdbf("registeringirq%d(extint)\n",irqno);
  34. set_irq_chip(irqno,&s3c_irq_eint0t4);
  35. set_irq_handler(irqno,handle_edge_irq);
  36. set_irq_flags(irqno,IRQF_VALID);
  37. }
  38. for(irqno=IRQ_EINT4;irqno<=IRQ_EINT23;irqno++){
  39. irqdbf("registeringirq%d(extendeds3cirq)\n",irqno);
  40. set_irq_chip(irqno,&s3c_irqext_chip);
  41. set_irq_handler(irqno,handle_edge_irq);
  42. set_irq_flags(irqno,IRQF_VALID);
  43. }
  44. /*registertheuartinterrupts*/
  45. irqdbf("s3c2410:registeringexternalinterrupts\n");
  46. for(irqno=IRQ_S3CUART_RX0;irqno<=IRQ_S3CUART_ERR0;irqno++){
  47. irqdbf("registeringirq%d(s3cuart0irq)\n",irqno);
  48. set_irq_chip(irqno,&s3c_irq_uart0);
  49. set_irq_handler(irqno,handle_level_irq);
  50. set_irq_flags(irqno,IRQF_VALID);
  51. }
  52. for(irqno=IRQ_S3CUART_RX1;irqno<=IRQ_S3CUART_ERR1;irqno++){
  53. irqdbf("registeringirq%d(s3cuart1irq)\n",irqno);
  54. set_irq_chip(irqno,&s3c_irq_uart1);
  55. set_irq_handler(irqno,handle_level_irq);
  56. set_irq_flags(irqno,IRQF_VALID);
  57. }
  58. for(irqno=IRQ_S3CUART_RX2;irqno<=IRQ_S3CUART_ERR2;irqno++){
  59. irqdbf("registeringirq%d(s3cuart2irq)\n",irqno);
  60. set_irq_chip(irqno,&s3c_irq_uart2);
  61. set_irq_handler(irqno,handle_level_irq);
  62. set_irq_flags(irqno,IRQF_VALID);
  63. }
  64. for(irqno=IRQ_TC;irqno<=IRQ_ADC;irqno++){//具体注册IRQ_TC、IRQ_ADC
  65. irqdbf("registeringirq%d(s3cadcirq)\n",irqno);
  66. set_irq_chip(irqno,&s3c_irq_adc);
  67. set_irq_handler(irqno,handle_edge_irq);
  68. set_irq_flags(irqno,IRQF_VALID);
  69. }

从以上代码中可以看出,注册中断主要是注册中断服务程序入口。Linux中将所有的中断号用一个stuctirq_desc数据结构进行统一管理,每个中断号或者一组中断号(如级联的中断),对应一个structirq_desc, 所以根据相应的中断号,可以获取对应的中断描述结构irq_desc:

  1. structirq_desc*desc=irq_to_desc(irq);
  2. irq_desc数据结构如下:
  3. structirq_desc{
  4. unsignedintirq;//中断号
  5. irq_flow_handler_thandle_irq;//系统中断处理的入口函数
  6. structirq_chip*chip;//对应的irq_chip结构,定义了与中断处理有关的函数
  7. structirqaction*action;//用户的中断处理函数,调用request_irq时添加
  8. unsignedintstatus;//IRQ的状态
  9. spinlock_tlock;
  10. constchar*name;
  11. }____cacheline_internodealigned_in_smp;

irq_chip结构定义了各种中断相关的处理行为,如开启或禁止中断以及中断服务完成的之后对相关的中断寄存器进行处理。关于电平触发型和边缘型触发中断入口函数可以从irq_chip结构中的看出只有ack函数的处理不同:

  1. structirq_chips3c_irq_level_chip={
  2. .name="s3c-level",
  3. .ack=s3c_irq_maskack,
  4. .mask=s3c_irq_mask,
  5. .unmask=s3c_irq_unmask,
  6. .set_wake=s3c_irq_wake
  7. };
  8. structirq_chips3c_irq_chip={
  9. .name="s3c",
  10. .ack=s3c_irq_ack,
  11. .mask=s3c_irq_mask,
  12. .unmask=s3c_irq_unmask,
  13. .set_wake=s3c_irq_wake
  14. };


在s3cirq_maskack中多了以下代码:

mask = __raw_readl(S3C2410_INTMSK);

__raw_writel(mask|bit

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top