Chinese translated version of Documentation/gpio.txt
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
communicating in English you can also ask the Chinese maintainer for
help. Contact the Chinese maintainer if this translation is outdated
or if there is a problem with the translation.
Maintainer: Grant Likely grant.likely@secretlab.ca
Linus Walleij linus.walleij@linaro.org
Chinese maintainer: Fu Wei tekkamanninja@gmail.com
Documentation/gpio.txt çä¸æç¿»è¯
å¦ææ³è¯è®ºææ´æ°æ¬æçå
容ï¼è¯·ç´æ¥èç³»åææ¡£çç»´æ¤è
ãå¦æä½ ä½¿ç¨è±æ
交æµæå°é¾çè¯ï¼ä¹å¯ä»¥åä¸æçç»´æ¤è
æ±å©ãå¦ææ¬ç¿»è¯æ´æ°ä¸åæ¶æè
ç¿»
è¯åå¨é®é¢ï¼è¯·èç³»ä¸æçç»´æ¤è
ã
è±æçç»´æ¤è
ï¼ Grant Likely grant.likely@secretlab.ca
Linus Walleij linus.walleij@linaro.org
ä¸æçç»´æ¤è
ï¼ å
ç Fu Wei tekkamanninja@gmail.com
ä¸æçç¿»è¯è
ï¼ å
ç Fu Wei tekkamanninja@gmail.com
ä¸æçæ ¡è¯è
ï¼ å
ç Fu Wei tekkamanninja@gmail.com
以ä¸ä¸ºæ£æ
GPIO æ¥å£
æ¬ææ¡£æä¾äºä¸ä¸ªå¨Linuxä¸è®¿é®GPIOçå ¬çº¦æ¦è¿°ã
è¿äºå½æ°ä»¥ gpio_* ä½ä¸ºåç¼ãå
¶ä»çå½æ°ä¸å
许使ç¨è¿æ ·çåç¼æç¸å
³ç
__gpio_* åç¼ã
ä»ä¹æ¯GPIO?
“éç¨è¾å
¥/è¾åºå£”(GPIO)æ¯ä¸ä¸ªçµæ´»çç±è½¯ä»¶æ§å¶çæ°åä¿¡å·ãä»ä»¬å¯
ç±å¤ç§è¯çæä¾,ä¸å¯¹äºä»äºåµå
¥å¼åå®å¶ç¡¬ä»¶ç Linux å¼åè
æ¥è¯´æ¯
æ¯è¾çæãæ¯ä¸ªGPIO é½ä»£è¡¨ä¸ä¸ªè¿æ¥å°ç¹å®å¼èæçæ
éµå(BGA)å°è£
ä¸
âçç âçä¸ä¸ªä½ãçµè·¯æ¿åçå¾æ¾ç¤ºäº GPIO ä¸å¤é¨ç¡¬ä»¶çè¿æ¥å
³ç³»ã
驱å¨å¯ä»¥ç¼åæéç¨ä»£ç ï¼ä»¥ä½¿æ¿çº§å¯å¨ä»£ç å¯ä¼ éå¼èé
ç½®æ°æ®ç»é©±å¨ã
çä¸ç³»ç» (SOC) å¤çå¨å¯¹ GPIO æå¾å¤§çä¾èµãå¨æäºæ
åµä¸,æ¯ä¸ª
éä¸ç¨å¼èé½å¯é
置为 GPIO,ä¸å¤§å¤æ°è¯çé½æå°æä¸äº GPIOã
å¯ç¼ç¨é»è¾å¨ä»¶(类似 FPGA) å¯ä»¥æ¹ä¾¿å°æä¾ GPIOãåçµæºç®¡çå
é³é¢ç¼è§£ç å¨è¿æ ·çå¤åè½è¯çç»å¸¸çæä¸äºè¿æ ·çå¼èæ¥å¸®å©é£äºå¼è
å®ä¹ç SOCãåæ¶è¿æéè¿ I2C æ SPI 串è¡æ»çº¿è¿æ¥çâGPIOæ©å±å¨â
è¯çã大å¤æ° PC çåæ¡¥æä¸äºæ¥æ GPIO è½åçå¼è (åªæBIOS
åºä»¶æç¥éå¦ä½ä½¿ç¨ä»ä»¬)ã
GPIO çå®é åè½å ç³»ç»èå¼ãé常ç¨æ³æ:
è¾åºå¼å¯å (é«çµå¹³=1ï¼ä½çµå¹³=0)ãä¸äºè¯çä¹æå¦ä½é©±å¨è¿äºå¼çé项,
ä¾å¦åªå 许è¾åºä¸ä¸ªå¼ãæ¯æâ线ä¸âåå ¶ä»åå¼ç±»ä¼¼ç模å¼(å¼å¾æ³¨æçæ¯
âå¼æ¼âä¿¡å·)è¾å ¥å¼å¯è¯»(1ã0)ãä¸äºè¯çæ¯æå¼èå¨é 置为âè¾åºâæ¶å读ï¼è¿å¯¹äºç±»ä¼¼
â线ä¸âçæ åµ(以æ¯æååä¿¡å·)æ¯é常æç¨çãGPIO æ§å¶å¨å¯è½æè¾å ¥
å»æ¯åº/æ¶æé»è¾,è¿ææ¶éè¦è½¯ä»¶æ§å¶ãè¾å ¥é常å¯ä½ä¸º IRQ ä¿¡å·,ä¸è¬æ¯æ²¿è§¦å,ä½ææ¶æ¯çµå¹³è§¦åãè¿æ ·ç IRQ
å¯è½é 置为系ç»å¤éäºä»¶,以å°ç³»ç»ä»ä½åèç¶æä¸å¤éãé常ä¸ä¸ª GPIO æ ¹æ®ä¸å产åçµè·¯æ¿çéæ±,å¯ä»¥é 置为è¾å ¥æè¾åº,ä¹æä»
æ¯æååçã大é¨å GPIO å¯ä»¥å¨ææèªæéæ¶è®¿é®,ä½æ¯é常ç±ä¸²è¡æ»çº¿æ©å±ç GPIO
ä¸å 许ææèªæéãä½æäºç³»ç»ä¹æ¯æè¿ç§ç±»åã
对äºç»å®ççµè·¯æ¿,æ¯ä¸ª GPIO é½ç¨äºæ个ç¹å®çç®ç,å¦çæ§ MMC/SD å¡ç
æå
¥/移é¤ãæ£æµå¡çåä¿æ¤ç¶æãé©±å¨ LEDãé
ç½®æ¶åå¨ã模æ串è¡æ»çº¿ã
å¤ä½ç¡¬ä»¶çé¨çãæç¥å¼å
³ç¶æççã
GPIO å ¬çº¦
注æ,è¿ä¸ªå«åâå
¬çº¦âï¼å 为è¿ä¸æ¯å¼ºå¶æ§çï¼ä¸éµå¾ªè¿ä¸ªå
¬çº¦æ¯æ 伤大é
çï¼
å 为æ¤æ¶å¯ç§»æ¤æ§å¹¶ä¸éè¦ãGPIO 常ç¨äºæ¿çº§ç¹å®ççµè·¯é»è¾,çè³å¯è½
éççµè·¯æ¿ççæ¬èæ¹åï¼ä¸ä¸å¯è½å¨ä¸å走线ççµè·¯æ¿ä¸ä½¿ç¨ãä»
æå¨å°æ°
åè½ä¸æå
·æå¯ç§»æ¤æ§ï¼å
¶ä»åè½æ¯å¹³å°ç¹å®ãè¿ä¹æ¯ç±äºâè¶åâçé»è¾é æçã
æ¤å¤ï¼è¿ä¸éè¦ä»»ä½çæ§è¡æ¡æ¶ï¼åªæ¯ä¸ä¸ªæ¥å£ãæ个平å°å¯è½éè¿ä¸ä¸ªç®åå°
访é®è¯çå¯åå¨çå
èå½æ°æ¥å®ç°å®ï¼å
¶ä»å¹³å°å¯è½éè¿å§æä¸ç³»åä¸åçGPIO
æ§å¶å¨çæ½è±¡å½æ°æ¥å®ç°å®ã(æä¸äºå¯éç代ç è½æ¯æè¿ç§çç¥çå®ç°,æ¬ææ¡£
åé¢ä¼ä»ç»ï¼ä½ä½ä¸º GPIO æ¥å£ç客æ·ç«¯é©±å¨ç¨åºå¿
é¡»ä¸å®çå®ç°æ å
³ã)
ä¹å°±æ¯è¯´,å¦æå¨ä»ä»¬çå¹³å°ä¸æ¯æè¿ä¸ªå
¬çº¦ï¼é©±å¨åºå°½å¯è½ç使ç¨å®ãåæ¶ï¼å¹³å°
å¿
é¡»å¨ Kconfig ä¸éæ© ARCH_REQUIRE_GPIOLIB æè
ARCH_WANT_OPTIONAL_GPIOLIB
é项ãé£äºè°ç¨æ å GPIO å½æ°ç驱å¨åºè¯¥å¨ Kconfig å
¥å£ä¸å£°æä¾èµGENERIC_GPIOã
å½é©±å¨å
å«æ件:
#include <linux/gpio.h>
å GPIO å½æ°æ¯å¯ç¨,æ 论æ¯âçå®ä»£ç âè¿æ¯ç»ä¼åè¿çè¯å¥ãå¦æä½ éµå®
è¿ä¸ªå
¬çº¦ï¼å½ä½ ç代ç å®æåï¼å¯¹å
¶ä»çå¼åè
æ¥è¯´ä¼æ´å®¹æçæåç»´æ¤ã
注æï¼è¿äºæä½å å«æç¨å¹³å°ç I/O å±é代ç ï¼é©±å¨æ é¡»æ¾å¼å°è°ç¨ä»ä»¬ã
æ è¯ GPIO
GPIO æ¯éè¿æ 符å·æ´åæ¥æ è¯ç,èå´æ¯ 0 å° MAX_INTãä¿çâè´âæ°
ç¨äºå
¶ä»ç®ç,ä¾å¦æ è¯ä¿¡å·âå¨è¿ä¸ªæ¿åä¸ä¸å¯ç¨âææ示é误ãæªæ¥è§¦åºå±
硬件ç代ç ä¼å¿½ç¥è¿äºæ´æ°ã
å¹³å°ä¼å®ä¹è¿äºæ´æ°çç¨æ³,ä¸éå¸¸ä½¿ç¨ #define æ¥å®ä¹ GPIOï¼è¿æ ·
æ¿çº§ç¹å®çå¯å¨ä»£ç å¯ä»¥ç´æ¥å
³èç¸åºçåçå¾ãç¸å¯¹æ¥è¯´ï¼é©±å¨åºè¯¥ä»
使ç¨
å¯å¨ä»£ç ä¼ éè¿æ¥ç GPIO ç¼å·ï¼ä½¿ç¨ platform_data ä¿åæ¿çº§ç¹å®
å¼èé
ç½®æ°æ® (åæ¶è¿æå
¶ä»é¡»è¦çæ¿çº§ç¹å®æ°æ®)ï¼é¿å
å¯è½åºç°çé®é¢ã
ä¾å¦ä¸ä¸ªå¹³å°ä½¿ç¨ç¼å· 32-159 æ¥æ è¯ GPIO,èå¨å¦ä¸ä¸ªå¹³å°ä½¿ç¨ç¼å·0-63
æ è¯ä¸ç» GPIO æ§å¶å¨,64-79æ è¯å¦ä¸ç±» GPIO æ§å¶å¨,ä¸å¨ä¸ä¸ªå«æ
FPGA çç¹å®æ¿åä¸ä½¿ç¨ 80-95ãç¼å·ä¸ä¸å®è¦è¿ç»,é£äºå¹³å°ä¸ï¼ä¹å¯ä»¥
使ç¨ç¼å·2000-2063æ¥æ è¯ä¸ä¸ª I2C æ¥å£ç GPIO æ©å±å¨ä¸ç GPIOã
å¦æä½ è¦åå§åä¸ä¸ªå¸¦ææ æ GPIO ç¼å·çç»æä½,å¯ä»¥ä½¿ç¨ä¸äºè´ç¼ç
(妔-EINVAL”)ï¼é£å°ä½¿å
¶æ°¸è¿ä¸ä¼æ¯ææãæ¥æµè¯è¿æ ·ä¸ä¸ªç»æä½ä¸çç¼å·
æ¯å¦å
³èä¸ä¸ª GPIOï¼ä½ å¯ä½¿ç¨ä»¥ä¸æè¨:
int gpio_is_valid(int number);
å¦æç¼å·ä¸åå¨ï¼å请æ±åéæ¾ GPIO çå½æ°å°æç»æ§è¡ç¸å
³æä½(è§ä¸æ)ã
å
¶ä»ç¼å·ä¹å¯è½è¢«æç»,æ¯å¦ä¸ä¸ªç¼å·å¯è½åå¨ï¼ä½ææ¶å¨ç»å®ççµè·¯ä¸ä¸å¯ç¨ã
ä¸ä¸ªå¹³å°æ¯å¦æ¯æå¤ä¸ª GPIO æ§å¶å¨ä¸ºå¹³å°ç¹å®çå®ç°é®é¢ï¼å°±åæ¯å¦å¯ä»¥
å¨ GPIO ç¼å·ç©ºé´ä¸æâ空æ´âåæ¯å¦å¯ä»¥å¨è¿è¡æ¶æ·»å æ°çæ§å¶å¨ä¸æ ·ã
è¿äºé®é¢ä¼å½±åå
¶ä»äºæ
ï¼å
æ¬ç¸é»ç GPIO ç¼å·æ¯å¦åå¨çã
ä½¿ç¨ GPIO
对äºä¸ä¸ª GPIOï¼ç³»ç»åºè¯¥åç第ä¸ä»¶äºæ
å°±æ¯éè¿ gpio_request()
å½æ°åé
å®ï¼è§ä¸æã
æ¥ä¸æ¥æ¯è®¾ç½®I/Oæ¹åï¼è¿é常æ¯å¨æ¿çº§å¯å¨ä»£ç ä¸ä¸ºæ使ç¨ç GPIO 设置
platform_device æ¶å®æã
/* 设置为è¾å
¥æè¾åº, è¿å 0 æè´çé误代ç */
int gpio_direction_input(unsigned gpio);
int gpio_direction_output(unsigned gpio, int value);
è¿åå¼ä¸ºé¶ä»£è¡¨æåï¼å¦åè¿åä¸ä¸ªè´çé误代ç ãè¿ä¸ªè¿åå¼éè¦æ£æ¥ï¼å 为
get/set(è·å/设置)å½æ°è°ç¨æ²¡æ³è¿åé误,ä¸æå¯è½æ¯é
ç½®é误ãé常ï¼
ä½ åºè¯¥å¨è¿ç¨ä¸ä¸æä¸è°ç¨è¿äºå½æ°ãç¶è,对äºèªæéå®å
¨ç GPIOï¼å¨æ¿å
å¯å¨çæ©æãè¿ç¨å¯å¨å使ç¨ä»ä»¬ä¹æ¯å¯ä»¥çã
对äºä½ä¸ºè¾åºç GPIOï¼ä¸ºå
¶æä¾åå§è¾åºå¼ï¼å¯¹äºé¿å
å¨ç³»ç»å¯å¨æé´åºç°
ä¿¡å·æ¯åºæ¯å¾æ帮å©çã
为äºä¸ä¼ ç»ç GPIO æ¥å£å
¼å®¹, å¨è®¾ç½®ä¸ä¸ª GPIO æ¹åæ¶ï¼å¦æå®è¿æªè¢«ç³è¯·ï¼
åéå«äºç³è¯·é£ä¸ª GPIO çæä½(è§ä¸æ)ãè¿ç§å
¼å®¹æ§æ£å¨ä»å¯éç gpiolib
æ¡æ¶ä¸ç§»é¤ã
å¦æè¿ä¸ª GPIO ç¼ç ä¸åå¨ï¼æè
ç¹å®ç GPIO ä¸è½ç¨äºé£ç§æ¨¡å¼ï¼åæ¹å
设置å¯è½å¤±è´¥ãä¾èµå¯å¨åºä»¶æ¥æ£ç¡®å°è®¾ç½®æ¹åé常æ¯ä¸ä¸ªå主æï¼å 为å®å¯è½
é¤äºå¯å¨Linuxï¼å¹¶æ²¡æåæ´å¤çéªè¯å·¥ä½ã(åç, æ¿åçå¯å¨ä»£ç å¯è½éè¦
å°è¿ä¸ªå¤ç¨çå¼è设置为 GPIOï¼å¹¶æ£ç¡®å°é
ç½®ä¸æ/ä¸æçµé»ã)
访é®èªæéå®å ¨ç GPIO
大å¤æ° GPIO æ§å¶å¨å¯ä»¥éè¿å
å读/åæ令æ¥è®¿é®ãè¿äºæ令ä¸ä¼ä¼ç ,å¯ä»¥
å®å
¨å°å¨ç¡¬(é线ç¨)ä¸æä¾ç¨å类似çä¸ä¸æä¸å®æã
对äºé£äºç¨ gpio_cansleep()æµè¯æ»æ¯è¿å失败ç GPIO(è§ä¸æ)ï¼ä½¿ç¨
以ä¸çå½æ°è®¿é®:
/* GPIO è¾å
¥:è¿åé¶æéé¶ */
int gpio_get_value(unsigned gpio);
/* GPIO è¾åº */
void gpio_set_value(unsigned gpio, int value);
GPIOå¼æ¯å¸å°å¼ï¼é¶è¡¨ç¤ºä½çµå¹³ï¼éé¶è¡¨ç¤ºé«çµå¹³ãå½è¯»åä¸ä¸ªè¾åºå¼èçå¼æ¶ï¼
è¿åå¼åºè¯¥æ¯å¼èä¸çå¼ãè¿ä¸ªå¼ä¸æ»æ¯åè¾åºå¼ç¸ç¬¦ï¼å 为åå¨å¼æ¼è¾åºä¿¡å·å
è¾åºå»¶è¿é®é¢ã
以ä¸ç get/set å½æ°æ é误è¿åå¼ï¼å 为ä¹å gpio_direction_*()åºå·²æ£æ¥è¿
å
¶æ¯å¦ä¸ºâæ æGPIOâãæ¤å¤ï¼è¿éè¦æ³¨æçæ¯å¹¶ä¸æ¯ææå¹³å°é½å¯ä»¥ä»è¾åºå¼è
ä¸è¯»åæ°æ®ï¼å¯¹äºä¸è½è¯»åçå¼èåºæ»è¿åé¶ãå¦å¤ï¼å¯¹é£äºå¨ååä¸ä¸æä¸æ æ³
å®å
¨è®¿é®ç GPIO (è¯è
注ï¼å 为访é®å¯è½å¯¼è´ä¼ç )使ç¨è¿äºå½æ°æ¯ä¸åéç
(è§ä¸æ)ã
å¨ GPIO ç¼å·(è¿æè¾åºãå¼)为常æ°çæ
åµä¸,é¼å±éè¿å¹³å°ç¹å®çå®ç°æ¥ä¼å
è¿ä¸¤ä¸ªå½æ°æ¥è®¿é® GPIO å¼ãè¿ç§æ
åµ(读åä¸ä¸ªç¡¬ä»¶å¯åå¨)ä¸åªéè¦å æ¡æ令
æ¯å¾æ£å¸¸ç,ä¸æ é¡»èªæéãè¿ç§ä¼åå½æ°æ¯èµ·é£äºå¨åç¨åºä¸è±è´¹è®¸å¤æ令ç
å½æ°å¯ä»¥ä½¿å¾æ¨¡ææ¥å£(è¯è
注:ä¾å¦ GPIO 模æ I2Cã1-wire æ SPI)ç
åºç¨(å¨ç©ºé´åæ¶é´ä¸é½)æ´å
·æçã
访é®å¯è½ä¼ç ç GPIO
æäº GPIO æ§å¶å¨å¿
é¡»éè¿åºäºæ»çº¿(å¦ I2C æ SPI)çæ¶æ¯è®¿é®ã读æåè¿äº
GPIO å¼çå½ä»¤éè¦çå¾
å
¶ä¿¡æ¯æå°éé¦æåéå½ä»¤ï¼åè·å¾å
¶åé¦ãæé´éè¦
ä¼ç ï¼è¿ä¸è½å¨ IRQ ä¾ç¨(ä¸æä¸ä¸æ)ä¸æ§è¡ã
æ¯ææ¤ç±» GPIO çå¹³å°éè¿ä»¥ä¸å½æ°è¿åéé¶å¼æ¥åºååºè¿ç§ GPIOã(æ¤å½æ°éè¦
ä¸ä¸ªä¹åéè¿ gpio_request åé
å°çææ GPIO ç¼å·):
int gpio_cansleep(unsigned gpio);
为äºè®¿é®è¿ç§ GPIO,å æ ¸å®ä¹äºä¸å¥ä¸åçå½æ°:
/* GPIO è¾å
¥:è¿åé¶æéé¶ ,å¯è½ä¼ä¼ç */
int gpio_get_value_cansleep(unsigned gpio);
/* GPIO è¾åº,å¯è½ä¼ä¼ç */
void gpio_set_value_cansleep(unsigned gpio, int value);
访é®è¿æ ·ç GPIO éè¦ä¸ä¸ªå
许ä¼ç çä¸ä¸æï¼ä¾å¦çº¿ç¨ IRQ å¤çä¾ç¨ï¼å¹¶ç¨ä»¥ä¸ç
访é®å½æ°æ¿æ¢é£äºæ²¡æ cansleep()åç¼çèªæéå®å
¨è®¿é®å½æ°ã
é¤äºè¿äºè®¿é®å½æ°å¯è½ä¼ç ï¼ä¸å®ä»¬æä½ç GPIO ä¸è½å¨ç¡¬ä»¶ IRQ å¤çä¾ç¨ä¸è®¿é®ç
äºå®ï¼è¿äºå¤çä¾ç¨å®é
ä¸åèªæéå®å
¨çå½æ°æ¯ä¸æ ·çã
** é¤æ¤ä¹å¤ ** è°ç¨è®¾ç½®åé
ç½®æ¤ç±» GPIO çå½æ°ä¹å¿
é¡»å¨å
许ä¼ç çä¸ä¸æä¸ï¼
å 为å®ä»¬å¯è½ä¹éè¦è®¿é® GPIO æ§å¶å¨è¯ç: (è¿äºè®¾ç½®å½æ°é常å¨æ¿çº§å¯å¨ä»£ç æè
驱å¨æ¢æµ/æå¼ä»£ç ä¸ï¼æ以è¿æ¯ä¸ä¸ªå®¹æ满足ç约ææ¡ä»¶ã)
gpio_direction_input()
gpio_direction_output()
gpio_request()
gpio_request_one()
gpio_request_array()
gpio_free_array()
gpio_free()
gpio_set_debounce()
声æåéæ¾ GPIO
为äºæå©äºæè·ç³»ç»é ç½®é误,å®ä¹äºä¸¤ä¸ªå½æ°ã
/* ç³è¯· GPIO, è¿å 0 æè´çé误代ç .
* é空æ ç¾å¯è½æå©äºè¯æ.
*/
int gpio_request(unsigned gpio, const char *label);
/* éæ¾ä¹å声æç GPIO */
void gpio_free(unsigned gpio);
å°æ æç GPIO ç¼ç ä¼ éç» gpio_request()ä¼å¯¼è´å¤±è´¥ï¼ç³è¯·ä¸ä¸ªå·²ä½¿ç¨è¿ä¸ª
å½æ°å£°æè¿ç GPIO ä¹ä¼å¤±è´¥ãgpio_request()çè¿åå¼å¿
é¡»æ£æ¥ãä½ åºè¯¥å¨
è¿ç¨ä¸ä¸æä¸è°ç¨è¿äºå½æ°ãç¶è,对äºèªæéå®å
¨ç GPIO,å¨æ¿åå¯å¨çæ©æã
è¿å
¥è¿ç¨ä¹åæ¯å¯ä»¥ç³è¯·çã
è¿ä¸ªå½æ°å®æ两个åºæ¬çç®æ ãä¸æ¯æ è¯é£äºå®é
ä¸å·²ä½ä¸º GPIO 使ç¨çä¿¡å·çº¿ï¼
è¿æ ·ä¾¿äºæ´å¥½å°è¯æ;ç³»ç»å¯è½éè¦æå¡å ç¾ä¸ªå¯ç¨ç GPIOï¼ä½æ¯å¯¹äºä»»ä½ä¸ä¸ª
ç»å®ççµè·¯æ¿é常åªæä¸äºè¢«ä½¿ç¨ãå¦ä¸ä¸ªç®çæ¯æè·å²çªï¼æ¥æé误:å¦ä¸¤ä¸ªæ
æ´å¤é©±å¨é误å°è®¤ä¸ºä»ä»¬å·²ç»ç¬å äºæ个信å·çº¿,ææ¯é误å°è®¤ä¸ºç§»é¤ä¸ä¸ªç®¡çç
æ个已æ¿æ´»ä¿¡å·ç驱å¨æ¯å®å
¨çãä¹å°±æ¯è¯´ï¼ç³è¯· GPIO çä½ç¨ç±»ä¼¼ä¸ç§éæºå¶ã
æäºå¹³å°å¯è½ä¹ä½¿ç¨ GPIO ä½ä¸ºçµæºç®¡çæ¿æ´»ä¿¡å·(ä¾å¦éè¿å
³éæªä½¿ç¨è¯çåºå
ç®åå°å
³éæªä½¿ç¨æ¶é)ã
å¯¹äº GPIO ä½¿ç¨ pinctrl åç³»ç»å·²ç¥çå¼èï¼åç³»ç»åºè¯¥è¢«åç¥å
¶ä½¿ç¨æ
åµï¼
ä¸ä¸ª gpiolib 驱å¨ç .request()æä½åºè°ç¨ pinctrl_request_gpio()ï¼
è gpiolib 驱å¨ç .free()æä½åºè°ç¨ pinctrl_free_gpio()ãpinctrl
åç³»ç»å
许 pinctrl_request_gpio()å¨æ个å¼èæå¼èç»ä»¥å¤ç¨å½¢å¼âå±äºâ
ä¸ä¸ªè®¾å¤æ¶é½æåè¿åã
ä»»ä½é¡»å° GPIO ä¿¡å·å¯¼åéå½å¼èçå¼èå¤ç¨ç¡¬ä»¶çç¼ç¨åºè¯¥åçå¨ GPIO
驱å¨ç .direction_input()æ .direction_output()å½æ°ä¸ï¼ä»¥å
ä»»ä½è¾åº GPIO å¼ç设置ä¹åãè¿æ ·å¯ä½¿ä»å¼èç¹æ®åè½å° GPIO ç转æ¢
ä¸ä¼å¨å¼è产çæ¯åºæ³¢å½¢ãææ¶å½ç¨ä¸ä¸ª GPIO å®ç°å
¶ä¿¡å·é©±å¨ä¸ä¸ªé GPIO
硬件模åç解å³æ¹æ¡æ¶ï¼å°±éè¦è¿ç§æºå¶ã
æäºå¹³å°å
许é¨åæææ GPIO ä¿¡å·ä½¿ç¨ä¸åçå¼èã类似çï¼GPIO æå¼èç
å
¶ä»æ¹é¢ä¹éè¦é
ç½®ï¼å¦ä¸æ/ä¸æãå¹³å°è½¯ä»¶åºè¯¥å¨å¯¹è¿äº GPIO è°ç¨
gpio_request()åå°è¿ç±»ç»èé
置好ï¼ä¾å¦ä½¿ç¨ pinctrl åç³»ç»çæ å°è¡¨ï¼
ä½¿å¾ GPIO çç¨æ·æ é¡»å
³æ³¨è¿äºç»èã
è¿æä¸ä¸ªå¼å¾æ³¨æçæ¯å¨éæ¾ GPIO åï¼ä½ å¿ é¡»åæ¢ä½¿ç¨å®ã
注æ:ç³è¯·ä¸ä¸ª GPIO 并没æ以任ä½æ¹å¼é
ç½®å®ï¼åªä¸è¿æ è¯é£ä¸ª GPIO å¤äºä½¿ç¨
ç¶æãå¿
é¡»æå¦å¤ç代ç æ¥å¤çå¼èé
ç½®(å¦æ§å¶ GPIO 使ç¨çå¼èãä¸æ/ä¸æ)ã
èèå°å¤§å¤æ°æ
åµä¸å£°æ GPIO ä¹åå°±ä¼ç«å³é
ç½®å®ä»¬,æ以å®ä¹äºä»¥ä¸ä¸ä¸ªè¾
å©å½æ°:
/* ç³è¯·ä¸ä¸ª GPIO ä¿¡å·, åæ¶éè¿ç¹å®ç'flags'åå§åé
ç½®,
* å
¶ä»å gpio_request()çåæ°åè¿åå¼ç¸å
*
*/
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
/* å¨å个å½æ°ä¸ç³è¯·å¤ä¸ª GPIO
*/
int gpio_request_array(struct gpio *array, size_t num);
/* å¨å个å½æ°ä¸éæ¾å¤ä¸ª GPIO
*/
void gpio_free_array(struct gpio *array, size_t num);
è¿é ‘flags’ å½åå®ä¹å¯æå®ä»¥ä¸å±æ§:
* GPIOF_DIR_IN - é
ç½®æ¹å为è¾å
¥
* GPIOF_DIR_OUT - é
ç½®æ¹å为è¾åº
* GPIOF_INIT_LOW - å¨ä½ä¸ºè¾åºæ¶,åå§å¼ä¸ºä½çµå¹³
* GPIOF_INIT_HIGH - å¨ä½ä¸ºè¾åºæ¶,åå§å¼ä¸ºé«çµå¹³
* GPIOF_OPEN_DRAIN - gpioå¼è为å¼æ¼ä¿¡å·
* GPIOF_OPEN_SOURCE - gpioå¼è为æºæå¼è·¯ä¿¡å·
* GPIOF_EXPORT_DIR_FIXED - å° gpio 导åºå° sysfsï¼å¹¶ä¿ææ¹å
* GPIOF_EXPORT_DIR_CHANGEABLE - åæ ·æ¯å¯¼åº, ä½å
许æ¹åæ¹å
å 为 GPIOF_INIT_* ä» æå¨é 置为è¾åºçæ¶åæåå¨,æ以ææçç»å为:
* GPIOF_IN - é
置为è¾å
¥
* GPIOF_OUT_INIT_LOW - é
置为è¾åº,并åå§å为ä½çµå¹³
* GPIOF_OUT_INIT_HIGH - é
置为è¾åº,并åå§å为é«çµå¹³
å½è®¾ç½® flag 为 GPIOF_OPEN_DRAIN æ¶ï¼åå设å¼èæ¯å¼æ¼ä¿¡å·ãè¿æ ·çå¼è
å°ä¸ä¼å¨è¾åºæ¨¡å¼ä¸ç½®1ãè¿æ ·çå¼èéè¦è¿æ¥ä¸æçµé»ãéè¿ä½¿è½è¿ä¸ªæ å¿ï¼gpioåº
å°ä¼å¨è¢«è¦æ±è¾åºæ¨¡å¼ä¸ç½®1æ¶å°å¼èå为è¾å
¥ç¶ææ¥ä½¿å¼èç½®é«ãå¼èå¨è¾åºæ¨¡å¼ä¸
éè¿ç½®0使å
¶è¾åºä½çµå¹³ã
å½è®¾ç½® flag 为 GPIOF_OPEN_SOURCE æ¶ï¼åå设å¼è为æºæå¼è·¯ä¿¡å·ãè¿æ ·çå¼è
å°ä¸ä¼å¨è¾åºæ¨¡å¼ä¸ç½®0ãè¿æ ·çå¼èéè¦è¿æ¥ä¸æçµé»ãéè¿ä½¿è½è¿ä¸ªæ å¿ï¼gpioåº
å°ä¼å¨è¢«è¦æ±è¾åºæ¨¡å¼ä¸ç½®0æ¶å°å¼èå为è¾å
¥ç¶ææ¥ä½¿å¼èç½®ä½ãå¼èå¨è¾åºæ¨¡å¼ä¸
éè¿ç½®1使å
¶è¾åºé«çµå¹³ã
å°æ¥è¿äºæ å¿å¯è½æ©å±å°æ¯ææ´å¤çå±æ§ã
æ´è¿ä¸æ¥,为äºæ´ç®åå°å£°æ/éæ¾å¤ä¸ª GPIO,’struct gpio’被å¼è¿æ¥å°è£
ææ
è¿ä¸ä¸ªé¢å:
struct gpio {
unsigned gpio;
unsigned long flags;
const char *label;
};
ä¸ä¸ªå ¸åçç¨ä¾:
static struct gpio leds_gpios[] = {
{ 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* é»è®¤å¼å¯ */
{ 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* é»è®¤å
³é */
{ 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* é»è®¤å
³é */
{ 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* é»è®¤å
³é */
{ ... },
};
err = gpio_request_one(31, GPIOF_IN, "Reset Button");
if (err)
...
err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
if (err)
...
gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
GPIO æ å°å° IRQ
GPIO ç¼å·æ¯æ 符å·æ´æ°;IRQ ç¼å·ä¹æ¯ãè¿äºææäºä¸¤ä¸ªé»è¾ä¸ä¸åçå½å空é´
(GPIO 0 ä¸ä¸å®ä½¿ç¨ IRQ 0)ãä½ å¯ä»¥éè¿ä»¥ä¸å½æ°å¨å®ä»¬ä¹é´å®ç°æ å°:
/* æ å° GPIO ç¼å·å° IRQ ç¼å· */
int gpio_to_irq(unsigned gpio);
/* æ å° IRQ ç¼å·å° GPIO ç¼å· (å°½éé¿å
使ç¨) */
int irq_to_gpio(unsigned irq);
å®ä»¬çè¿åå¼ä¸ºå¯¹åºå½å空é´çç¸å
³ç¼å·ï¼ææ¯è´çé误代ç (å¦ææ æ³æ å°)ã
(ä¾å¦,æäº GPIO æ æ³å为 IRQ 使ç¨ã)以ä¸çç¼å·é误æ¯æªç»æ£æµç:使ç¨ä¸ä¸ª
æªéè¿ gpio_direction_input()é
置为è¾å
¥ç GPIO ç¼å·ï¼æè
使ç¨ä¸ä¸ª
并éæ¥æºäºgpio_to_irq()ç IRQ ç¼å·ã
è¿ä¸¤ä¸ªæ å°å½æ°å¯è½ä¼å¨ä¿¡å·ç¼å·çå å计ç®è¿ç¨ä¸è±äºæ¶é´ãå®ä»¬ä¸å¯ä¼ç ã
gpio_to_irq()è¿åçéé误å¼å¯ä»¥ä¼ éç» request_irq()æè
free_irq()ã
å®ä»¬é常éè¿æ¿çº§ç¹å®çåå§å代ç åæ¾å°å¹³å°è®¾å¤ç IRQ èµæºä¸ã注æ:IRQ
触åéé¡¹æ¯ IRQ æ¥å£çä¸é¨åï¼å¦ IRQF_TRIGGER_FALLINGï¼ç³»ç»å¤éè½å
ä¹æ¯å¦æ¤ã
irq_to_gpio()è¿åçéé误å¼å¤§å¤æ°é常å¯ä»¥è¢« gpio_get_value()æ使ç¨ï¼
æ¯å¦å¨ IRQ æ¯æ²¿è§¦åæ¶åå§åææ´æ°é©±å¨ç¶æã注ææäºå¹³å°ä¸æ¯æåæ å°,æ以
ä½ åºè¯¥å°½éé¿å
使ç¨å®ã
模æå¼æ¼ä¿¡å·
ææ¶å¨åªæä½çµå¹³ä¿¡å·ä½ä¸ºå®é
驱å¨ç»æ(è¯è
注:å¤ä¸ªè¾åºè¿æ¥äºä¸ç¹ï¼é»è¾çµå¹³
ç»æ为ææè¾åºçé»è¾ä¸)çæ¶å,å
±äº«çä¿¡å·çº¿éè¦ä½¿ç¨âå¼æ¼âä¿¡å·ã(该æ¯è¯
éç¨äº CMOS 管ï¼è TTL ç¨âéçµæå¼è·¯âã)ä¸ä¸ªä¸æçµé»ä½¿ä¿¡å·ä¸ºé«çµå¹³ãè¿
ææ¶è¢«ç§°ä¸ºâ线ä¸âãå®é
ä¸ï¼ä»è´é»è¾(ä½çµå¹³ä¸ºç)çè§åº¦æ¥çï¼è¿æ¯ä¸ä¸ªâ线æâã
ä¸ä¸ªå¼æ¼ä¿¡å·ç常è§ä¾åæ¯å
±äº«çä½çµå¹³ä½¿è½ IRQ ä¿¡å·çº¿ãæ¤å¤,ææ¶ååæ°æ®æ»çº¿
ä¿¡å·ä¹ä½¿ç¨æ¼æå¼è·¯ä¿¡å·ã
æäº GPIO æ§å¶å¨ç´æ¥æ¯æå¼æ¼è¾åºï¼è¿æ许å¤ä¸æ¯æãå½ä½ éè¦å¼æ¼ä¿¡å·ï¼ä½
硬件åä¸ç´æ¥æ¯æçæ¶åï¼ä¸ä¸ªå¸¸ç¨çæ¹æ³æ¯ç¨ä»»ä½å³å¯ä½è¾å
¥ä¹å¯ä½è¾åºç GPIO
å¼èæ¥æ¨¡æ:
LOW: gpio_direction_output(gpio, 0) … è¿ä»£ç 驱å¨ä¿¡å·å¹¶è¦ç
ä¸æé
ç½®ã
HIGH: gpio_direction_input(gpio) … è¿ä»£ç å
³éè¾åº,æ以ä¸æçµé»
(æå
¶ä»çä¸äºå¨ä»¶)æ§å¶äºä¿¡å·ã
å¦æä½ å°ä¿¡å·çº¿â驱å¨â为é«çµå¹³ï¼ä½æ¯ gpio_get_value(gpio)æ¥åäºä¸ä¸ª
ä½çµå¹³(å¨éå½çä¸åæ¶é´å)ï¼ä½ å°±å¯ä»¥ç¥éæ¯å
¶ä»çä¸äºç»ä»¶å°å
±äº«ä¿¡å·çº¿æä½äºã
è¿ä¸ä¸å®æ¯é误çãä¸ä¸ªå¸¸è§çä¾åå°±æ¯ I2C æ¶éç延é¿ï¼ä¸ä¸ªéè¦è¾æ
¢æ¶éç
ä»è®¾å¤å»¶è¿ SCK çä¸å沿ï¼è I2C 主设å¤ç¸åºå°è°æ´å
¶ä¿¡å·ä¼ è¾éçã
è¿äºå ¬çº¦å¿½ç¥äºä»ä¹?
è¿äºå
¬çº¦å¿½ç¥çæ大ä¸ä»¶äºå°±æ¯å¼èå¤ç¨ï¼å 为è¿å±äºé«åº¦è¯çç¹å®çå±æ§ä¸
没æå¯ç§»æ¤æ§ãæ个平å°å¯è½ä¸éè¦æç¡®çå¤ç¨ä¿¡æ¯ï¼æç对äºä»»æç»å®çå¼è
å¯è½åªæ两个åè½é项ï¼æçå¯è½æ¯ä¸ªå¼èæå
«ä¸ªåè½é项ï¼æçå¯è½å¯ä»¥å°
å 个å¼èä¸çä»»ä½ä¸ä¸ªä½ä¸ºç»å®ç GPIOã(æ¯çï¼è¿äºä¾åé½æ¥èªäºå½åè¿è¡
Linux çç³»ç»ã)
å¨æäºç³»ç»ä¸,ä¸å¼èå¤ç¨ç¸å
³çæ¯é
ç½®å使è½éæçä¸ãä¸æ模å¼ã并ä¸æ¯ææ
å¹³å°é½æ¯æè¿ç§æ¨¡å¼,æè
ä¸ä¼ä»¥ç¸åçæ¹å¼æ¥æ¯æè¿ç§æ¨¡å¼ï¼ä¸ä»»ä½ç»å®ççµè·¯æ¿
å¯è½ä½¿ç¨å¤ç½®çä¸æ(æä¸æ)çµé»,è¿æ¶è¯çä¸çå°±ä¸åºè¯¥ä½¿ç¨ã(å½ä¸ä¸ªçµè·¯éè¦
5kOhm çæå¨çµé»,è¯çä¸ç 100 kOhm çµé»å°±ä¸è½åå°ã)åæ ·çï¼é©±å¨è½å
(2 mA vs 20 mA)åçµå(1.8V vs 3.3V)æ¯å¹³å°ç¹å®é®é¢,å°±å模åä¸æ ·å¨
å¯é
ç½®å¼èå GPIO ä¹é´(没)æä¸ä¸å¯¹åºçå
³ç³»ã
è¿æå
¶ä»ä¸äºç³»ç»ç¹å®çæºå¶æ²¡æå¨è¿éæåºï¼ä¾å¦ä¸è¿°çè¾å
¥å»æ¯åºå线ä¸è¾åº
é项ã硬件å¯è½æ¯ææ¹é读æå GPIOï¼ä½æ¯é£ä¸è¬æ¯é
ç½®ç¸å
³çï¼å¯¹äºå¤äºåä¸
ååº(bank)çGPIOã(GPIO é常以 16 æ 32 个ç»æä¸ä¸ªåºåï¼ä¸ä¸ªç»å®ç
çä¸ç³»ç»ä¸è¬æå 个è¿æ ·çåºåã)æäºç³»ç»å¯ä»¥éè¿è¾åº GPIO 触å IRQï¼
æè
ä»å¹¶é以 GPIO 管ççå¼èåå¼ãè¿äºæºå¶çç¸å
³ä»£ç 没æå¿
è¦å
·æå¯ç§»æ¤æ§ã
å½åï¼å¨æå®ä¹ GPIO 并ä¸æ¯æ åçï¼ä¾å¦ä½ä¸ºé
ç½®ä¸ä¸ªå¸¦ææäº GPIO æ©å±å¨ç
éå çµè·¯æ¿çå¯ä½ç¨ã
GPIO å®ç°è çæ¡æ¶ (å¯é)
åé¢æå°äºï¼æä¸ä¸ªå¯éçå®ç°æ¡æ¶ï¼è®©å¹³å°ä½¿ç¨ç¸åçç¼ç¨æ¥å£ï¼æ´å ç®åå°æ¯æ
ä¸åç§ç±»ç GPIO æ§å¶å¨ãè¿ä¸ªæ¡æ¶ç§°ä¸º”gpiolib”ã
ä½ä¸ºä¸ä¸ªè¾
å©è°è¯åè½ï¼å¦æ debugfs å¯ç¨ï¼å°±ä¼æä¸ä¸ª /sys/kernel/debug/gpio
æ件ãéè¿è¿ä¸ªæ¡æ¶ï¼å®å¯ä»¥ååºææ注åçæ§å¶å¨,以åå½åæ£å¨ä½¿ç¨ä¸ç GPIO
çç¶æã
æ§å¶å¨é©±å¨: gpio_chip
å¨æ¡æ¶ä¸æ¯ä¸ª GPIO æ§å¶å¨é½å
è£
为ä¸ä¸ª “struct gpio_chip”ï¼ä»å
å«äº
该类åçæ¯ä¸ªæ§å¶å¨ç常ç¨ä¿¡æ¯:
- 设置 GPIO æ¹åçæ¹æ³
- ç¨äºè®¿é® GPIO å¼çæ¹æ³
- åç¥è°ç¨å ¶æ¹æ³æ¯å¦å¯è½ä¼ç çæ å¿
- å¯éç debugfs ä¿¡æ¯å¯¼åºæ¹æ³ (æ¾ç¤ºç±»ä¼¼ä¸æé ç½®ä¸æ ·çé¢å¤ç¶æ)
- è¯ææ ç¾
ä¹å
å«äºæ¥èª device.platform_data çæ¯ä¸ªå®ä¾çæ°æ®ï¼å®ç¬¬ä¸ä¸ª GPIO ç
ç¼å·åå®å¯ç¨ç GPIO çæ°éã
å®ç° gpio_chip ç代ç åºæ¯æå¤æ§å¶å¨å®ä¾ï¼è¿å¯è½ä½¿ç¨é©±å¨æ¨¡åãé£äºä»£ç è¦
é
ç½®æ¯ä¸ª gpio_chipï¼å¹¶åèµ·gpiochip_add()ãå¸è½½ä¸ä¸ª GPIO æ§å¶å¨å¾å°è§ï¼
ä½å¨å¿
è¦çæ¶åå¯ä»¥ä½¿ç¨ gpiochip_remove()ã
大é¨å gpio_chip æ¯ä¸ä¸ªå®ä¾ç¹å®ç»æä½çä¸é¨åï¼è并ä¸å° GPIO æ¥å£åç¬
æ´é²åºæ¥,æ¯å¦ç¼åãçµæºç®¡ççã类似ç¼è§£ç å¨è¿æ ·çè¯çä¼æå¤æçé GPIO
ç¶æã
ä»»ä½ä¸ä¸ª debugfs ä¿¡æ¯å¯¼åºæ¹æ³é常åºè¯¥å¿½ç¥è¿æªç³è¯·ä½ä¸º GPIO çä¿¡å·çº¿ã
ä»ä»¬å¯ä»¥ä½¿ç¨ gpiochip_is_requested()æµè¯ï¼å½è¿ä¸ª GPIO å·²ç»ç³è¯·è¿äº
å°±è¿åç¸å
³çæ ç¾ï¼å¦åè¿å NULLã
å¹³å°æ¯æ
为äºæ¯æè¿ä¸ªæ¡æ¶ï¼ä¸ä¸ªå¹³å°ç Kconfig æ件å°ä¼ “select”(éæ©)
ARCH_REQUIRE_GPIOLIB æ ARCH_WANT_OPTIONAL_GPIOLIBï¼å¹¶è®©å®ç
<asm/gpio.h> å
å« <asm-generic/gpio.h>ï¼åæ¶å®ä¹ä¸ä¸ªæ¹æ³:
gpio_get_value()ãgpio_set_value()å gpio_cansleep()ã
å®ä¹åºæä¾ä¸ä¸ª ARCH_NR_GPIOS çå®ä¹å¼ï¼è¿æ ·å¯ä»¥æ´å¥½å°åæ è¯¥å¹³å° GPIO
çå®é
æ°é,èçéæ表ç空é´ã(è¿ä¸ªå®ä¹å¼åºè¯¥å
å«çä¸ç³»ç»å
建 GPIO å
GPIO æ©å±å¨ä¸çæ°æ®ã)
ARCH_REQUIRE_GPIOLIB æå³ç gpiolib æ ¸å¿å¨è¿ä¸ªææ¶ä¸å°æ»æ¯ç¼è¯è¿å æ ¸ã
ARCH_WANT_OPTIONAL_GPIOLIB æå³ç gpiolib æ ¸å¿é»è®¤å
³é,ä¸ç¨æ·å¯ä»¥
使è½å®,并å°å
¶ç¼è¯è¿å
æ ¸(å¯é)ã
å¦æè¿äºé项é½æ²¡è¢«éæ©,该平å°å°±ä¸éè¿ GPIO-lib æ¯æ GPIO,ä¸ä»£ç ä¸å¯ä»¥
被ç¨æ·ä½¿è½ã
以ä¸è¿äºæ¹æ³çå®ç°å¯ä»¥ç´æ¥ä½¿ç¨æ¡æ¶ä»£ç ,并æ»æ¯éè¿ gpio_chip è°åº¦:
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
è¿äºå®ä¹å¯ä»¥ç¨æ´çæ³çå®ç°æ¹æ³æ¿ä»£ï¼é£å°±æ¯ä½¿ç¨ç»è¿é»è¾ä¼åçå
èå½æ°æ¥è®¿é®
åºäºç¹å®çä¸ç³»ç»ç GPIOãä¾å¦,è¥å¼ç¨ç GPIO (å¯åå¨ä½å移)æ¯å¸¸éâ12âï¼
读åæ设置å®å¯è½åªéå°å两æä¸ä¸ªæ令ï¼ä¸ä¸ä¼ä¼ç ãå½è¿æ ·çä¼åæ æ³å®ç°æ¶ï¼
é£äºå½æ°å¿
须使ç¨æ¡æ¶æä¾ç代ç ï¼é£å°±è³å°è¦å åæ¡æ令æå¯ä»¥å®ç°ã对äºç¨ GPIO
模æç I/O æ¥å£, å¦æ¤ç²¾ç®æ令æ¯å¾ææä¹çã
对äºçä¸ç³»ç»ï¼å¹³å°ç¹å®ä»£ç 为çä¸ GPIO æ¯ä¸ªåº(bank)å®ä¹å¹¶æ³¨å gpio_chip
å®ä¾ãé£äº GPIO åºè¯¥æ ¹æ®è¯çååçææ¡£è¿è¡ç¼ç /æ ç¾,并ç´æ¥åçµè·¯æ¿åçå¾
对åºãä»ä»¬åºè¯¥å¼å§äºé¶å¹¶ç»æ¢äºå¹³å°ç¹å®çéå¶ãè¿äº GPIO(代ç )é常ä»
arch_initcall()æè
æ´æ©çå°æ¹éæè¿å¹³å°åå§å代ç ï¼ä½¿è¿äº GPIO æ»æ¯å¯ç¨ï¼
ä¸ä»ä»¬é常å¯ä»¥ä½ä¸º IRQ 使ç¨ã
æ¿çº§æ¯æ
对äºå¤é¨ GPIO æ§å¶å¨(ä¾å¦ I2C æ SPI æ©å±å¨ãä¸ç¨è¯çãå¤åè½å¨ä»¶ãFPGA
æ CPLD)ï¼å¤§å¤æ°å¸¸ç¨æ¿çº§ç¹å®ä»£ç é½å¯ä»¥æ³¨åæ§å¶å¨è®¾å¤ï¼å¹¶ä¿è¯ä»ä»¬ç驱å¨ç¥é
gpiochip_add()æ使ç¨ç GPIO ç¼å·ãä»ä»¬çèµ·å§ç¼å·é常è·å¨å¹³å°ç¹å®ç GPIO
ç¼å·ä¹åã
ä¾å¦æ¿çº§å¯å¨ä»£ç åºè¯¥å建ç»æä½ææè¯çå
¬å¼ç GPIO èå´ï¼å¹¶ä½¿ç¨ platform_data
å°å
¶ä¼ éç»æ¯ä¸ª GPIO æ©å±å¨è¯çãç¶åè¯ç驱å¨ä¸ç probe()ä¾ç¨å¯ä»¥å°è¿ä¸ª
æ°æ®ä¼ éç» gpiochip_add()ã
åå§å顺åºå¾éè¦ãä¾å¦ï¼å¦æä¸ä¸ªè®¾å¤ä¾èµåºäº I2C ç(æ©å±)GPIOï¼é£ä¹å®ç
probe()ä¾ç¨å°±åºè¯¥å¨é£ä¸ª GPIO ææ以åæå¯ä»¥è¢«è°ç¨ãè¿æå³ç设å¤åºè¯¥å¨
GPIO å¯ä»¥å·¥ä½ä¹åæå¯è¢«æ³¨åã解å³è¿ç±»ä¾èµççä¸ç§æ¹æ³æ¯è®©è¿ç§ gpio_chip
æ§å¶å¨åæ¿çº§ç¹å®ä»£ç æä¾ setup()å teardown()åè°å½æ°ãä¸æ¦ææå¿
é¡»ç
èµæºå¯ç¨ä¹åï¼è¿äºæ¿çº§ç¹å®çåè°å½æ°å°ä¼æ³¨å设å¤ï¼å¹¶å¯ä»¥å¨è¿äº GPIO æ§å¶å¨
设å¤åææ ææ¶ç§»é¤å®ä»¬ã
ç¨æ·ç©ºé´ç Sysfs æ¥å£(å¯é)
使ç¨âgpiolibâå®ç°æ¡æ¶çå¹³å°å¯ä»¥éæ©é
ç½®ä¸ä¸ª GPIO ç sysfs ç¨æ·æ¥å£ã
è¿ä¸åäº debugfs æ¥å£ï¼å 为å®æä¾çæ¯å¯¹ GPIOæ¹ååå¼çæ§å¶ï¼èä¸åªæ¾ç¤º
ä¸ä¸ªGPIO çç¶ææè¦ãæ¤å¤,å®å¯ä»¥åºç°å¨æ²¡æè°è¯æ¯æç产å级系ç»ä¸ã
ä¾å¦ï¼éè¿éå½çç³»ç»ç¡¬ä»¶ææ¡£ï¼ç¨æ·ç©ºé´å¯ä»¥ç¥é GIOP #23 æ§å¶ Flash
åå¨å¨çåä¿æ¤(ç¨äºä¿æ¤å
¶ä¸ Bootloader ååº)ã产åçç³»ç»å级å¯è½éè¦
临æ¶è§£é¤è¿ä¸ªä¿æ¤ï¼é¦å
导å
¥ä¸ä¸ª GPIOï¼æ¹åå
¶è¾åºç¶æï¼ç¶åå¨éæ°ä½¿è½åä¿æ¤
åå级代ç ãé常æ
åµä¸,GPIO #23 æ¯ä¸ä¼è¢«è§¦åçï¼å¹¶ä¸å
æ ¸ä¹ä¸éè¦ç¥éä»ã
æ ¹æ®éå½ç硬件ææ¡£ï¼æäºç³»ç»çç¨æ·ç©ºé´ GPIO å¯ä»¥ç¨äºç¡®å®ç³»ç»é
ç½®æ°æ®ï¼
è¿äºæ°æ®æ¯æ åå
æ ¸ä¸ç¥éçãå¨æäºä»»å¡ä¸ï¼ç®åçç¨æ·ç©ºé´ GPIO 驱å¨å¯è½æ¯
ç³»ç»çæ£éè¦çã
注æï¼æ åå
æ ¸é©±å¨ä¸å·²ç»åå¨éç¨çâLED åæé®âGPIO ä»»å¡ï¼åå«æ¯:
“leds-gpio” å “gpio_keys”ã请使ç¨è¿äºæ¥æ¿ä»£ç´æ¥è®¿é® GPIOï¼å 为éæå¨
å
æ ¸æ¡æ¶ä¸çè¿ç±»é©±å¨æ¯ä½ å¨ç¨æ·ç©ºé´ç代ç æ´å¥½ã
Sysfs ä¸çè·¯å¾
å¨/sys/class/gpio ä¸æ 3 ç±»å ¥å£:
ç¨äºå¨ç¨æ·ç©ºé´æ§å¶ GPIO çæ§å¶æ¥å£;
GPIOs æ¬èº«;以å
GPIO æ§å¶å¨ (“gpio_chip” å®ä¾)ã
é¤äºè¿äºæ åçæ件,è¿å å«âdeviceâ符å·é¾æ¥ã
æ§å¶æ¥å£æ¯åªåç:
/sys/class/gpio/
"export" ... ç¨æ·ç©ºé´å¯ä»¥éè¿åå
¶ç¼å·å°è¿ä¸ªæ件ï¼è¦æ±å
æ ¸å¯¼åº
ä¸ä¸ª GPIO çæ§å¶å°ç¨æ·ç©ºé´ã
ä¾å¦: å¦æå
æ ¸ä»£ç 没æç³è¯· GPIO #19,"echo 19 > export"
å°ä¼ä¸º GPIO #19 å建ä¸ä¸ª "gpio19" èç¹ã
"unexport" ... 导åºå°ç¨æ·ç©ºé´çéæä½ã
ä¾å¦: "echo 19 > unexport" å°ä¼ç§»é¤ä½¿ç¨"export"æ件导åºç
"gpio19" èç¹ã
GPIO ä¿¡å·çè·¯å¾ç±»ä¼¼ /sys/class/gpio/gpio42/ (å¯¹äº GPIO #42 æ¥è¯´)ï¼
并æå¦ä¸ç读/åå±æ§:
/sys/class/gpio/gpioN/
"direction" ... 读åå¾å° "in" æ "out"ãè¿ä¸ªå¼é常è¿è¡åå
¥ã
åå
¥"out" æ¶,å
¶å¼èçé»è®¤è¾åºä¸ºä½çµå¹³ã为äºç¡®ä¿æ æ
éè¿è¡ï¼
"low" æ "high" ççµå¹³å¼åºè¯¥åå
¥ GPIO çé
ç½®ï¼ä½ä¸ºåå§è¾åºå¼ã
注æ:å¦æå
æ ¸ä¸æ¯ææ¹å GPIO çæ¹åï¼æè
å¨å¯¼åºæ¶å
æ ¸ä»£ç 没æ
æç¡®å
许ç¨æ·ç©ºé´å¯ä»¥éæ°é
ç½® GPIO æ¹åï¼é£ä¹è¿ä¸ªå±æ§å°ä¸åå¨ã
"value" ... 读åå¾å° 0 (ä½çµå¹³) æ 1 (é«çµå¹³)ãå¦æ GPIO é
置为
è¾åº,è¿ä¸ªå¼å
许åæä½ãä»»ä½éé¶å¼é½ä»¥é«çµå¹³çå¾
ã
å¦æå¼èå¯ä»¥é
置为ä¸æä¿¡å·ï¼ä¸å¦æå·²ç»é
ç½®äºäº§çä¸æç模å¼
ï¼è§"edge"çæè¿°ï¼ï¼ä½ å¯ä»¥å¯¹è¿ä¸ªæ件使ç¨è½®è¯¢æä½(poll(2))ï¼
ä¸è½®è¯¢æä½ä¼å¨ä»»ä½ä¸æ触åæ¶è¿åãå¦æä½ ä½¿ç¨è½®è¯¢æä½(poll(2))ï¼
è¯·å¨ events ä¸è®¾ç½® POLLPRI å POLLERRãå¦æä½ ä½¿ç¨è½®è¯¢æä½
(select(2))ï¼è¯·å¨ exceptfds è®¾ç½®ä½ ææçæ件æ述符ãå¨
轮询æä½(poll(2))è¿åä¹åï¼æ¢å¯ä»¥éè¿ lseek(2)æä½è¯»å
sysfs æ件çå¼å§é¨åï¼ä¹å¯ä»¥å
³éè¿ä¸ªæ件并éæ°æå¼å®æ¥è¯»åæ°æ®ã
"edge" ... 读åå¾å°ânoneâãârisingâãâfallingâæè
âbothâã
å°è¿äºå符串åå
¥è¿ä¸ªæ件å¯ä»¥éæ©æ²¿è§¦å模å¼ï¼ä¼ä½¿å¾è½®è¯¢æä½
(select(2))å¨"value"æ件ä¸è¿åã
è¿ä¸ªæ件ä»
æå¨è¿ä¸ªå¼èå¯ä»¥é
置为å¯äº§çä¸æè¾å
¥å¼èæ¶ï¼æåå¨ã
"active_low" ... 读åå¾å° 0 (å) æ 1 (ç)ãåå
¥ä»»ä½éé¶å¼å¯ä»¥
翻转è¿ä¸ªå±æ§ç(读å)å¼ãå·²åå¨æä¹åéè¿"edge"å±æ§è®¾ç½®äº"rising"
å "falling" 沿触å模å¼ç轮询æä½(poll(2))å°ä¼éµå¾ªè¿ä¸ªè®¾ç½®ã
GPIO æ§å¶å¨çè·¯å¾ç±»ä¼¼ /sys/class/gpio/gpiochip42/ (对äºä»#42 GPIO
å¼å§å®ç°æ§å¶çæ§å¶å¨),并æç以ä¸åªè¯»å±æ§:
/sys/class/gpio/gpiochipN/
"base" ... ä¸ä»¥ä¸ç N ç¸å,代表æ¤è¯ç管çç第ä¸ä¸ª GPIO çç¼å·
"label" ... ç¨äºè¯æ (并ä¸æ»æ¯åªæå¯ä¸å¼)
"ngpio" ... æ¤æ§å¶å¨æ管çç GPIO æ°é(è GPIO ç¼å·ä» N å°
N + ngpio - 1)
大å¤æ°æ
åµä¸,çµè·¯æ¿çææ¡£åºå½æ ææ¯ä¸ª GPIO ç使ç¨ç®çãä½æ¯é£äºç¼å·å¹¶ä¸æ»æ¯
åºå®ç,ä¾å¦å¨æ©å±å¡ä¸ç GPIOä¼æ ¹æ®æ使ç¨ç主æ¿ææå¨å å æ¶æä¸å
¶ä»çæ¿åè
ææä¸åãå¨è¿ç§æ
åµä¸,ä½ å¯è½éè¦ä½¿ç¨ gpiochip èç¹(å°½å¯è½å°ç»åçµè·¯å¾)æ¥
ç¡®å®ç»å®ä¿¡å·æç¨ç GPIO ç¼å·ã
ä»å æ ¸ä»£ç ä¸å¯¼åº
å æ ¸ä»£ç å¯ä»¥æç¡®å°ç®¡çé£äºå·²éè¿ gpio_request()ç³è¯·ç GPIO ç导åº:
/* å¯¼åº GPIO å°ç¨æ·ç©ºé´ */
int gpio_export(unsigned gpio, bool direction_may_change);
/* gpio_export()çéæä½ */
void gpio_unexport();
/* å建ä¸ä¸ª sysfs è¿æ¥å°å·²å¯¼åºç GPIO èç¹ */
int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
/* æ¹å sysfs ä¸çä¸ä¸ª GPIO èç¹çææ§ */
int gpio_sysfs_set_active_low(unsigned gpio, int value);
å¨ä¸ä¸ªå
æ ¸é©±å¨ç³è¯·ä¸ä¸ª GPIO ä¹åï¼å®å¯ä»¥éè¿ gpio_export()使å
¶å¨ sysfs
æ¥å£ä¸å¯è§ã该驱å¨å¯ä»¥æ§å¶ä¿¡å·æ¹åæ¯å¦å¯ä¿®æ¹ãè¿æå©äºé²æ¢ç¨æ·ç©ºé´ä»£ç æ æé´
ç ´åéè¦çç³»ç»ç¶æã
è¿ä¸ªæç¡®ç导åºæå©äº(éè¿ä½¿æäºå®éªæ´å®¹ææ¥)è°è¯ï¼ä¹å¯ä»¥æä¾ä¸ä¸ªå§ç»åå¨çæ¥å£ï¼
ä¸ææ¡£é
åä½ä¸ºæ¿çº§æ¯æå
çä¸é¨åã
å¨ GPIO 被导åºä¹åï¼gpio_export_link()å
è®¸å¨ sysfs æ件系ç»çä»»ä½å°æ¹
å建ä¸ä¸ªå°è¿ä¸ª GPIO sysfs èç¹ç符å·é¾æ¥ãè¿æ ·é©±å¨å°±å¯ä»¥éè¿ä¸ä¸ªæè¿°æ§ç
ååï¼å¨ sysfs ä¸ä»ä»¬ææ¥æç设å¤ä¸æä¾ä¸ä¸ª(å°è¿ä¸ª GPIO sysfs èç¹ç)æ¥å£ã
驱å¨å¯ä»¥ä½¿ç¨ gpio_sysfs_set_active_low() æ¥å¨ç¨æ·ç©ºé´éèçµè·¯æ¿ä¹é´
GPIO 线çææ§å·®å¼ãè¿ä¸ªä»
对 sysfs æ¥å£èµ·ä½ç¨ãææ§çæ¹åå¯ä»¥å¨ gpio_export()
ååè¿è¡,ä¸ä¹å使è½ç轮询æä½(poll(2))æ¯æ(ä¸åæä¸é沿)å°ä¼è¢«éæ°é
ç½®æ¥éµå¾ª
è¿ä¸ªè®¾ç½®ã