成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

手把手教你使用 Gpio 子系統 API

系統 Linux
本文講解 pinctrl 子系統和 gpio 子系統的 API,以及使用示例。傳統的配置 pin 的方式就是直接操作相應的寄存器,但是這種配置方式比較繁瑣、而且容易出問題(比如 pin 功能沖突)。

[[440470]]

本文講解 pinctrl 子系統和 gpio 子系統的 API,以及使用示例。

傳統的配置 pin 的方式就是直接操作相應的寄存器,但是這種配置方式比較繁瑣、而且容易出問題(比如 pin 功能沖突)。pinctrl 子系統就是為了解決這個問題而引入的,pinctrl 子系統主要工作內容如下:

①獲取設備樹中 pin 信息。

②根據獲取到的 pin 信息來設置 pin 的復用功能

③根據獲取到的 pin 信息來設置 pin 的電氣特性,比如上/下拉、速度、驅動能力等。

對于我們使用者來講,只需要在設備樹里面設置好某個 pin 的相關屬性即可,其他的初始化工作均由 pinctrl 子系統來完成。

如果 pinctrl 將一個 pin 腳初始化為 GPIO 而不是 IIC 或者 SPI,那么接下來就可以使用 gpio 子系統的API。

gpio 子系統是基于 pinctrl 子系統的!pin controller 和 GPIO Controller 不是一回事,前者控制引腳可用于 GPIO 功能、I2C 功能等功能性切換;后者只是把引腳配置為輸入、輸出、設置GPIO方向、獲取值等簡單的功能。(pinctrl 的 api 其實可以實現所有需求,但 gpio 的函數更常用一些)

1、gpio 子系統 API

gpio 子系統中操作一個 GPIO 需要如下幾步:

  1. 1、of_find_compatible_node 
  2. 2、of_get_named_gpio 
  3. 3、gpio_request 
  4. 4、控制gpio(gpio_direction_input、gpio_direction_output……) 
  5. 5、gpio_free 

1)of_find_compatible_node 函數在設備樹中根據 device_type 和 compatible 這兩個屬性查找指定的節點,此處是為了獲取在設備樹中設置的 GPIO 的節點句柄。如果其他地方有獲得句柄,那么可以直接使用這個句柄。

2) of_get_named_gpio ,獲取所設置的 gpio number。

3) gpio_request ,請求這個 gpio 。如果其他地方請求了這個 gpio,還沒有釋放,那么我們會請求不到。

4)請求到這個 gpio 以后,我們就可以對它進行操作,比如獲取到它的值,設置它的值。

5)使用完以后,釋放這個 gpio。

原理圖:

博主手里有一個 正點原子 imx6ull 開發板,查原理圖,發現蜂鳴器直連的 GPIO 是 GPIO5_1。我把此 IO 口拉低,蜂鳴器就會響。

在設備樹中增加如下代碼(imx6ull-alientek-emmc.dts)

  1. test:test { 
  2.  compatible = "Jason_hello"
  3.  hello = <&gpio5 1 GPIO_ACTIVE_HIGH>; 
  4. }; 

設置 GPIO 為 GPIO5_1,高電平有效,但實際上第三個參數我沒有使用。

gpio.c

  1. #include <linux/init.h> 
  2. #include <linux/kernel.h> 
  3. #include <linux/module.h> 
  4. #include <linux/gpio.h> 
  5. #include <linux/of.h> 
  6. #include <linux/of_gpio.h> 
  7.  
  8. static int __init mypinctrl_init(void) 
  9.  int gpionum = 0; 
  10.  int ret = 0; 
  11.  struct device_node *node = NULL
  12.   
  13.  node = of_find_compatible_node(NULL,NULL,"Jason_hello"); 
  14.  if(!node){ 
  15.   printk("get node error\n"); 
  16.   return ret; 
  17.  } 
  18.   
  19.  gpionum = of_get_named_gpio(node,"hello",0); 
  20.  if(gpionum < 0){ 
  21.   printk("get gpionum error\n"); 
  22.   return ret; 
  23.  } 
  24.   
  25.  ret = gpio_request(gpionum,"hello"); 
  26.  if(ret){ 
  27.   printk("gpio_request error\n"); 
  28.   return ret; 
  29.  } 
  30.    
  31.  printk("gpio(%d) value = %d\n",gpionum,ret); 
  32.    
  33.  ret = gpio_get_value(gpionum); 
  34.    
  35.  printk("gpio(%d) value = %d\n",gpionum,ret); 
  36.    
  37.  gpio_direction_output(gpionum,0);  // 設置 gpio 輸出低電平 
  38.    
  39.  ret = gpio_get_value(gpionum); 
  40.    
  41.  printk("gpio(%d) value = %d\n",gpionum,ret); 
  42.    
  43.  return 0; 
  44.  
  45. static void __exit mypinctrl_exit(void) 
  46.  printk("%s\n",__func__); 
  47.  
  48. module_init(mypinctrl_init); 
  49. module_exit(mypinctrl_exit); 
  50.  
  51. MODULE_LICENSE("GPL"); 

Makefile

  1. KERNELDIR := /home/book/linux/tool/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek 
  2.  
  3. CURRENT_PATH := $(shell pwd) 
  4.  
  5. obj-m := gpio.o 
  6.  
  7. build: kernel_modules 
  8.  
  9. kernel_modules: 
  10.  $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules 
  11. clean: 
  12.  $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean 

在 Linux 內核源碼根目錄中輸入 make dtbs,編譯一份設備樹,下載進開發板。

在 kernel/drivers/misc/ 中新建文件夾,命名為 mygpio,里面放置 gpio.c 和 Makefile。然后輸入 make 編譯出 gpio.ko。然后拷貝進板子,insmod 上去,可以發現蜂鳴器有響。

2、pinctrl 子系統 API

pinctrl 子系統的 API 有很多,對于驅動工程師來說,pinctrl 操作一個 GPIO 只需要三步:

  1. 1、devm_pinctrl_get 
  2. 2、pinctrl_lookup_state 
  3. 3、pinctrl_select_state 

在 Linux 中,加 devm_ 開頭的函數,代表這個函數支持資源管理。一般情況下,我們寫一個驅動程序,在程序開頭都會申請資源,比如內存、中斷號等,萬一后面哪一步申請出錯,我們要回滾到第一步,去釋放已經申請的資源,這樣很麻煩。后來 Linux 開發出了很多 devm_ 開頭的函數,代表這個函數有支持資源管理的版本,不管哪一步出錯,只要錯誤退出,就會自動釋放所申請的資源。

1)devm_pinctrl_get:用于獲取設備樹中自己用 pinctrl 建立的節點的句柄;

2) pinctrl_lookup_state:用于選擇其中一個 pinctrl 的狀態,同一個 pinctrl 可以有很多狀態。比如 GPIO50 ,一開始初始化的時候是 I2C ,設備待機時候,我希望切換到普通 GPIO 模式,并且配置為下拉輸入,省電。這時候如果 pinctrl 節點有描述,我們就可以在代碼中切換 pin 的功能,從 I2C 功能切換成普通 GPIO 功能;

3) pinctrl_select_stat:用于真正設置,在上一步獲取到某個狀態以后,這一步真正設置為這個狀態。

對于 pinctrl 子系統的設備樹配置,是遵守 service 和 client 結構。

client 端各個平臺基本都是一樣的,server 端每個平臺都不一樣,使用的字符串的配置也不一樣。

設備樹配置:

  1. //client端,設置不同狀態 
  2. &test { 
  3.  pinctrl-names = "default","test_low","test_high"
  4.  pinctrl-0 = <&test_default>; 
  5.  pinctrl-1 = <&test_low>; 
  6.  pinctrl-2 = <&test_high>; 
  7.  gpio = <&gpio5 1 GPIO_ACTIVE_LOW>; 
  8.  status = "okay"
  9. }; 
  10.  
  11. //server 即 pin controller 端,設置 GPIO 幾種功能狀態 
  12. &gpio5 { 
  13.  test_default:test_default{}; 
  14.    
  15.  test_low:test_low{ 
  16.   fsl,pins = < 
  17.    MX6UL_PAD_GPIO5_IO01__GPIO5_IO01 0x17059 
  18.   > 
  19.  }; 
  20.    
  21.  test_high:test_low{ 
  22.   fsl,pins = < 
  23.    MX6UL_PAD_GPIO5_IO01__GPIO5_IO01 0x1b0b1 
  24.   > 
  25.  }; 
  26. }; 

pinctrl.c

  1. #include <linux/init.h> 
  2. #include <linux/kernel.h> 
  3. #include <linux/module.h> 
  4. #include <linux/platform_device.h> 
  5. #include <linux/delay.h> 
  6. #include <linux/pinctrl/pinctrl.h> 
  7. #include <linux/pinctrl/consumer.h> 
  8.  
  9. static int __init mypinctrl_init(void) 
  10.  int ret = 0; 
  11.  struct pinctrl *pctrl; 
  12.  struct platform_device *pdev; 
  13.  struct pinctrl_state *test_high; 
  14.  struct pinctrl_state *test_low; 
  15.    
  16.  pctrl = devm_pinctrl_get(&pdev->dev); 
  17.  if(IS_ERR(pctrl)){ 
  18.   ret = PTR_ERR(pctrl); 
  19.   printk("devm_pinctrl_get error\n"); 
  20.   return ret; 
  21.  } 
  22.    
  23.  test_high = pinctrl_lookup_state(pctrl,"test_high"); 
  24.  if(IS_ERR(pctrl)){ 
  25.   ret = PTR_ERR(test_high); 
  26.   printk("pinctrl_lookup_state test_high error\n"); 
  27.   return ret; 
  28.  } 
  29.    
  30.  test_low = pinctrl_lookup_state(pctrl,"test_low"); 
  31.  if(IS_ERR(pctrl)){ 
  32.   ret = PTR_ERR(test_low); 
  33.   printk("pinctrl_lookup_state test_low error\n"); 
  34.   return ret; 
  35.  } 
  36.    
  37.  pinctrl_select_state(pctrl,test_low); 
  38.  udelay(200); 
  39.  pinctrl_select_state(pctrl,test_high); 
  40.    
  41.  return 0; 
  42.  
  43. static void __exit mypinctrl_exit(void) 
  44.  printk("%s\n",__func__); 
  45.  
  46. module_init(mypinctrl_init); 
  47. module_exit(mypinctrl_exit); 
  48.  
  49. MUDULE_LICENSE("GPL"); 

Makefile 與上面相同,只是更改一下編譯輸出的名字。

這個驅動加載上去,可以切換GPIO口的功能狀態,我這里只是控制GPIO輸出高低,具體看你設備樹怎么配,比如你可以配置某個GPIO一開始是I2C功能,待機時候是普通GPIO功能,達到省電的目的。

補充:

設備樹是用來描述板子上的設備信息的,不同的設備其信息不同,反映到設備樹中就是屬性不同。那么我們在設備樹中添加一個硬件對應的節點的時候從哪里查閱相關的說明呢?在Linux 內核源碼中有詳細的.txt 文檔描述了如何添加節點,這些.txt 文檔叫做綁定文檔,路徑為:Linux 源碼目錄/Documentation/devicetree/bindings。

比如我們現在要想在 I.MX6ULL 這顆 SOC 的 I2C 下添加一個節點,那么就可以查看Documentation/devicetree/bindings/i2c/i2c-imx.txt,此文檔詳細的描述了 I.MX 系列的 SOC 如何在設備樹中添加 I2C 設備節點。

有時候使用的一些芯片在 Documentation/devicetree/bindings 目錄下找不到對應的文檔,這個時候就要咨詢芯片的提供商,讓他們給你提供參考的設備樹文件。

小技巧:很多時候我們看設備樹文件,里面的內容看不懂,這時候你看 .dts 最開始引用的頭文件,點進去,你就會發現這些字符串是定義在這里的。

參考文檔:

Documentation\devicetree\bindings\Pinctrl\Pinctrl-bindings.txt

Documentation\gpio\Pinctrl-bindings.txt

Documentation\devicetree\bindings\gpio\gpio.txt

Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt

【編輯推薦】

 

責任編輯:姜華 來源: 嵌入式Linux系統開發
相關推薦

2025-05-07 00:31:30

2021-07-14 09:00:00

JavaFX開發應用

2021-12-28 08:38:26

Linux 中斷喚醒系統Linux 系統

2022-01-08 20:04:20

攔截系統調用

2022-12-07 08:42:35

2011-01-10 14:41:26

2011-05-03 15:59:00

黑盒打印機

2021-08-02 07:35:19

Nacos配置中心namespace

2022-07-22 12:45:39

GNU

2020-05-15 08:07:33

JWT登錄單點

2022-10-30 10:31:42

i2ccpuftrace

2021-03-12 10:01:24

JavaScript 前端表單驗證

2021-01-19 09:06:21

MysqlDjango數據庫

2011-02-22 13:46:27

微軟SQL.NET

2021-02-26 11:54:38

MyBatis 插件接口

2023-04-26 12:46:43

DockerSpringKubernetes

2022-03-14 14:47:21

HarmonyOS操作系統鴻蒙

2022-07-27 08:16:22

搜索引擎Lucene

2009-07-19 15:02:56

2020-12-08 10:32:15

Python郵件tcp
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 九九99久久 | 日韩免费视频一区二区 | 99久久精品国产一区二区三区 | 欧美一级片 | 在线免费黄色小视频 | 午夜小视频在线观看 | 亚洲欧洲成人av每日更新 | 欧美性猛片aaaaaaa做受 | 最新毛片网站 | 欧美精品在欧美一区二区 | 香蕉视频一区二区 | 欧美11一13sex性hd | 一区二区在线免费观看视频 | 91视频在线看 | 精品国产欧美一区二区三区不卡 | 中文在线观看视频 | 久久久久久黄 | 在线亚州 | 日韩在线三级 | 国产精品99久久久久久动医院 | 天天躁日日躁狠狠的躁天龙影院 | 亚洲成av人片在线观看无码 | 欧美亚洲视频在线观看 | 玖玖视频 | 日本不卡高清视频 | 亚州综合一区 | 成人福利影院 | 国产精品日日做人人爱 | 精品国产精品三级精品av网址 | 毛片入口| 久精品久久| 99精品久久久 | 亚洲国产欧美一区二区三区久久 | 欧美日韩国产三级 | 91视频在线看| 日本在线免费观看 | 中文字幕一区二区三区在线观看 | 人和拘一级毛片c | 亚洲精品久久久蜜桃网站 | 视频一区在线播放 | 日日日干干干 |