新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > arm驅動linux內核中斷編程

        arm驅動linux內核中斷編程

        作者: 時間:2016-11-19 來源:網絡 收藏

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

        本文引用地址:http://www.104case.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)中斷處理函數

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

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

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

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

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

        3)擴展---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內核irqflags的值),不要在新版本使用。(2.6 內核及2.6以上內核都為新內核)

        /*
        * Migration helpers. Scheduled for removal in 9/2007
        * Do not use for new code !//不要的新版本使用,2.6 內核及2.6以上內核都為新內核
        */
        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)定義結構體,相當于定義(void *dev_id)中的(void *)

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

        b)實例化結構體,相當于(void *dev_id)中的 dev_id

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

        c)定義中斷處理函數

        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表示中斷已經處理
        }

        d)申請中斷

        request_irq(IRQ_EINT0, irq_handle, IRQ_TYPE_EDGE_BOTH, "s2", &pins_desc[0]);//IRQ_EINTn在內核中定義好了
        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)釋放內存

        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]);
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 宣汉县| 深圳市| 清徐县| 江山市| 公安县| 隆安县| 潍坊市| 班戈县| 吕梁市| 阳山县| 琼海市| 陕西省| 甘孜县| 名山县| 彭山县| 昌宁县| 原阳县| 武汉市| 鄢陵县| 武宁县| 墨玉县| 迭部县| 乐昌市| 集贤县| 陇川县| 调兵山市| 叶城县| 吴堡县| 枣强县| 重庆市| 苍山县| 云和县| 洪雅县| 宜君县| 股票| 宜春市| 那曲县| 曲靖市| 华坪县| 民和| 宜州市|