162306a36Sopenharmony_ciChinese translated version of Documentation/admin-guide/gpio 262306a36Sopenharmony_ci 362306a36Sopenharmony_ciIf you have any comment or update to the content, please contact the 462306a36Sopenharmony_cioriginal document maintainer directly. However, if you have a problem 562306a36Sopenharmony_cicommunicating in English you can also ask the Chinese maintainer for 662306a36Sopenharmony_cihelp. Contact the Chinese maintainer if this translation is outdated 762306a36Sopenharmony_cior if there is a problem with the translation. 862306a36Sopenharmony_ci 962306a36Sopenharmony_ciMaintainer: Grant Likely <grant.likely@secretlab.ca> 1062306a36Sopenharmony_ci Linus Walleij <linus.walleij@linaro.org> 1162306a36Sopenharmony_ciTraditional Chinese maintainer: Hu Haowen <src.res.211@gmail.com> 1262306a36Sopenharmony_ci--------------------------------------------------------------------- 1362306a36Sopenharmony_ciDocumentation/admin-guide/gpio 的繁體中文翻譯 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文 1662306a36Sopenharmony_ci交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或 1762306a36Sopenharmony_ci者翻譯存在問題,請聯繫繁體中文版維護者。 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci英文版維護者: Grant Likely <grant.likely@secretlab.ca> 2062306a36Sopenharmony_ci Linus Walleij <linus.walleij@linaro.org> 2162306a36Sopenharmony_ci繁體中文版維護者: 胡皓文 Hu Haowen <src.res.211@gmail.com> 2262306a36Sopenharmony_ci繁體中文版翻譯者: 胡皓文 Hu Haowen <src.res.211@gmail.com> 2362306a36Sopenharmony_ci繁體中文版校譯者: 胡皓文 Hu Haowen <src.res.211@gmail.com> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci以下爲正文 2662306a36Sopenharmony_ci--------------------------------------------------------------------- 2762306a36Sopenharmony_ciGPIO 接口 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci本文檔提供了一個在Linux下訪問GPIO的公約概述。 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci這些函數以 gpio_* 作爲前綴。其他的函數不允許使用這樣的前綴或相關的 3262306a36Sopenharmony_ci__gpio_* 前綴。 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci什麼是GPIO? 3662306a36Sopenharmony_ci========== 3762306a36Sopenharmony_ci"通用輸入/輸出口"(GPIO)是一個靈活的由軟體控制的數位訊號。他們可 3862306a36Sopenharmony_ci由多種晶片提供,且對於從事嵌入式和定製硬體的 Linux 開發者來說是 3962306a36Sopenharmony_ci比較熟悉。每個GPIO 都代表一個連接到特定引腳或球柵陣列(BGA)封裝中 4062306a36Sopenharmony_ci「球珠」的一個位。電路板原理圖顯示了 GPIO 與外部硬體的連接關係。 4162306a36Sopenharmony_ci驅動可以編寫成通用代碼,以使板級啓動代碼可傳遞引腳配置數據給驅動。 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci片上系統 (SOC) 處理器對 GPIO 有很大的依賴。在某些情況下,每個 4462306a36Sopenharmony_ci非專用引腳都可配置爲 GPIO,且大多數晶片都最少有一些 GPIO。 4562306a36Sopenharmony_ci可編程邏輯器件(類似 FPGA) 可以方便地提供 GPIO。像電源管理和 4662306a36Sopenharmony_ci音頻編解碼器這樣的多功能晶片經常留有一些這樣的引腳來幫助那些引腳 4762306a36Sopenharmony_ci匱乏的 SOC。同時還有通過 I2C 或 SPI 串行總線連接的「GPIO擴展器」 4862306a36Sopenharmony_ci晶片。大多數 PC 的南橋有一些擁有 GPIO 能力的引腳 (只有BIOS 4962306a36Sopenharmony_ci固件才知道如何使用他們)。 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciGPIO 的實際功能因系統而異。通常用法有: 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci - 輸出值可寫 (高電平=1,低電平=0)。一些晶片也有如何驅動這些值的選項, 5462306a36Sopenharmony_ci 例如只允許輸出一個值、支持「線與」及其他取值類似的模式(值得注意的是 5562306a36Sopenharmony_ci 「開漏」信號) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci - 輸入值可讀(1、0)。一些晶片支持引腳在配置爲「輸出」時回讀,這對於類似 5862306a36Sopenharmony_ci 「線與」的情況(以支持雙向信號)是非常有用的。GPIO 控制器可能有輸入 5962306a36Sopenharmony_ci 去毛刺/消抖邏輯,這有時需要軟體控制。 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci - 輸入通常可作爲 IRQ 信號,一般是沿觸發,但有時是電平觸發。這樣的 IRQ 6262306a36Sopenharmony_ci 可能配置爲系統喚醒事件,以將系統從低功耗狀態下喚醒。 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci - 通常一個 GPIO 根據不同產品電路板的需求,可以配置爲輸入或輸出,也有僅 6562306a36Sopenharmony_ci 支持單向的。 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci - 大部分 GPIO 可以在持有自旋鎖時訪問,但是通常由串行總線擴展的 GPIO 6862306a36Sopenharmony_ci 不允許持有自旋鎖。但某些系統也支持這種類型。 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci對於給定的電路板,每個 GPIO 都用於某個特定的目的,如監控 MMC/SD 卡的 7162306a36Sopenharmony_ci插入/移除、檢測卡的防寫狀態、驅動 LED、配置收發器、模擬串行總線、 7262306a36Sopenharmony_ci復位硬體看門狗、感知開關狀態等等。 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciGPIO 公約 7662306a36Sopenharmony_ci========= 7762306a36Sopenharmony_ci注意,這個叫做「公約」,因爲這不是強制性的,不遵循這個公約是無傷大雅的, 7862306a36Sopenharmony_ci因爲此時可移植性並不重要。GPIO 常用於板級特定的電路邏輯,甚至可能 7962306a36Sopenharmony_ci隨著電路板的版本而改變,且不可能在不同走線的電路板上使用。僅有在少數 8062306a36Sopenharmony_ci功能上才具有可移植性,其他功能是平台特定。這也是由於「膠合」的邏輯造成的。 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci此外,這不需要任何的執行框架,只是一個接口。某個平台可能通過一個簡單地 8362306a36Sopenharmony_ci訪問晶片寄存器的內聯函數來實現它,其他平台可能通過委託一系列不同的GPIO 8462306a36Sopenharmony_ci控制器的抽象函數來實現它。(有一些可選的代碼能支持這種策略的實現,本文檔 8562306a36Sopenharmony_ci後面會介紹,但作爲 GPIO 接口的客戶端驅動程序必須與它的實現無關。) 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci也就是說,如果在他們的平台上支持這個公約,驅動應儘可能的使用它。同時,平台 8862306a36Sopenharmony_ci必須在 Kconfig 中選擇 ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB 8962306a36Sopenharmony_ci選項。那些調用標準 GPIO 函數的驅動應該在 Kconfig 入口中聲明依賴GENERIC_GPIO。 9062306a36Sopenharmony_ci當驅動包含文件: 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci #include <linux/gpio.h> 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci則 GPIO 函數是可用,無論是「真實代碼」還是經優化過的語句。如果你遵守 9562306a36Sopenharmony_ci這個公約,當你的代碼完成後,對其他的開發者來說會更容易看懂和維護。 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci注意,這些操作包含所用平台的 I/O 屏障代碼,驅動無須顯式地調用他們。 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci標識 GPIO 10162306a36Sopenharmony_ci--------- 10262306a36Sopenharmony_ciGPIO 是通過無符號整型來標識的,範圍是 0 到 MAX_INT。保留「負」數 10362306a36Sopenharmony_ci用於其他目的,例如標識信號「在這個板子上不可用」或指示錯誤。未接觸底層 10462306a36Sopenharmony_ci硬體的代碼會忽略這些整數。 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci平台會定義這些整數的用法,且通常使用 #define 來定義 GPIO,這樣 10762306a36Sopenharmony_ci板級特定的啓動代碼可以直接關聯相應的原理圖。相對來說,驅動應該僅使用 10862306a36Sopenharmony_ci啓動代碼傳遞過來的 GPIO 編號,使用 platform_data 保存板級特定 10962306a36Sopenharmony_ci引腳配置數據 (同時還有其他須要的板級特定數據),避免可能出現的問題。 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci例如一個平台使用編號 32-159 來標識 GPIO,而在另一個平台使用編號0-63 11262306a36Sopenharmony_ci標識一組 GPIO 控制器,64-79標識另一類 GPIO 控制器,且在一個含有 11362306a36Sopenharmony_ciFPGA 的特定板子上使用 80-95。編號不一定要連續,那些平台中,也可以 11462306a36Sopenharmony_ci使用編號2000-2063來標識一個 I2C 接口的 GPIO 擴展器中的 GPIO。 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci如果你要初始化一個帶有無效 GPIO 編號的結構體,可以使用一些負編碼 11762306a36Sopenharmony_ci(如"-EINVAL"),那將使其永遠不會是有效。來測試這樣一個結構體中的編號 11862306a36Sopenharmony_ci是否關聯一個 GPIO,你可使用以下斷言: 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci int gpio_is_valid(int number); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci如果編號不存在,則請求和釋放 GPIO 的函數將拒絕執行相關操作(見下文)。 12362306a36Sopenharmony_ci其他編號也可能被拒絕,比如一個編號可能存在,但暫時在給定的電路上不可用。 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci一個平台是否支持多個 GPIO 控制器爲平台特定的實現問題,就像是否可以 12662306a36Sopenharmony_ci在 GPIO 編號空間中有「空洞」和是否可以在運行時添加新的控制器一樣。 12762306a36Sopenharmony_ci這些問題會影響其他事情,包括相鄰的 GPIO 編號是否存在等。 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci使用 GPIO 13062306a36Sopenharmony_ci--------- 13162306a36Sopenharmony_ci對於一個 GPIO,系統應該做的第一件事情就是通過 gpio_request() 13262306a36Sopenharmony_ci函數分配它,見下文。 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci接下來是設置I/O方向,這通常是在板級啓動代碼中爲所使用的 GPIO 設置 13562306a36Sopenharmony_ciplatform_device 時完成。 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* 設置爲輸入或輸出, 返回 0 或負的錯誤代碼 */ 13862306a36Sopenharmony_ci int gpio_direction_input(unsigned gpio); 13962306a36Sopenharmony_ci int gpio_direction_output(unsigned gpio, int value); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci返回值爲零代表成功,否則返回一個負的錯誤代碼。這個返回值需要檢查,因爲 14262306a36Sopenharmony_ciget/set(獲取/設置)函數調用沒法返回錯誤,且有可能是配置錯誤。通常, 14362306a36Sopenharmony_ci你應該在進程上下文中調用這些函數。然而,對於自旋鎖安全的 GPIO,在板子 14462306a36Sopenharmony_ci啓動的早期、進程啓動前使用他們也是可以的。 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci對於作爲輸出的 GPIO,爲其提供初始輸出值,對於避免在系統啓動期間出現 14762306a36Sopenharmony_ci信號毛刺是很有幫助的。 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci爲了與傳統的 GPIO 接口兼容, 在設置一個 GPIO 方向時,如果它還未被申請, 15062306a36Sopenharmony_ci則隱含了申請那個 GPIO 的操作(見下文)。這種兼容性正在從可選的 gpiolib 15162306a36Sopenharmony_ci框架中移除。 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci如果這個 GPIO 編碼不存在,或者特定的 GPIO 不能用於那種模式,則方向 15462306a36Sopenharmony_ci設置可能失敗。依賴啓動固件來正確地設置方向通常是一個壞主意,因爲它可能 15562306a36Sopenharmony_ci除了啓動Linux,並沒有做更多的驗證工作。(同理, 板子的啓動代碼可能需要 15662306a36Sopenharmony_ci將這個復用的引腳設置爲 GPIO,並正確地配置上拉/下拉電阻。) 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci訪問自旋鎖安全的 GPIO 16062306a36Sopenharmony_ci------------------- 16162306a36Sopenharmony_ci大多數 GPIO 控制器可以通過內存讀/寫指令來訪問。這些指令不會休眠,可以 16262306a36Sopenharmony_ci安全地在硬(非線程)中斷例程和類似的上下文中完成。 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci對於那些 GPIO,使用以下的函數訪問: 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci /* GPIO 輸入:返回零或非零 */ 16762306a36Sopenharmony_ci int gpio_get_value(unsigned gpio); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci /* GPIO 輸出 */ 17062306a36Sopenharmony_ci void gpio_set_value(unsigned gpio, int value); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciGPIO值是布爾值,零表示低電平,非零表示高電平。當讀取一個輸出引腳的值時, 17362306a36Sopenharmony_ci返回值應該是引腳上的值。這個值不總是和輸出值相符,因爲存在開漏輸出信號和 17462306a36Sopenharmony_ci輸出延遲問題。 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci以上的 get/set 函數無錯誤返回值,因爲之前 gpio_direction_*()應已檢查過 17762306a36Sopenharmony_ci其是否爲「無效GPIO」。此外,還需要注意的是並不是所有平台都可以從輸出引腳 17862306a36Sopenharmony_ci中讀取數據,對於不能讀取的引腳應總返回零。另外,對那些在原子上下文中無法 17962306a36Sopenharmony_ci安全訪問的 GPIO (譯者註:因爲訪問可能導致休眠)使用這些函數是不合適的 18062306a36Sopenharmony_ci(見下文)。 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci在 GPIO 編號(還有輸出、值)爲常數的情況下,鼓勵通過平台特定的實現來優化 18362306a36Sopenharmony_ci這兩個函數來訪問 GPIO 值。這種情況(讀寫一個硬體寄存器)下只需要幾條指令 18462306a36Sopenharmony_ci是很正常的,且無須自旋鎖。這種優化函數比起那些在子程序上花費許多指令的 18562306a36Sopenharmony_ci函數可以使得模擬接口(譯者注:例如 GPIO 模擬 I2C、1-wire 或 SPI)的 18662306a36Sopenharmony_ci應用(在空間和時間上都)更具效率。 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci訪問可能休眠的 GPIO 19062306a36Sopenharmony_ci----------------- 19162306a36Sopenharmony_ci某些 GPIO 控制器必須通過基於總線(如 I2C 或 SPI)的消息訪問。讀或寫這些 19262306a36Sopenharmony_ciGPIO 值的命令需要等待其信息排到隊首才發送命令,再獲得其反饋。期間需要 19362306a36Sopenharmony_ci休眠,這不能在 IRQ 例程(中斷上下文)中執行。 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci爲了訪問這種 GPIO,內核定義了一套不同的函數: 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* GPIO 輸入:返回零或非零 ,可能會休眠 */ 19862306a36Sopenharmony_ci int gpio_get_value_cansleep(unsigned gpio); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci /* GPIO 輸出,可能會休眠 */ 20162306a36Sopenharmony_ci void gpio_set_value_cansleep(unsigned gpio, int value); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci訪問這樣的 GPIO 需要一個允許休眠的上下文,例如線程 IRQ 處理例程,並用以上的 20462306a36Sopenharmony_ci訪問函數替換那些沒有 cansleep()後綴的自旋鎖安全訪問函數。 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci除了這些訪問函數可能休眠,且它們操作的 GPIO 不能在硬體 IRQ 處理例程中訪問的 20762306a36Sopenharmony_ci事實,這些處理例程實際上和自旋鎖安全的函數是一樣的。 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci** 除此之外 ** 調用設置和配置此類 GPIO 的函數也必須在允許休眠的上下文中, 21062306a36Sopenharmony_ci因爲它們可能也需要訪問 GPIO 控制器晶片: (這些設置函數通常在板級啓動代碼或者 21162306a36Sopenharmony_ci驅動探測/斷開代碼中,所以這是一個容易滿足的約束條件。) 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci gpio_direction_input() 21462306a36Sopenharmony_ci gpio_direction_output() 21562306a36Sopenharmony_ci gpio_request() 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci## gpio_request_one() 21862306a36Sopenharmony_ci## gpio_request_array() 21962306a36Sopenharmony_ci## gpio_free_array() 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci gpio_free() 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci聲明和釋放 GPIO 22662306a36Sopenharmony_ci---------------------------- 22762306a36Sopenharmony_ci爲了有助於捕獲系統配置錯誤,定義了兩個函數。 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* 申請 GPIO, 返回 0 或負的錯誤代碼. 23062306a36Sopenharmony_ci * 非空標籤可能有助於診斷. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_ci int gpio_request(unsigned gpio, const char *label); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* 釋放之前聲明的 GPIO */ 23562306a36Sopenharmony_ci void gpio_free(unsigned gpio); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci將無效的 GPIO 編碼傳遞給 gpio_request()會導致失敗,申請一個已使用這個 23862306a36Sopenharmony_ci函數聲明過的 GPIO 也會失敗。gpio_request()的返回值必須檢查。你應該在 23962306a36Sopenharmony_ci進程上下文中調用這些函數。然而,對於自旋鎖安全的 GPIO,在板子啓動的早期、 24062306a36Sopenharmony_ci進入進程之前是可以申請的。 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci這個函數完成兩個基本的目標。一是標識那些實際上已作爲 GPIO 使用的信號線, 24362306a36Sopenharmony_ci這樣便於更好地診斷;系統可能需要服務幾百個可用的 GPIO,但是對於任何一個 24462306a36Sopenharmony_ci給定的電路板通常只有一些被使用。另一個目的是捕獲衝突,查明錯誤:如兩個或 24562306a36Sopenharmony_ci更多驅動錯誤地認爲他們已經獨占了某個信號線,或是錯誤地認爲移除一個管理著 24662306a36Sopenharmony_ci某個已激活信號的驅動是安全的。也就是說,申請 GPIO 的作用類似一種鎖機制。 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci某些平台可能也使用 GPIO 作爲電源管理激活信號(例如通過關閉未使用晶片區和 24962306a36Sopenharmony_ci簡單地關閉未使用時鐘)。 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci對於 GPIO 使用 pinctrl 子系統已知的引腳,子系統應該被告知其使用情況; 25262306a36Sopenharmony_ci一個 gpiolib 驅動的 .request()操作應調用 pinctrl_gpio_request(), 25362306a36Sopenharmony_ci而 gpiolib 驅動的 .free()操作應調用 pinctrl_gpio_free()。pinctrl 25462306a36Sopenharmony_ci子系統允許 pinctrl_gpio_request()在某個引腳或引腳組以復用形式「屬於」 25562306a36Sopenharmony_ci一個設備時都成功返回。 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci任何須將 GPIO 信號導向適當引腳的引腳復用硬體的編程應該發生在 GPIO 25862306a36Sopenharmony_ci驅動的 .direction_input()或 .direction_output()函數中,以及 25962306a36Sopenharmony_ci任何輸出 GPIO 值的設置之後。這樣可使從引腳特殊功能到 GPIO 的轉換 26062306a36Sopenharmony_ci不會在引腳產生毛刺波形。有時當用一個 GPIO 實現其信號驅動一個非 GPIO 26162306a36Sopenharmony_ci硬體模塊的解決方案時,就需要這種機制。 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci某些平台允許部分或所有 GPIO 信號使用不同的引腳。類似的,GPIO 或引腳的 26462306a36Sopenharmony_ci其他方面也需要配置,如上拉/下拉。平台軟體應該在對這些 GPIO 調用 26562306a36Sopenharmony_cigpio_request()前將這類細節配置好,例如使用 pinctrl 子系統的映射表, 26662306a36Sopenharmony_ci使得 GPIO 的用戶無須關注這些細節。 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci還有一個值得注意的是在釋放 GPIO 前,你必須停止使用它。 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci注意:申請一個 GPIO 並沒有以任何方式配置它,只不過標識那個 GPIO 處於使用 27262306a36Sopenharmony_ci狀態。必須有另外的代碼來處理引腳配置(如控制 GPIO 使用的引腳、上拉/下拉)。 27362306a36Sopenharmony_ci考慮到大多數情況下聲明 GPIO 之後就會立即配置它們,所以定義了以下三個輔助函數: 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* 申請一個 GPIO 信號, 同時通過特定的'flags'初始化配置, 27662306a36Sopenharmony_ci * 其他和 gpio_request()的參數和返回值相同 27762306a36Sopenharmony_ci * 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* 在單個函數中申請多個 GPIO 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_ci int gpio_request_array(struct gpio *array, size_t num); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* 在單個函數中釋放多個 GPIO 28662306a36Sopenharmony_ci */ 28762306a36Sopenharmony_ci void gpio_free_array(struct gpio *array, size_t num); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci這裡 'flags' 當前定義可指定以下屬性: 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci * GPIOF_DIR_IN - 配置方向爲輸入 29262306a36Sopenharmony_ci * GPIOF_DIR_OUT - 配置方向爲輸出 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci * GPIOF_INIT_LOW - 在作爲輸出時,初始值爲低電平 29562306a36Sopenharmony_ci * GPIOF_INIT_HIGH - 在作爲輸出時,初始值爲高電平 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci因爲 GPIOF_INIT_* 僅有在配置爲輸出的時候才存在,所以有效的組合爲: 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci * GPIOF_IN - 配置爲輸入 30062306a36Sopenharmony_ci * GPIOF_OUT_INIT_LOW - 配置爲輸出,並初始化爲低電平 30162306a36Sopenharmony_ci * GPIOF_OUT_INIT_HIGH - 配置爲輸出,並初始化爲高電平 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci更進一步,爲了更簡單地聲明/釋放多個 GPIO,'struct gpio'被引進來封裝所有 30462306a36Sopenharmony_ci這三個領域: 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci struct gpio { 30762306a36Sopenharmony_ci unsigned gpio; 30862306a36Sopenharmony_ci unsigned long flags; 30962306a36Sopenharmony_ci const char *label; 31062306a36Sopenharmony_ci }; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci一個典型的用例: 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci static struct gpio leds_gpios[] = { 31562306a36Sopenharmony_ci { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默認開啓 */ 31662306a36Sopenharmony_ci { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* 默認關閉 */ 31762306a36Sopenharmony_ci { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* 默認關閉 */ 31862306a36Sopenharmony_ci { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* 默認關閉 */ 31962306a36Sopenharmony_ci { ... }, 32062306a36Sopenharmony_ci }; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci err = gpio_request_one(31, GPIOF_IN, "Reset Button"); 32362306a36Sopenharmony_ci if (err) 32462306a36Sopenharmony_ci ... 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios)); 32762306a36Sopenharmony_ci if (err) 32862306a36Sopenharmony_ci ... 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios)); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ciGPIO 映射到 IRQ 33462306a36Sopenharmony_ci-------------------- 33562306a36Sopenharmony_ciGPIO 編號是無符號整數;IRQ 編號也是。這些構成了兩個邏輯上不同的命名空間 33662306a36Sopenharmony_ci(GPIO 0 不一定使用 IRQ 0)。你可以通過以下函數在它們之間實現映射: 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* 映射 GPIO 編號到 IRQ 編號 */ 33962306a36Sopenharmony_ci int gpio_to_irq(unsigned gpio); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci它們的返回值爲對應命名空間的相關編號,或是負的錯誤代碼(如果無法映射)。 34262306a36Sopenharmony_ci(例如,某些 GPIO 無法做爲 IRQ 使用。)以下的編號錯誤是未經檢測的:使用一個 34362306a36Sopenharmony_ci未通過 gpio_direction_input()配置爲輸入的 GPIO 編號,或者使用一個 34462306a36Sopenharmony_ci並非來源於gpio_to_irq()的 IRQ 編號。 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci這兩個映射函數可能會在信號編號的加減計算過程上花些時間。它們不可休眠。 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cigpio_to_irq()返回的非錯誤值可以傳遞給 request_irq()或者 free_irq()。 34962306a36Sopenharmony_ci它們通常通過板級特定的初始化代碼存放到平台設備的 IRQ 資源中。注意:IRQ 35062306a36Sopenharmony_ci觸發選項是 IRQ 接口的一部分,如 IRQF_TRIGGER_FALLING,系統喚醒能力 35162306a36Sopenharmony_ci也是如此。 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci模擬開漏信號 35562306a36Sopenharmony_ci---------------------------- 35662306a36Sopenharmony_ci有時在只有低電平信號作爲實際驅動結果(譯者注:多個輸出連接於一點,邏輯電平 35762306a36Sopenharmony_ci結果爲所有輸出的邏輯與)的時候,共享的信號線需要使用「開漏」信號。(該術語 35862306a36Sopenharmony_ci適用於 CMOS 管;而 TTL 用「集電極開路」。)一個上拉電阻使信號爲高電平。這 35962306a36Sopenharmony_ci有時被稱爲「線與」。實際上,從負邏輯(低電平爲真)的角度來看,這是一個「線或」。 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci一個開漏信號的常見例子是共享的低電平使能 IRQ 信號線。此外,有時雙向數據總線 36262306a36Sopenharmony_ci信號也使用漏極開路信號。 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci某些 GPIO 控制器直接支持開漏輸出,還有許多不支持。當你需要開漏信號,但 36562306a36Sopenharmony_ci硬體又不直接支持的時候,一個常用的方法是用任何即可作輸入也可作輸出的 GPIO 36662306a36Sopenharmony_ci引腳來模擬: 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci LOW: gpio_direction_output(gpio, 0) ... 這代碼驅動信號並覆蓋 36962306a36Sopenharmony_ci 上拉配置。 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci HIGH: gpio_direction_input(gpio) ... 這代碼關閉輸出,所以上拉電阻 37262306a36Sopenharmony_ci (或其他的一些器件)控制了信號。 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci如果你將信號線「驅動」爲高電平,但是 gpio_get_value(gpio)報告了一個 37562306a36Sopenharmony_ci低電平(在適當的上升時間後),你就可以知道是其他的一些組件將共享信號線拉低了。 37662306a36Sopenharmony_ci這不一定是錯誤的。一個常見的例子就是 I2C 時鐘的延長:一個需要較慢時鐘的 37762306a36Sopenharmony_ci從設備延遲 SCK 的上升沿,而 I2C 主設備相應地調整其信號傳輸速率。 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci這些公約忽略了什麼? 38162306a36Sopenharmony_ci================ 38262306a36Sopenharmony_ci這些公約忽略的最大一件事就是引腳復用,因爲這屬於高度晶片特定的屬性且 38362306a36Sopenharmony_ci沒有可移植性。某個平台可能不需要明確的復用信息;有的對於任意給定的引腳 38462306a36Sopenharmony_ci可能只有兩個功能選項;有的可能每個引腳有八個功能選項;有的可能可以將 38562306a36Sopenharmony_ci幾個引腳中的任何一個作爲給定的 GPIO。(是的,這些例子都來自於當前運行 38662306a36Sopenharmony_ciLinux 的系統。) 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci在某些系統中,與引腳復用相關的是配置和使能集成的上、下拉模式。並不是所有 38962306a36Sopenharmony_ci平台都支持這種模式,或者不會以相同的方式來支持這種模式;且任何給定的電路板 39062306a36Sopenharmony_ci可能使用外置的上拉(或下拉)電阻,這時晶片上的就不應該使用。(當一個電路需要 39162306a36Sopenharmony_ci5kOhm 的拉動電阻,晶片上的 100 kOhm 電阻就不能做到。)同樣的,驅動能力 39262306a36Sopenharmony_ci(2 mA vs 20 mA)和電壓(1.8V vs 3.3V)是平台特定問題,就像模型一樣在 39362306a36Sopenharmony_ci可配置引腳和 GPIO 之間(沒)有一一對應的關係。 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci還有其他一些系統特定的機制沒有在這裡指出,例如上述的輸入去毛刺和線與輸出 39662306a36Sopenharmony_ci選項。硬體可能支持批量讀或寫 GPIO,但是那一般是配置相關的:對於處於同一 39762306a36Sopenharmony_ci塊區(bank)的GPIO。(GPIO 通常以 16 或 32 個組成一個區塊,一個給定的 39862306a36Sopenharmony_ci片上系統一般有幾個這樣的區塊。)某些系統可以通過輸出 GPIO 觸發 IRQ, 39962306a36Sopenharmony_ci或者從並非以 GPIO 管理的引腳取值。這些機制的相關代碼沒有必要具有可移植性。 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci當前,動態定義 GPIO 並不是標準的,例如作爲配置一個帶有某些 GPIO 擴展器的 40262306a36Sopenharmony_ci附加電路板的副作用。 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ciGPIO 實現者的框架 (可選) 40562306a36Sopenharmony_ci===================== 40662306a36Sopenharmony_ci前面提到了,有一個可選的實現框架,讓平台使用相同的編程接口,更加簡單地支持 40762306a36Sopenharmony_ci不同種類的 GPIO 控制器。這個框架稱爲"gpiolib"。 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci作爲一個輔助調試功能,如果 debugfs 可用,就會有一個 /sys/kernel/debug/gpio 41062306a36Sopenharmony_ci文件。通過這個框架,它可以列出所有註冊的控制器,以及當前正在使用中的 GPIO 41162306a36Sopenharmony_ci的狀態。 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci控制器驅動: gpio_chip 41562306a36Sopenharmony_ci------------------- 41662306a36Sopenharmony_ci在框架中每個 GPIO 控制器都包裝爲一個 "struct gpio_chip",他包含了 41762306a36Sopenharmony_ci該類型的每個控制器的常用信息: 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci - 設置 GPIO 方向的方法 42062306a36Sopenharmony_ci - 用於訪問 GPIO 值的方法 42162306a36Sopenharmony_ci - 告知調用其方法是否可能休眠的標誌 42262306a36Sopenharmony_ci - 可選的 debugfs 信息導出方法 (顯示類似上拉配置一樣的額外狀態) 42362306a36Sopenharmony_ci - 診斷標籤 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci也包含了來自 device.platform_data 的每個實例的數據:它第一個 GPIO 的 42662306a36Sopenharmony_ci編號和它可用的 GPIO 的數量。 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci實現 gpio_chip 的代碼應支持多控制器實例,這可能使用驅動模型。那些代碼要 42962306a36Sopenharmony_ci配置每個 gpio_chip,並發起gpiochip_add()。卸載一個 GPIO 控制器很少見, 43062306a36Sopenharmony_ci但在必要的時候可以使用 gpiochip_remove()。 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci大部分 gpio_chip 是一個實例特定結構體的一部分,而並不將 GPIO 接口單獨 43362306a36Sopenharmony_ci暴露出來,比如編址、電源管理等。類似編解碼器這樣的晶片會有複雜的非 GPIO 43462306a36Sopenharmony_ci狀態。 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci任何一個 debugfs 信息導出方法通常應該忽略還未申請作爲 GPIO 的信號線。 43762306a36Sopenharmony_ci他們可以使用 gpiochip_is_requested()測試,當這個 GPIO 已經申請過了 43862306a36Sopenharmony_ci就返回相關的標籤,否則返回 NULL。 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci平台支持 44262306a36Sopenharmony_ci------- 44362306a36Sopenharmony_ci爲了支持這個框架,一個平台的 Kconfig 文件將會 "select"(選擇) 44462306a36Sopenharmony_ciARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,並讓它的 44562306a36Sopenharmony_ci<asm/gpio.h> 包含 <asm-generic/gpio.h>,同時定義二個方法: 44662306a36Sopenharmony_cigpio_get_value()、gpio_set_value()。 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci它也應提供一個 ARCH_NR_GPIOS 的定義值,這樣可以更好地反映該平台 GPIO 44962306a36Sopenharmony_ci的實際數量,節省靜態表的空間。(這個定義值應該包含片上系統內建 GPIO 和 45062306a36Sopenharmony_ciGPIO 擴展器中的數據。) 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ciARCH_REQUIRE_GPIOLIB 意味著 gpiolib 核心在這個構架中將總是編譯進內核。 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ciARCH_WANT_OPTIONAL_GPIOLIB 意味著 gpiolib 核心默認關閉,且用戶可以 45562306a36Sopenharmony_ci使能它,並將其編譯進內核(可選)。 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci如果這些選項都沒被選擇,該平台就不通過 GPIO-lib 支持 GPIO,且代碼不可以 45862306a36Sopenharmony_ci被用戶使能。 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci以下這些方法的實現可以直接使用框架代碼,並總是通過 gpio_chip 調度: 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci #define gpio_get_value __gpio_get_value 46362306a36Sopenharmony_ci #define gpio_set_value __gpio_set_value 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci這些定義可以用更理想的實現方法替代,那就是使用經過邏輯優化的內聯函數來訪問 46662306a36Sopenharmony_ci基於特定片上系統的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量「12」, 46762306a36Sopenharmony_ci讀取或設置它可能只需少則兩或三個指令,且不會休眠。當這樣的優化無法實現時, 46862306a36Sopenharmony_ci那些函數必須使用框架提供的代碼,那就至少要幾十條指令才可以實現。對於用 GPIO 46962306a36Sopenharmony_ci模擬的 I/O 接口, 如此精簡指令是很有意義的。 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci對於片上系統,平台特定代碼爲片上 GPIO 每個區(bank)定義並註冊 gpio_chip 47262306a36Sopenharmony_ci實例。那些 GPIO 應該根據晶片廠商的文檔進行編碼/標籤,並直接和電路板原理圖 47362306a36Sopenharmony_ci對應。他們應該開始於零並終止於平台特定的限制。這些 GPIO(代碼)通常從 47462306a36Sopenharmony_ciarch_initcall()或者更早的地方集成進平台初始化代碼,使這些 GPIO 總是可用, 47562306a36Sopenharmony_ci且他們通常可以作爲 IRQ 使用。 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci板級支持 47862306a36Sopenharmony_ci------- 47962306a36Sopenharmony_ci對於外部 GPIO 控制器(例如 I2C 或 SPI 擴展器、專用晶片、多功能器件、FPGA 48062306a36Sopenharmony_ci或 CPLD),大多數常用板級特定代碼都可以註冊控制器設備,並保證他們的驅動知道 48162306a36Sopenharmony_cigpiochip_add()所使用的 GPIO 編號。他們的起始編號通常跟在平台特定的 GPIO 48262306a36Sopenharmony_ci編號之後。 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci例如板級啓動代碼應該創建結構體指明晶片公開的 GPIO 範圍,並使用 platform_data 48562306a36Sopenharmony_ci將其傳遞給每個 GPIO 擴展器晶片。然後晶片驅動中的 probe()例程可以將這個 48662306a36Sopenharmony_ci數據傳遞給 gpiochip_add()。 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci初始化順序很重要。例如,如果一個設備依賴基於 I2C 的(擴展)GPIO,那麼它的 48962306a36Sopenharmony_ciprobe()例程就應該在那個 GPIO 有效以後才可以被調用。這意味著設備應該在 49062306a36Sopenharmony_ciGPIO 可以工作之後才可被註冊。解決這類依賴的的一種方法是讓這種 gpio_chip 49162306a36Sopenharmony_ci控制器向板級特定代碼提供 setup()和 teardown()回調函數。一旦所有必須的 49262306a36Sopenharmony_ci資源可用之後,這些板級特定的回調函數將會註冊設備,並可以在這些 GPIO 控制器 49362306a36Sopenharmony_ci設備變成無效時移除它們。 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci用戶空間的 Sysfs 接口(可選) 49762306a36Sopenharmony_ci======================== 49862306a36Sopenharmony_ci使用「gpiolib」實現框架的平台可以選擇配置一個 GPIO 的 sysfs 用戶接口。 49962306a36Sopenharmony_ci這不同於 debugfs 接口,因爲它提供的是對 GPIO方向和值的控制,而不只顯示 50062306a36Sopenharmony_ci一個GPIO 的狀態摘要。此外,它可以出現在沒有調試支持的產品級系統中。 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci例如,通過適當的系統硬體文檔,用戶空間可以知道 GIOP #23 控制 Flash 50362306a36Sopenharmony_ci存儲器的防寫(用於保護其中 Bootloader 分區)。產品的系統升級可能需要 50462306a36Sopenharmony_ci臨時解除這個保護:首先導入一個 GPIO,改變其輸出狀態,然後在重新使能防寫 50562306a36Sopenharmony_ci前升級代碼。通常情況下,GPIO #23 是不會被觸及的,並且內核也不需要知道他。 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci根據適當的硬體文檔,某些系統的用戶空間 GPIO 可以用於確定系統配置數據, 50862306a36Sopenharmony_ci這些數據是標準內核不知道的。在某些任務中,簡單的用戶空間 GPIO 驅動可能是 50962306a36Sopenharmony_ci系統真正需要的。 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci注意:標準內核驅動中已經存在通用的「LED 和按鍵」GPIO 任務,分別是: 51262306a36Sopenharmony_ci"leds-gpio" 和 "gpio_keys"。請使用這些來替代直接訪問 GPIO,因爲集成在 51362306a36Sopenharmony_ci內核框架中的這類驅動比你在用戶空間的代碼更好。 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ciSysfs 中的路徑 51762306a36Sopenharmony_ci-------------- 51862306a36Sopenharmony_ci在/sys/class/gpio 中有 3 類入口: 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci - 用於在用戶空間控制 GPIO 的控制接口; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci - GPIOs 本身;以及 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci - GPIO 控制器 ("gpio_chip" 實例)。 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci除了這些標準的文件,還包含「device」符號連結。 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci控制接口是只寫的: 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci /sys/class/gpio/ 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci "export" ... 用戶空間可以通過寫其編號到這個文件,要求內核導出 53362306a36Sopenharmony_ci 一個 GPIO 的控制到用戶空間。 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci 例如: 如果內核代碼沒有申請 GPIO #19,"echo 19 > export" 53662306a36Sopenharmony_ci 將會爲 GPIO #19 創建一個 "gpio19" 節點。 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci "unexport" ... 導出到用戶空間的逆操作。 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci 例如: "echo 19 > unexport" 將會移除使用"export"文件導出的 54162306a36Sopenharmony_ci "gpio19" 節點。 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ciGPIO 信號的路徑類似 /sys/class/gpio/gpio42/ (對於 GPIO #42 來說), 54462306a36Sopenharmony_ci並有如下的讀/寫屬性: 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci /sys/class/gpio/gpioN/ 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci "direction" ... 讀取得到 "in" 或 "out"。這個值通常運行寫入。 54962306a36Sopenharmony_ci 寫入"out" 時,其引腳的默認輸出爲低電平。爲了確保無故障運行, 55062306a36Sopenharmony_ci "low" 或 "high" 的電平值應該寫入 GPIO 的配置,作爲初始輸出值。 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci 注意:如果內核不支持改變 GPIO 的方向,或者在導出時內核代碼沒有 55362306a36Sopenharmony_ci 明確允許用戶空間可以重新配置 GPIO 方向,那麼這個屬性將不存在。 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci "value" ... 讀取得到 0 (低電平) 或 1 (高電平)。如果 GPIO 配置爲 55662306a36Sopenharmony_ci 輸出,這個值允許寫操作。任何非零值都以高電平看待。 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci 如果引腳可以配置爲中斷信號,且如果已經配置了產生中斷的模式 55962306a36Sopenharmony_ci (見"edge"的描述),你可以對這個文件使用輪詢操作(poll(2)), 56062306a36Sopenharmony_ci 且輪詢操作會在任何中斷觸發時返回。如果你使用輪詢操作(poll(2)), 56162306a36Sopenharmony_ci 請在 events 中設置 POLLPRI 和 POLLERR。如果你使用輪詢操作 56262306a36Sopenharmony_ci (select(2)),請在 exceptfds 設置你期望的文件描述符。在 56362306a36Sopenharmony_ci 輪詢操作(poll(2))返回之後,既可以通過 lseek(2)操作讀取 56462306a36Sopenharmony_ci sysfs 文件的開始部分,也可以關閉這個文件並重新打開它來讀取數據。 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci "edge" ... 讀取得到「none」、「rising」、「falling」或者「both」。 56762306a36Sopenharmony_ci 將這些字符串寫入這個文件可以選擇沿觸發模式,會使得輪詢操作 56862306a36Sopenharmony_ci (select(2))在"value"文件中返回。 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci 這個文件僅有在這個引腳可以配置爲可產生中斷輸入引腳時,才存在。 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci "active_low" ... 讀取得到 0 (假) 或 1 (真)。寫入任何非零值可以 57362306a36Sopenharmony_ci 翻轉這個屬性的(讀寫)值。已存在或之後通過"edge"屬性設置了"rising" 57462306a36Sopenharmony_ci 和 "falling" 沿觸發模式的輪詢操作(poll(2))將會遵循這個設置。 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ciGPIO 控制器的路徑類似 /sys/class/gpio/gpiochip42/ (對於從#42 GPIO 57762306a36Sopenharmony_ci開始實現控制的控制器),並有著以下只讀屬性: 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci /sys/class/gpio/gpiochipN/ 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci "base" ... 與以上的 N 相同,代表此晶片管理的第一個 GPIO 的編號 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci "label" ... 用於診斷 (並不總是只有唯一值) 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci "ngpio" ... 此控制器所管理的 GPIO 數量(而 GPIO 編號從 N 到 58662306a36Sopenharmony_ci N + ngpio - 1) 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci大多數情況下,電路板的文檔應當標明每個 GPIO 的使用目的。但是那些編號並不總是 58962306a36Sopenharmony_ci固定的,例如在擴展卡上的 GPIO會根據所使用的主板或所在堆疊架構中其他的板子而 59062306a36Sopenharmony_ci有所不同。在這種情況下,你可能需要使用 gpiochip 節點(儘可能地結合電路圖)來 59162306a36Sopenharmony_ci確定給定信號所用的 GPIO 編號。 592