在嵌入式Linux開發(fā)中,設備樹(Device Tree)已成為硬件抽象的核心機制,其通過動態(tài)描述硬件資源,使內(nèi)核能夠靈活適配不同硬件平臺。本文聚焦GPIO與中斷資源的設備樹映射技術,結合實際案例解析其配置方法與優(yōu)化策略。
一、GPIO資源映射:從硬件到內(nèi)核的橋梁
1.1 GPIO控制器節(jié)點配置
GPIO控制器的設備樹節(jié)點需包含關鍵屬性:
dts
gpio0: gpio@10000000 {
compatible = "vendor,gpio-v1"; // 驅(qū)動匹配標識
reg = <0x10000000 0x1000>; // 寄存器基地址與長度
gpio-controller; // 聲明為GPIO控制器
#gpio-cells = <2>; // 每個GPIO需2個參數(shù):編號+配置
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; // 中斷配置
};
其中#gpio-cells定義了GPIO描述符的參數(shù)數(shù)量,典型值2表示第一個參數(shù)為GPIO編號,第二個參數(shù)為電氣特性(如GPIO_ACTIVE_LOW表示低電平有效)。
1.2 設備級GPIO綁定
設備節(jié)點通過gpios屬性引用GPIO控制器資源:
dts
led: led-controller {
compatible = "custom,led-driver";
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; // 使用gpio0的第12腳,低電平有效
};
驅(qū)動程序通過gpiod_get()獲取GPIO描述符:
c
struct gpio_desc *led_pin;
led_pin = gpiod_get(&pdev->dev, "led", GPIOD_OUT_LOW); // 配置為輸出,初始低電平
if (IS_ERR(led_pin)) {
dev_err(&pdev->dev, "Failed to get GPIO\n");
return PTR_ERR(led_pin);
}
二、中斷資源映射:多級中斷控制器協(xié)同
2.1 中斷控制器層級建模
現(xiàn)代SoC通常采用多級中斷控制器(如GICv3+GPIO控制器):
dts
gic: interrupt-controller@2f000000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>; // 每個中斷需3個參數(shù):中斷號/觸發(fā)方式/優(yōu)先級
interrupt-controller;
};
gpio0: gpio@10000000 {
compatible = "vendor,gpio-v1";
interrupt-parent = <&gic>; // 指定父中斷控制器
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; // SPI中斷33,高電平觸發(fā)
};
2.2 設備中斷綁定與處理
設備節(jié)點通過interrupts屬性聲明中斷需求:
dts
button: button-controller {
compatible = "custom,button-driver";
interrupt-parent = <&gpio0>; // 使用gpio0作為中斷控制器
interrupts = <3 IRQ_TYPE_EDGE_FALLING>; // GPIO3,下降沿觸發(fā)
};
驅(qū)動程序通過gpiod_to_irq()獲取Linux IRQ號:
c
int irq_num = gpiod_to_irq(button_pin); // 獲取中斷號
if (devm_request_irq(&pdev->dev, irq_num, button_isr,
IRQF_TRIGGER_FALLING, "button-irq", NULL) < 0) {
dev_err(&pdev->dev, "Failed to request IRQ\n");
return -EINVAL;
}
中斷處理函數(shù)需高效執(zhí)行,復雜任務可委托給工作隊列:
c
static irqreturn_t button_isr(int irq, void *dev_id) {
schedule_work(&button_work); // 調(diào)度工作隊列
return IRQ_HANDLED;
}
三、實戰(zhàn)案例:RK3568平臺觸摸屏驅(qū)動
在RK3568平臺中,觸摸屏通過GPIO中斷實現(xiàn)事件上報:
dts
ts: touchscreen@38 {
compatible = "edt,edt-ft5306";
reg = <0x38>;
touch-gpio = <&gpio0 RK_PB5 IRQ_TYPE_EDGE_RISING>; // PB5上升沿觸發(fā)
interrupt-parent = <&gpio0>;
interrupts = <RK_PB5 IRQ_TYPE_LEVEL_LOW>; // 低電平中斷(備用)
};
驅(qū)動程序關鍵代碼:
c
// 獲取GPIO與中斷號
struct gpio_desc *ts_gpio = gpiod_get(&pdev->dev, "touch", GPIOD_IN);
int irq_num = gpiod_to_irq(ts_gpio);
// 配置中斷觸發(fā)方式
if (devm_request_irq(&pdev->dev, irq_num, ts_isr,
IRQF_TRIGGER_RISING, "ts-irq", NULL) < 0) {
dev_err(&pdev->dev, "Failed to request IRQ\n");
return -EINVAL;
}
四、優(yōu)化與調(diào)試技巧
資源釋放:使用devm_系列函數(shù)(如devm_gpiod_get())自動管理資源,避免內(nèi)存泄漏。
并發(fā)控制:對共享GPIO資源使用spin_lock_irqsave()保護。
調(diào)試工具:
查看GPIO狀態(tài):cat /sys/kernel/debug/gpio
動態(tài)修改設備樹:通過dtoverlay機制在運行時加載覆蓋片段。
通過合理配置設備樹,開發(fā)者可實現(xiàn)GPIO與中斷資源的高效映射,顯著提升嵌入式Linux系統(tǒng)的硬件適配能力與穩(wěn)定性。掌握這些技術,是邁向高級嵌入式開發(fā)的關鍵一步。





