<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > arm驅(qū)動linux內(nèi)核中斷編程

          arm驅(qū)動linux內(nèi)核中斷編程

          作者: 時間:2016-11-19 來源:網(wǎng)絡(luò) 收藏

          第一部分獲取中斷(開啟硬件中斷)

          本文引用地址:http://www.ex-cimer.com/article/201611/318227.htm

          一、中斷的申請注銷:
          1)中斷的申請

          int request_irq(unsigned int irq, irq_handler_t handler,
          unsigned long irqflags, const char *devname, void *dev_id)

          2)中斷的注銷

          void free_irq(unsigned int irq, void *dev_id)

          3)中斷處理函數(shù)

          static irqreturn_t irq_handle(int irq, void *dev__id);

          參數(shù):irq:表示中斷號,這個參數(shù)還保留由于歷史遺留問題,往后可能越來越?jīng)]用了。由于第二個參數(shù)信息更強(qiáng)大
          dev__id:就是request_irq()中void *dev_id參數(shù)。
          二、中斷申請函數(shù)參數(shù)

          int request_irq(unsigned int irq, irq_handler_t handler,
          unsigned long irqflags, const char *devname, void *dev_id)

          1)參數(shù):
          irq:是要申請的硬件中斷號。
          handler:是向系統(tǒng)注冊的中斷處理函數(shù),是一個回調(diào)函數(shù),中斷發(fā)生時,系統(tǒng)調(diào)用這個函數(shù),dev_id參數(shù)將被傳遞給它。
          irqflags:是中斷處理的屬性,
          a)若設(shè)置了IRQF_DISABLED,則表示中斷處理程序是快速處理程序,快速處理程序被調(diào)用時屏蔽所有中斷,慢速處理程序不屏蔽;
          b)若設(shè)置了 IRQF_SHARED,則表示多個設(shè)備共享中斷;//在另一篇文章會提到
          c)若設(shè)置了IRQF_SAMPLE_RANDOM,表示對系統(tǒng)熵有貢獻(xiàn),對系統(tǒng)獲取隨機(jī)數(shù)有好處。
          Tip:(flag是可以通過或的方式同時使用的)
          devname:設(shè)置中斷名稱,通常是設(shè)備驅(qū)動程序的名稱 在cat /proc/interrupts中可以看到此名稱。
          dev_id:在中斷共享時會用到,一般設(shè)置為這個設(shè)備的設(shè)備結(jié)構(gòu)體或者不使用時為NULL。因為在共享中斷中同一個中斷線(或可以說同一個中斷號)可能掛載好幾個設(shè)備,當(dāng)使用void free_irq(unsigned int irq, void *dev_id)時,根據(jù)irq和dev_id可以找到中斷線為irq上的標(biāo)識為dev_id的某個具體設(shè)備。dev_id也經(jīng)常在不是共享中斷中的驅(qū)動傳遞數(shù)據(jù)

          2)返回值:
          a)request_irq()返回0表示成功;
          b)返回-EINVAL表示無效的參數(shù),如果返回這個值,應(yīng)該看看傳遞給request_irq()的參數(shù)是否正確;
          c)返回-EBUSY表示中斷已經(jīng)被占用且不能共享;
          d)返回ENOMEM表示內(nèi)存不足。嵌入式系統(tǒng)由于內(nèi)存資源有限,經(jīng)常會發(fā)生這樣的錯誤。

          3)擴(kuò)展---unsigned long irqflags值
          在includelinuxinterrupt.h中

          /*
          * These correspond to the IORESOURCE_IRQ_* defines in
          * linux/ioport.h to select the interrupt line behaviour. When
          * requesting an interrupt without specifying a IRQF_TRIGGER, the
          * setting should be assumed to be "as already configured", which
          * may be as per machine or firmware initialisation.
          */
          #define IRQF_TRIGGER_NONE 0x00000000
          #define IRQF_TRIGGER_RISING 0x00000001
          #define IRQF_TRIGGER_FALLING 0x00000002
          #define IRQF_TRIGGER_HIGH 0x00000004
          #define IRQF_TRIGGER_LOW 0x00000008
          #define IRQF_TRIGGER_MASK (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW |
          IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
          #define IRQF_TRIGGER_PROBE 0x00000010
          /*
          * These flags used only by the kernel as part of the
          * irq handling routines.
          *
          * IRQF_DISABLED - keep irqs disabled when calling the action handler
          * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator
          * IRQF_SHARED - allow sharing the irq among several devices
          * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
          * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
          * IRQF_PERCPU - Interrupt is per cpu
          * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
          * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
          * registered first in an shared interrupt is considered for
          * performance reasons)
          */
          #define IRQF_DISABLED 0x00000020
          #define IRQF_SAMPLE_RANDOM 0x00000040
          #define IRQF_SHARED 0x00000080
          #define IRQF_PROBE_SHARED 0x00000100
          #define IRQF_TIMER 0x00000200
          #define IRQF_PERCPU 0x00000400
          #define IRQF_NOBALANCING 0x00000800
          #define IRQF_IRQPOLL 0x00001000

          Tip:下面是老版本(2.4內(nèi)核irqflags的值),不要在新版本使用。(2.6 內(nèi)核及2.6以上內(nèi)核都為新內(nèi)核)

          /*
          * Migration helpers. Scheduled for removal in 9/2007
          * Do not use for new code !//不要的新版本使用,2.6 內(nèi)核及2.6以上內(nèi)核都為新內(nèi)核
          */
          static inline
          unsigned long __deprecated deprecated_irq_flag(unsigned long flag)
          {
          return flag;
          }
          #define SA_INTERRUPT deprecated_irq_flag(IRQF_DISABLED)
          #define SA_SAMPLE_RANDOM deprecated_irq_flag(IRQF_SAMPLE_RANDOM)
          #define SA_SHIRQ deprecated_irq_flag(IRQF_SHARED)
          #define SA_PROBEIRQ deprecated_irq_flag(IRQF_PROBE_SHARED)
          #define SA_PERCPU deprecated_irq_flag(IRQF_PERCPU)
          #define SA_TRIGGER_LOW deprecated_irq_flag(IRQF_TRIGGER_LOW)
          #define SA_TRIGGER_HIGH deprecated_irq_flag(IRQF_TRIGGER_HIGH)
          #define SA_TRIGGER_FALLING deprecated_irq_flag(IRQF_TRIGGER_FALLING)
          #define SA_TRIGGER_RISING deprecated_irq_flag(IRQF_TRIGGER_RISING)
          #define SA_TRIGGER_MASK deprecated_irq_flag(IRQF_TRIGGER_MASK)

          三、使用模板
          使用步驟:以外部中斷為例
          a)定義結(jié)構(gòu)體,相當(dāng)于定義(void *dev_id)中的(void *)

          struct pin_desc{//聲明一個引腳描述的結(jié)構(gòu)體pin_desc
          unsigned int pin;//引腳值,參考數(shù)據(jù)手冊及板子電路原理
          unsigned int key_val;//值自已隨便定義;看自己的項目需要
          //...................
          };

          b)實例化結(jié)構(gòu)體,相當(dāng)于(void *dev_id)中的 dev_id

          struct pin_desc pins_desc[3] = {//實例化結(jié)構(gòu)體,以jz2440按鍵為列
          {S3C2410_GPF0, 0x01},//S3C2410_GPFn在內(nèi)核中定義好了
          {S3C2410_GPF2, 0x02},
          {S3C2410_GPG3, 0x03},
          };

          c)定義中斷處理函數(shù)

          static irqreturn_t irq_handle(int irq, void *dev__id){
          struct pin_desc *pindesc = (struct pin_desc *)dev__id;
          //................
          return IRQ_RETVAL(IRQ_HANDLED);//返回IRQ_HANDLED表示中斷已經(jīng)處理
          }

          d)申請中斷

          request_irq(IRQ_EINT0, irq_handle, IRQ_TYPE_EDGE_BOTH, "s2", &pins_desc[0]);//IRQ_EINTn在內(nèi)核中定義好了
          request_irq(IRQ_EINT2, irq_handle, IRQ_TYPE_EDGE_BOTH, "s3", &pins_desc[1]);
          request_irq(IRQ_EINT11, irq_handle, IRQ_TYPE_EDGE_BOTH, "s4", &pins_desc[2]);

          e)釋放內(nèi)存

          free_irq(IRQ_EINT0, &pins_desc[0]);
          free_irq(IRQ_EINT2, &pins_desc[1]);
          free_irq(IRQ_EINT11, &pins_desc[2]);

          Tip:可以直接將IRQ_EINTn也在pins_desc定義,然后

          int i = 0;
          for(i = 0; i < 3; i++){
          free_irq(pins_desc[i].irqnum, &pins_desc[i]);
          }



          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();