熟女俱乐部五十路二区av,又爽又黄禁片视频1000免费,国产卡一卡二卡三无线乱码新区,中文无码一区二区不卡αv,中文在线中文a

新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM-Linux s3c2440 之中斷分析(三)

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

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
Linux通過以下函數(shù)來(lái)注冊(cè)中斷以及中斷相關(guān)的入口函數(shù)handle,只有先注冊(cè)IRQ,才能正常使用。

本文引用地址:http://www.bjwjmy.cn/article/201611/318130.htm
  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)

實(shí)現(xiàn)的代碼如下:


  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);//電平觸發(fā)型
  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);//邊緣觸發(fā)型
  22. set_irq_flags(irqno,IRQF_VALID);
  23. }
  24. /*級(jí)聯(lián)中斷的注冊(cè)*/
  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:registeringexternalinterruptsn");
  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++){//具體注冊(cè)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. }

從以上代碼中可以看出,注冊(cè)中斷主要是注冊(cè)中斷服務(wù)程序入口。Linux中將所有的中斷號(hào)用一個(gè)stuctirq_desc數(shù)據(jù)結(jié)構(gòu)進(jìn)行統(tǒng)一管理,每個(gè)中斷號(hào)或者一組中斷號(hào)(如級(jí)聯(lián)的中斷),對(duì)應(yīng)一個(gè)structirq_desc, 所以根據(jù)相應(yīng)的中斷號(hào),可以獲取對(duì)應(yīng)的中斷描述結(jié)構(gòu)irq_desc:


  1. structirq_desc*desc=irq_to_desc(irq);
  2. irq_desc數(shù)據(jù)結(jié)構(gòu)如下:
  3. structirq_desc{
  4. unsignedintirq;//中斷號(hào)
  5. irq_flow_handler_thandle_irq;//系統(tǒng)中斷處理的入口函數(shù)
  6. structirq_chip*chip;//對(duì)應(yīng)的irq_chip結(jié)構(gòu),定義了與中斷處理有關(guān)的函數(shù)
  7. structirqaction*action;//用戶的中斷處理函數(shù),調(diào)用request_irq時(shí)添加
  8. unsignedintstatus;//IRQ的狀態(tài)
  9. spinlock_tlock;
  10. constchar*name;
  11. }____cacheline_internodealigned_in_smp;

irq_chip結(jié)構(gòu)定義了各種中斷相關(guān)的處理行為,如開啟或禁止中斷以及中斷服務(wù)完成的之后對(duì)相關(guān)的中斷寄存器進(jìn)行處理。關(guān)于電平觸發(fā)型和邊緣型觸發(fā)中斷入口函數(shù)可以從irq_chip結(jié)構(gòu)中的看出只有ack函數(shù)的處理不同:


  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|bitval, S3C2410_INTMSK);

實(shí)現(xiàn)的功能是,屏蔽相應(yīng)的中斷。

在early_trap_init()中已經(jīng)進(jìn)行了中斷(異常)向量的初始化,將異常向量表從物理地址0x00000000拷貝到虛擬0xffff0000的虛擬地址處。異常向量在arch/arm/kernel/entry-armv.S中定義:


  1. .globl__vectors_start
  2. rs_start:
  3. swiSYS_ERROR0
  4. bvector_und+stubs_offset
  5. ldrpc,.LCvswi+stubs_offset
  6. bvector_pabt+stubs_offset
  7. bvector_dabt+stubs_offset
  8. bvector_addrexcptn+stubs_offset
  9. bvector_irq+stubs_offset
  10. bvector_fiq+stubs_offset
  11. .globl__vectors_end

那么當(dāng)有中斷產(chǎn)生時(shí):

  1. /*
  2. *Interrupthandling.Preservesr7,r8,r9
  3. */
  4. .macroirq_handler
  5. get_irqnr_preambler5,lr
  6. 1:get_irqnr_and_baser0,r6,r5,lr
  7. movner1,sp
  8. @
  9. @routinecalledwithr0=irqnumber,r1=structpt_regs*
  10. @
  11. adrnelr,1b
  12. bneasm_do_IRQ//跳轉(zhuǎn)到這里中斷的總?cè)肟诤瘮?shù)

這里的asm_do_IRQ對(duì)應(yīng)arch/arm/kernel/irq.c中:


  1. asmlinkagevoid__exceptionasm_do_IRQ(unsignedintirq,structpt_regs*regs)

所以這是Linux中所有中斷的總?cè)肟诤瘮?shù)。asm_doIRQ()調(diào)用generic_handle_irq()再后調(diào)用

generic_handle_irq_desc(),最后到各個(gè)irq_desc的處理。


  1. staticinlinevoidgeneric_handle_irq_desc(unsignedintirq,structirq_desc*desc)
  2. {
  3. #ifdefCONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
  4. desc->handle_irq(irq,desc);
  5. #else
  6. if(likely(desc->handle_irq))
  7. desc->handle_irq(irq,desc);
  8. else
  9. __do_IRQ(irq);
  10. #endif
  11. }

從總?cè)肟诘接脩舻闹袛嗵幚砗瘮?shù)的流程:

asm_do_IRQ() –-> generic_handle_irq() –->irq_dsc->handle() à handle_IRQ_event() à irq_des->action()

最后對(duì)中斷處理流程進(jìn)行簡(jiǎn)單總結(jié):

(1)總?cè)肟诤瘮?shù)asm_do_IRQ,獲取中斷號(hào)irq

(2)asm_do_IRQ根據(jù)中斷號(hào)調(diào)用各中斷號(hào)所注冊(cè)的中斷入口函數(shù)irq_desc[irq]->handle_irq

(3)最后在中斷入口函數(shù)中調(diào)用handle_IRQ_event()依次執(zhí)行用戶的中斷處理函數(shù)action



關(guān)鍵詞: ARMLinuxs3c2440中

評(píng)論


技術(shù)專區(qū)

關(guān)閉