BBB IRQ 驅動分析

一、 說明
Beaglebone Black開發板自帶GPIO以及IRQ等驅動程序,所以爲驅動的開發提供了極大的便利,在此主要分析內核自帶的庫文件中相關的函數以及驅動編寫的步驟。


二、 IRQ庫函數分析
 驅動添加的庫函數有:
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
其中,庫位於/kernel/kernel/include/linux路徑下,
gpio.h庫函數包含對IO口操作的相關函數,例如
static inline int gpio_get_value(unsigned int gpio) 獲取引腳值
static inline void gpio_set_value(unsigned int gpio, int value)設置引腳值
static inline int gpio_to_irq(unsigned int gpio)把gpio引腳號轉換爲中斷號
static inline int irq_to_gpio(unsigned int irq)把中斷號轉換爲引腳號
static inline int gpio_direction_input(unsigned gpio)引腳方向設置爲輸入
static inline int gpio_direction_output(unsigned gpio, int value)引腳方向設置爲輸出
static inline int gpio_get_value(unsigned gpio)獲取引腳的狀態值
以上這些函數實際上已經完全可以實現GPIO所需的功能需求,換句話說,GPIO需要的驅動函數無非以上這些,當然僅限於IO操作,不涉及中斷等
interrupt.h庫函數主要包含中斷相關的參數宏定義以及相關函數:
中斷觸發方式宏定義:
#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
函數:
中斷申請函數
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
中斷釋放函數

extern void free_irq(unsigned int, void *)


三、 中斷程序分析


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>


#define PIN_A_GPIO 65 // is on 2*32+1 設置中斷引腳爲GPIO2_1
#define PIN_A_FLAGS GPIOF_IN
#define PIN_A_LABEL "HI_PIN_A"
int k;
static irqreturn_t irq_handler_pin_a (int irq, void *dev_id)  //中斷處理函數
{
  printk (KERN_INFO "Hello from irq_handler_pin_a...%d\n",k);
  k++;
  return IRQ_HANDLED;
}
//加載函數,實現中斷申請等相關功能
static int __init hello_interrupts_start (void) 
{
  int retval, irq, regval;
  printk (KERN_INFO "Loading hello_interrupts module...\n");
  retval = gpio_request_one(PIN_A_GPIO, PIN_A_FLAGS, PIN_A_LABEL);
printk (KERN_INFO "HI:request GPIO pin#%i for IRQ (%i)\n", PIN_A_GPIO, retval);

irq = gpio_to_irq (PIN_A_GPIO);
retval = request_irq (irq, irq_handler_pin_a, 1/*IRQF_TRIGGER_RISING */, PIN_A_LABEL, NULL);
irq_set_irq_type (irq, IRQ_TYPE_EDGE_BOTH);
 return 0;
}
//驅動卸載
static void __exit hello_interrupts_end(void)
 {
  printk ("HI: Releasing IRQ resources...\n");
  free_irq (gpio_to_irq (PIN_A_GPIO), NULL);
  gpio_free (PIN_A_GPIO);
}
module_init (hello_interrupts_start);
module_exit (hello_interrupts_end);
MODULE_AUTHOR("000");
MODULE_DESCRIPTION("A sample driver using interrupts");
MODULE_LICENSE("GPL");


四、  程序使用的函數分析
1、 retval = gpio_request_one(PIN_A_GPIO, PIN_A_FLAGS, PIN_A_LABEL);
申請一個單獨的GPIO,使用flag作爲初始參數,函數原型爲:
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); 
flag用來配置下面的特性:
 * GPIOF_DIR_IN          - 配置方向爲輸入
 * GPIOF_DIR_OUT         -配置方向爲輸出
 * GPIOF_INIT_LOW    - 做輸出引腳,輸出低電平
  * GPIOF_INIT_HIGH   - 做輸出引腳,輸出高電平
Label貌似爲名稱


2、 gpio_to_irq
原型爲:int gpio_to_irq(unsigned gpio);
將GPIO引腳號映射爲IRQ號
3、 request_irq
申請IRQ,原型爲int   request_irq(unsigned int irq , irq_handler_t hander , unsigned long irqflags , 
                              Const char *devname , void *dev_id )
Irq爲申請的中斷號
Handler 爲向系統登記的中斷處理函數,dev_id爲傳遞給該函數的參數
Irqflags爲中斷處理屬性。具體如下:
    IRQF_TRIGGER_RISING上升沿觸發 、IRQF_TRIGGER_FALLING下降沿觸發 、 IRQF_TRIGGER_HIGH高電平觸發 、 IRQF_TRIGGER_LOW低電平觸發,dev_id一般設置爲NULL
4、 irq_set_irq_type
設置中斷觸發類型,函數原型爲int set_irq_type(unsigned int irq, unsigned int type)
  #define IRQ_TYPE_NONE           0x00000000     未指明類型
    #define IRQ_TYPE_EDGE_RISING    0x00000001     上升沿觸發
    #define IRQ_TYPE_EDGE_FALLING   0x00000002     下降沿觸發
    #define IRQ_TYPE_EDGE_BOTH      (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
    #define IRQ_TYPE_LEVEL_HIGH     0x00000004     高電平觸發
    #define IRQ_TYPE_LEVEL_LOW      0x00000008     低電平觸發
    #define IRQ_TYPE_SENSE_MASK     0x0000000f    
    #define IRQ_TYPE_PROBE          0x00000010 

5、 free_irq 釋放中斷
6、 gpio_free釋放之前申請的GPIO


五、測試
 將驅動編譯加載後,驅動即運行,中斷程序也隨之啓動,通過查看內核輸出(dmesg –k查看),即可看到內核的所有輸出,包括驅動加載是的輸出以及中斷觸發是的輸出信息,至此,中斷測試成功。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章