GPIO 初始化

部分驅動程式需要使用主機專用的靜態 GPIO PIN 碼或圖釘 Mux 設定。在這類情況下,您通常建議將 GPIO 設定詳細資料保留在棋盤驅動程式庫中,確保相依驅動程式保持可攜性。如要這麼做,可以讓主面板驅動程式庫將中繼資料和初始化步驟清單傳送給 GPIO 驅動程式。請見以下範例。

在主面板驅動程式庫中設定 GPIO 中繼資料

舉例來說,SDMMC 驅動程式需要將 PIN 碼設為特定替代函式和驅動力。為此,主面板驅動程式庫會建立 fuchsia.hardware.gpioimpl.InitStep 物件清單,指定要發出的 GPIO 通訊協定呼叫,以及用來發出這類呼叫的 GPIO 索引:

#include <fidl/fuchsia.hardware.gpioimpl/cpp/wire.h>

// Helper lambda to simplify the following code.
auto sdmmc_gpio = [&](uint64_t alt_function, uint64_t drive_strength_ua) {
  return fuchsia_hardware_gpioimpl::wire::InitOptions::Builder(arena)
      .alt_function(alt_function)
      .drive_strength_ua(drive_strength_ua)
      .Build();
};

const fuchsia_hardware_gpioimpl::wire::InitStep init_steps[] = {
    {SDMMC_GPIO_0, sdmmc_gpio(SDMMC_GPIO_0_ALT_FUNCTION, 4000)},
    {SDMMC_GPIO_1, sdmmc_gpio(SDMMC_GPIO_1_ALT_FUNCTION, 4000)},
    {SDMMC_GPIO_2, sdmmc_gpio(SDMMC_GPIO_2_ALT_FUNCTION, 4000)},
    {SDMMC_GPIO_3, sdmmc_gpio(SDMMC_GPIO_3_ALT_FUNCTION, 4000)},
    {SDMMC_GPIO_4, sdmmc_gpio(SDMMC_GPIO_4_ALT_FUNCTION, 4000)},
    {SDMMC_GPIO_5, sdmmc_gpio(SDMMC_GPIO_5_ALT_FUNCTION, 4000)},
};

系統會將這份清單做為中繼資料提供給 GPIO 驅動程式庫:


fuchsia_hardware_gpioimpl::wire::InitMetadata metadata;
metadata.steps = fidl::VectorView<fuchsia_hardware_gpioimpl::wire::InitStep>::FromExternal(
    init_steps, std::size(init_steps));

fit::result encoded = fidl::Persist(metadata);
if (!encoded.is_ok()) {
  return encoded.error_value().status();
}

const std::vector<fpbus::Metadata> gpio_metadata{
    {{
        .type = DEVICE_METADATA_GPIO_INIT_STEPS,
        .data = std::move(encoded.value()),
    }},
    // Other metadata goes here.
};

const fpbus::Node gpio_dev = []() {
  fpbus::Node dev = {};
  dev.name() = "gpio";
  dev.vid() = PDEV_VID_SOME_VENDOR;
  dev.pid() = PDEV_PID_SOME_PRODUCT;
  dev.did() = PDEV_DID_SOME_GPIO_DEVICE;
  dev.mmio() = gpio_mmios;
  dev.irq() = gpio_irqs;
  dev.metadata() = gpio_metadata;
  return dev;
}();

// Add the node here.

使用繫結規則在 GPIO 設定上建立依附元件

現在 GPIO 驅動程式庫已正確設定這些 PIN 碼,因此 SDMMC 驅動程式庫必須在繫結前依附這項設定。方法是在主機板驅動程式庫繫結檔案中的 SDMMC 裝置新增額外片段:

using fuchsia.gpio;

// Other nodes go here.

node "gpio-init" {
  fuchsia.BIND_INIT_STEP == fuchsia.gpio.BIND_INIT_STEP.GPIO;
  fuchsia.BIND_GPIO_CONTROLLER = 1;
}

完成初始化步驟後,GPIO 驅動程式庫程式會新增 fuchsia.gpio.BIND_INIT_STEP.GPIO 裝置。任意數量的子項可繫結至此裝置,以便在啟動前確保其 GPIO 已設定完成。

GPIO 驅動程式庫如何處理設定錯誤

當 GPIO 驅動程式庫在處理初始化步驟時遇到錯誤時,會繼續設定其餘 GPIO,但不會新增 init 裝置。這是為了確保盡可能讓更多的針腳進入已知狀態,而且驅動程式不會嘗試以可能設定錯誤的圖釘執行。同樣地,如果 GPIO 驅動程式庫沒有或無法剖析初始化中繼資料,就不會新增 init 裝置。

有兩種情況建議使用 GPIO init 步驟:

  • 驅動程式需要靜態主機板或平台專屬的 GPIO 設定。

上拉/下拉、Alt 函式和驅動力量設定通常因董事會或平台而異,因此建議您使用 GPIO init 在板機驅動程式庫中設定。如果所有主面板上的值不相同 (或不需要),也建議以這種方式設定 GPIO 輸出值。

  • 多個驅動程式都需依賴一個 GPIO 的靜態設定。

如果有多個驅動程式需要使用一個 GPIO 的靜態設定,則該設定應由 GPIO init 執行。這樣可防止多個驅動程式向單一 GPIO 發出可能相互衝突的呼叫。

GPIO 初始化步驟不應用於驅動程式庫會在執行階段變更的任何設定。

GPIO 初始化選項

如需初始化選項的完整清單及其說明,請參閱 fuchsia.hardware.gpioimpl FIDL 規格。