Chinese translated version of Documentation/admin-guide/gpio 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/admin-guide/gpio çä¸æç¿»è¯ å¦ææ³è¯è®ºææ´æ°æ¬æçå 容ï¼è¯·ç´æ¥èç³»åææ¡£çç»´æ¤è ãå¦æä½ ä½¿ç¨è±æ 交æµæå°é¾çè¯ï¼ä¹å¯ä»¥åä¸æçç»´æ¤è æ±å©ãå¦ææ¬ç¿»è¯æ´æ°ä¸åæ¶æè ç¿» è¯åå¨é®é¢ï¼è¯·èç³»ä¸æçç»´æ¤è ã è±æçç»´æ¤è ï¼ 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_gpio_request()ï¼ è gpiolib 驱å¨ç .free()æä½åºè°ç¨ pinctrl_gpio_free()ãpinctrl åç³»ç»å 许 pinctrl_gpio_request()å¨æ个å¼èæå¼èç»ä»¥å¤ç¨å½¢å¼âå±äºâ ä¸ä¸ªè®¾å¤æ¶é½æåè¿åã ä»»ä½é¡»å° 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) å¨ä¸ä¸ªå æ ¸é©±å¨ç³è¯·ä¸ä¸ª GPIO ä¹åï¼å®å¯ä»¥éè¿ gpio_export()ä½¿å ¶å¨ sysfs æ¥å£ä¸å¯è§ã该驱å¨å¯ä»¥æ§å¶ä¿¡å·æ¹åæ¯å¦å¯ä¿®æ¹ãè¿æå©äºé²æ¢ç¨æ·ç©ºé´ä»£ç æ æé´ ç ´åéè¦çç³»ç»ç¶æã è¿ä¸ªæç¡®ç导åºæå©äº(éè¿ä½¿æäºå®éªæ´å®¹ææ¥)è°è¯ï¼ä¹å¯ä»¥æä¾ä¸ä¸ªå§ç»åå¨çæ¥å£ï¼ ä¸ææ¡£é åä½ä¸ºæ¿çº§æ¯æå çä¸é¨åã å¨ GPIO 被导åºä¹åï¼gpio_export_link()å è®¸å¨ sysfs æ件系ç»çä»»ä½å°æ¹ å建ä¸ä¸ªå°è¿ä¸ª GPIO sysfs èç¹ç符å·é¾æ¥ãè¿æ ·é©±å¨å°±å¯ä»¥éè¿ä¸ä¸ªæè¿°æ§ç ååï¼å¨ sysfs ä¸ä»ä»¬ææ¥æç设å¤ä¸æä¾ä¸ä¸ª(å°è¿ä¸ª GPIO sysfs èç¹ç)æ¥å£ã