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> Traditional Chinese maintainer: Hu Haowen <src.res.211@gmail.com> --------------------------------------------------------------------- Documentation/admin-guide/gpio çš„ç¹é«”ä¸æ–‡ç¿»è¯ 如果想評論或更新本文的內容,請直接è¯ç¹«åŽŸæ–‡æª”çš„ç¶è·è€…ã€‚å¦‚æžœä½ ä½¿ç”¨è‹±æ–‡ 交æµæœ‰å›°é›£çš„話,也å¯ä»¥å‘ç¹é«”ä¸æ–‡ç‰ˆç¶è·è€…求助。如果本翻è¯æ›´æ–°ä¸åŠæ™‚或 者翻è¯å˜åœ¨å•é¡Œï¼Œè«‹è¯ç¹«ç¹é«”ä¸æ–‡ç‰ˆç¶è·è€…。 英文版ç¶è·è€…: Grant Likely <grant.likely@secretlab.ca> Linus Walleij <linus.walleij@linaro.org> ç¹é«”ä¸æ–‡ç‰ˆç¶è·è€…: 胡皓文 Hu Haowen <src.res.211@gmail.com> ç¹é«”ä¸æ–‡ç‰ˆç¿»è¯è€…: 胡皓文 Hu Haowen <src.res.211@gmail.com> ç¹é«”ä¸æ–‡ç‰ˆæ ¡è¯è€…: 胡皓文 Hu Haowen <src.res.211@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,使用以下的函數訪å•: /* 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 輸入:返回零或éžé›¶ ,å¯èƒ½æœƒä¼‘çœ */ 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 ---------------------------- 爲了有助於æ•ç²ç³»çµ±é…置錯誤,定義了兩個函數。 /* 申請 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_INIT_* 僅有在é…置爲輸出的時候æ‰å˜åœ¨,所以有效的組åˆçˆ²: * GPIOF_IN - é…置爲輸入 * GPIOF_OUT_INIT_LOW - é…置爲輸出,並åˆå§‹åŒ–爲低電平 * GPIOF_OUT_INIT_HIGH - é…置爲輸出,並åˆå§‹åŒ–爲高電平 更進一æ¥,爲了更簡單地è²æ˜Ž/釋放多個 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); 它們的返回值爲å°æ‡‰å‘½åç©ºé–“çš„ç›¸é—œç·¨è™Ÿï¼Œæˆ–æ˜¯è² çš„éŒ¯èª¤ä»£ç¢¼(å¦‚æžœç„¡æ³•æ˜ å°„)。 (例如,æŸäº› GPIO 無法åšçˆ² IRQ 使用。)以下的編號錯誤是未經檢測的:使用一個 æœªé€šéŽ gpio_direction_input()é…置爲輸入的 GPIO 編號,或者使用一個 並éžä¾†æºæ–¼gpio_to_irq()çš„ IRQ 編號。 é€™å…©å€‹æ˜ å°„å‡½æ•¸å¯èƒ½æœƒåœ¨ä¿¡è™Ÿç·¨è™Ÿçš„åŠ æ¸›è¨ˆç®—éŽç¨‹ä¸ŠèŠ±äº›æ™‚間。它們ä¸å¯ä¼‘çœ ã€‚ gpio_to_irq()返回的éžéŒ¯èª¤å€¼å¯ä»¥å‚³éžçµ¦ request_irq()或者 free_irq()。 它們通常通éŽæ¿ç´šç‰¹å®šçš„åˆå§‹åŒ–代碼å˜æ”¾åˆ°å¹³å°è¨å‚™çš„ IRQ 資æºä¸ã€‚注æ„:IRQ 觸發é¸é …是 IRQ 接å£çš„一部分,如 IRQF_TRIGGER_FALLING,系統喚醒能力 也是如æ¤ã€‚ 模擬開æ¼ä¿¡è™Ÿ ---------------------------- 有時在åªæœ‰ä½Žé›»å¹³ä¿¡è™Ÿä½œçˆ²å¯¦éš›é©…å‹•çµæžœ(è¯è€…注:多個輸出連接於一點,é‚輯電平 çµæžœçˆ²æ‰€æœ‰è¼¸å‡ºçš„é‚輯與)的時候,共享的信號線需è¦ä½¿ç”¨ã€Œé–‹æ¼ã€ä¿¡è™Ÿã€‚(該術語 é©ç”¨æ–¼ 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()。 它也應æ供一個 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 這些定義å¯ä»¥ç”¨æ›´ç†æƒ³çš„實ç¾æ–¹æ³•æ›¿ä»£ï¼Œé‚£å°±æ˜¯ä½¿ç”¨ç¶“éŽé‚輯優化的內è¯å‡½æ•¸ä¾†è¨ªå• 基於特定片上系統的 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 編號。