如果我所做的每一件事都要對我的人生有用,那我的人生到底是什麼呢?
賺更多的錢?開更好的車?住更大的房子?
這些鬼東西就是我的人生麼?
一、回顧編寫驅動的三種方法
1、資源和驅動在同一個文件裏
2、資源用Platform_device指定,驅動在Platform_driver實現
3、資源用設備樹指定,驅動在Platform_driver實現
核心永遠是 file_operations 結構體。上述三種方法,只是指定“硬件資源”的方式不一樣。
從上圖可以知道, platform_device/platform_driver 只是編程的技巧,不涉及驅動的核心。
二、怎麼使用設備樹寫驅動程序
2.1 設備樹節點要與 platform_driver 能匹配
在我們的工作中,驅動要求設備樹節點提供什麼,我們就得按這要求去編寫設備樹。但是,匹配過程所要求的東西是固定的。
- ① 設備樹要有 compatible 屬性,它的值是一個字符串
- ② platform_driver 中要有 of_match_table,其中一項的.compatible 成員設置爲一個字符串
- ③ 上述 2 個字符串要一致。
比如:
2.2 設備樹節點指定資源, platform_driver 獲得資源
如果在設備樹節點裏使用 reg 屬性,那麼內核生成對應的 platform_device 時會用 reg屬性來設置 IORESOURCE_MEM 類型的資源。
如果在設備樹節點裏使用 interrupts 屬性,那麼內核生成對應的 platform_device 時會用reg 屬性來設置 IORESOURCE_IRQ 類型的資源。對於 interrupts 屬性,內核會檢查它的有效性,所以不建議在設備樹裏使用該屬性來表示其他資源。
在我們的工作中,驅動要求設備樹節點提供什麼,我們就得按這要求去編寫設備樹。驅動程序中根據 pin 屬性來確定引腳,那麼我們就在設備樹節點中添加 pin 屬性。
比如:
設備樹節點中有
#define GROUP_PIN(g,p) ((g<<16) | (p))
100ask_led0 {
compatible = “100ask,led”;
pin = <GROUP_PIN(5, 3)>;
};
驅動程序中,可以從 platform_device 中得到 device_node,再用 of_property_read_u32
得到屬性的值:
struct device_node* np = pdev->dev.of_node;
int led_pin;
int err = of_property_read_u32(np, “pin”, &led_pin);
三、編寫程序
在本實驗中,需要添加的設備節點代碼是一樣的,你需要找到你的單板所用的設備樹文
件,在它的根節點下添加如下內容:
#define GROUP_PIN(g,p) ((g<<16) | (p))
100ask_led@0 {
compatible = "100as,leddrv";
pin = <GROUP_PIN(3, 1)>;
};
100ask_led@1 {
compatible = "100as,leddrv";
pin = <GROUP_PIN(5, 8)>;
};
- 對於QEMU 模擬的 IMX6ULL 板子,我的設備樹文件是在內核源碼目錄中
/home/clay/linux/qemu/kernel/100ask_imx6ull-qemu/linux-4.9.88/arch/arm/boot/dts/100ask_imx6ul_qemu.dts
。
-
修改、編譯後得到
arch/arm/boot/dts/100ask_imx6ul_qemu.dtb
文件- 注意需要在內核源碼的根目錄下,執行
make dtbs
- 我的內核源碼目錄是:
/home/clay/linux/qemu/kernel/100ask_imx6ull-qemu/linux-4.9.88
- 注意需要在內核源碼的根目錄下,執行
-
然後去覆蓋qemu板舊的dtb文件,路徑在qemu安裝目錄下的
./imx6ull-system-image
文件夾中,我的是/home/clay/linux/qemu/new/ubuntu-16.04_imx6ul_qemu_system/imx6ull-system-image
目錄
然後修改chipY_gpio.c,較上一節不同的是,主要修改瞭如下幾個地方
- 添加of_match_table屬性,定義其中的compatible屬性和設備樹中的一致,做到Platform_device和Platform_driver匹配!
- 修改probe函數,通過of函數獲取設備樹中的定義的引腳,創建設備
- 修改remove函數,銷燬設備
刪除了board_A_led.c因爲由設備樹指定資源!其他的內容幾乎不變!
四、運行程序
編譯程序沒有問題後,運行qemu虛擬開發板,並做好準備工作!
- 拷貝所有的.ko和ledtest到NFS中
cp *.ko ledtest ~/linux/qemu/NFS/
- 在qemu終端,加載ko文件,需要注意的是,因爲有依賴關係,所以順序需要確定!chipY_gpio.ko依賴leddrv.ko,故需要先加載leddrv.ko!
insmod leddrv.ko
insmod chipY_gpio.ko
在qemu中加載最後一個模塊時,會出現下面的提示信息,但是ctrl+c之後,似乎測試還是可以用的,不知道是怎麼回事。知道的朋友,可以在下面留言一起探討!
-
查看LED對應的設備樹節點是夠加載成功
cd /sys/firmware/devicetree/base/
,然後輸入ls
命令可以看到如下信息
- 其中就包含了我們在設備樹中添加的兩個LED節點!
- 我們可以進入節點,查看節點的屬性。
cd cd 100ask_led@0
- 屬性值是字符串時,用 cat 命令可以打印出來;屬性值是數值時,用 hexdump 命令可以打印出來。
- 除了可以看到設備樹信息,我們當然也可以看到節點解析後生成的platform_device信息
cd /sys/devices/soc0
,然後可以看到一堆的platform_device,當然也可以周到我們的led了.
- 繼續進入led裏,
cd 100ask_led@0
,可以看到Platform_divice的各種屬性,需要注意的是其中的driver目錄,這個是只有在platform_device和Platform_driver綁定後纔會生成的!
- 當然我們可以查看driver的具體信息,
ls -l driver
,可以看到它指向/sys/bus/platform/drivers/100ask_led
-
在qemu終端,運行應用程序打開LED0
./ledtest /dev/100ask_led0 on
led0對應的就是GPIO3_IO1引腳,這個在設備樹中指定的!
- 在qemu終端,運行應用程序打開LED1
./ledtest /dev/100ask_led1 on
led1對應的就是GPIO5_IO8引腳
終於終於,將設備樹的內容一口氣輸出完了,但是上面的程序我們並沒有配置具體的硬件,爲了更好的理解設備樹思想嘛!所以,這還僅僅是一盞假的LED,別急別急,下一次我們真的LED就要來了!拭目以待~~