部分驅動程式會依賴靜態 GPIO 接腳或接腳多工器設定,這些設定會因主機板而異。在這些情況下,通常建議將 GPIO 設定詳細資料保留在主機板驅動程式庫中,確保依附元件驅動程式仍可攜。方法是讓主機板驅動程式庫將中繼資料和初始化步驟清單傳遞給 GPIO 驅動程式庫。請參閱下方的範例。
在主機板驅動程式庫中設定 GPIO 中繼資料
假設 SDMMC 驅動程式需要使用特定替代函式和驅動強度設定接腳。為此,主機板驅動程式庫會建立 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 驅動程式庫已正確設定這些接腳,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 驅動程式沒有或無法剖析初始化中繼資料,就不會新增任何初始化裝置。
建議用途
建議在以下兩種情況使用 GPIO 初始化步驟:
- 驅動程式需要靜態板或平台專屬的 GPIO 設定。
上拉/下拉、替代函式和驅動強度設定通常是板或平台專屬,因此建議在板驅動程式庫中使用 GPIO init 進行設定。如果所有開發板上的 GPIO 輸出值不同 (或不需要相同),也建議採用這種方式設定。
- 多個驅動程式依賴單一 GPIO 的靜態設定。
如果多個驅動程式依賴一個 GPIO 的靜態設定,則該設定應由 GPIO init 執行。這樣一來,多個驅動程式就不必對單一 GPIO 進行可能發生衝突的呼叫。
如果驅動程式庫會在執行階段變更設定,請勿使用 GPIO 初始化步驟。
GPIO 初始化選項
如需完整的初始化選項清單和說明,請參閱 fuchsia.hardware.pinimpl FIDL 規格。