天天看點

GPIO口及中斷API函數【轉】

#include <linux/gpio.h> // 标準 GPIO_API
   int gpio_request(unsigned gpio, const char *label);
獲得并占有 GPIO port 的使用權,由參數 gpio 指定具體 port,非空的lables指針有助于診斷。主要是告訴核心這位址被占用了。當其它地方調用同一位址的gpio_request就會報告錯誤,該位址已被申請。在/proc/mem應該會有位址占用表描述。
這種用法的保護作用前提是大家都遵守先申請再通路,有一個地方沒遵守這個規則,這功能就失效了。好比程序互斥,必需大家在通路臨界資源的時候都得先擷取鎖一樣,其中一個沒遵守約定,代碼就廢了。
例1:void gpio_free(unsigned gpio);//釋放 GPIO port 的使用權,由gpio 指定具體port。
例2:gpio_free(RK29_PIN0_PA0);//釋放GPIO0_A0
int gpio_direction_input(unsigned gpio);//傳回0
例3:gpio_direction_input (RK29_PIN0_PA0);//把GPIO0_A0設定為輸入
int gpio_direction_output(unsigned gpio, int value);//傳回0
4:gpio_direction_output(RK29_PIN0_PA0,GPIO_LOW);//把GPIO0_A0設定為輸出口,且其電平拉低。    int gpio_get_value(unsigned gpio);//傳回value
5:ret = gpio_get_value (RK29_PIN0_PA0);// 讀取GPIO0_A0的電平,并指派給變量ret。
void gpio_set_value(unsigned gpio, int value);
例6:gpio_set_value (RK29_PIN0_PA0, GPIO_HIGH);// 設定RK29_PIN0_PA0電平為高。
        value = 0, normal
        value = 1, pull up
        value = 2, pull down
        例7:gpio_pull_updown(RK29_PIN0_PA0,1)上拉
       int gpio_cansleep(unsigned gpio);
支援這種gpio的平台為了通過在這個函數中傳回非零來區分其它類型的gpio(需要一個已經被  gpio_request申請的gpio号)為了通路這些端口,定義了另一組函數接口:
       int gpio_get_value_cansleep(unsigned gpio);
       void gpio_set_value_cansleep(unsigned gpio, int value);
        隻能在允許睡眠的上下文中通路這些端口,比如線程化的中斷中,
       static inline int gpio_is_valid(int number)//判斷GPIO是否有效,有效傳回0
       int gpio_export(unsigned gpio, bool direction_may_change);//傳回0成功
       void gpio_unexport();  //傳回0成功
       int gpio_export_link(struct device *dev, const char *name, unsigned gpio) 
//建立到導出GPIO的 sysfs link  ,第一個參數是在哪個dev下建立,第二個是參數名字,第三個是gpio編号 
 
中斷部分的API:
  static inline int gpio_to_irq(unsigned gpio)
8:gpioToIrq = gpio_to_irq (RK29_PIN0_PA0);// 把GPIO0_A0的PIN值轉換為相應的IRQ值,并指派給變量gpioToIrq。
   gpio_to_irq()傳回的中斷編号可以傳給request_irq()和free_irq()。
   irq_to_gpio()傳回的gpio編号通常用來調用gpio_get_value(),比如在沿觸發的中斷中擷取引腳的狀态。有些平台不支援這種映射,應該避免調用映射函數
   static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);
範例:irq是要申請的硬體中斷号; handler是向系統登記的中斷處理函數,是一個回調函數,中斷發生時,系統調用這個函數,dev參數将被傳遞; flags是中斷處理的屬性,若設定SA_INTERRUPT,标明中斷處理程式是快速處理程式,快速處理程式被調用時屏蔽所有中斷,慢速處理程式不屏蔽;若設定SA_SHIRQ,則多個裝置共享中斷,*dev在中斷共享時會用到,一般設定為這個裝置的device結構本身或者NULL。 當flags發生時,觸發中斷。
9:static irqreturn_t PA0IntHandler(int irq, void *dev_id)
{
printk(KERN_INFO "PA0IntHandler:irq=%d ",irq);
return IRQ_HANDLED;
}
void main(void)
{
// 把GPIO0_A0的PIN值轉換為相應的IRQ值,并指派給變量gpioToIrq。
unsigned long req_flags = IRQF_TRIGGER_RISING;
int gpioToIrq = gpio_to_irq (RK29_PIN0_PA0);
If(gpioToIrq != -1){
//注冊PA0IntHandler中斷處理函數,中斷号是RK29_PIN0_PA0,設定為上升沿觸發
    request_irq(gpioToIrq, PA0IntHandler,req_flags, "PA0_test", NULL);
    }
}
void free_irq(unsigned int irq, void *dev_id)//釋放中斷
irq: 釋放的中斷号dev_id
例10: free_irq(gpio_to_irq(RK29_PIN0_PA0),NULL);// 釋放GPIO0_A0中斷。
     int set_irq_type(unsigned int irq, unsigned int type)
irq: 指定的中斷号type   : 設定的中斷類型
例11:set_irq_type(gpio_to_irq(RK2818_PIN_PA0),IRQF_TRIGGER_LOW);//設定GPIO0_A0中斷為低電平觸發
void disable_irq_nosync(unsigned int irq)
強行關閉指定中斷,不會等待目前中斷處理程式執行完畢。,立即傳回
例12:disable_irq_nosync(gpio_to_irq(RK29_PIN0_PA0));//關閉GPIO0_A0中斷。
void disable_irq(unsigned int irq)
将關閉硬體中斷并等待(可能有的)中斷處理完成才傳回。
例13:disable_irq (gpio_to_irq(RK29_PIN0_PA0));//關閉GPIO0_A0中斷。
void enable_irq(unsigned int irq)
使能一個指定的中斷
例14: enable_irq (gpio_to_irq(RK29_PIN0_PA0));//使能GPIO0_A0中斷。
注意:使能IRQ和不使能IRQ應該配對使用。
enable_irq之前,并未關閉指定中斷(如調用disable_irq_nosync 關閉指定中斷),
enable_irq會報警告(WARNING: at kernel/irq/manage.c:274 enable_irq+0x48/0x68();Unbalanced enable for IRQ 58),此為正常現象。
     int enable_irq_wake(unsigned int irq)//傳回0成功
     int disable_irq_wake(unsigned int irq)//傳回0成功
   要enable和disable的次數相同
例15:static inline int enable_irq_wake(unsigned int irq)
{return set_irq_wake(irq, 1);
}
static inline int disable_irq_wake(unsigned int irq)
{
return set_irq_wake(irq, 0);
}
  void rk29_gpio_suspend(void)// 讓GPIO進入省電睡眠模式
調用此函數,是否會讓GPIO進入省電睡眠模式,與enable_irq_wake和disable_irq_wake函數相關,
例16:如果先調用了enable_irq_wake(gpio_to_irq(RK29_PIN0_PA0)),則即使調用了
  void rk29_gpio_resume(void)//喚醒GPIO