【嵌入式Linux驅動開發】八、LED驅動盡善盡美 - 設備樹點亮一盞假的LED

   如果我所做的每一件事都要對我的人生有用,那我的人生到底是什麼呢?
  賺更多的錢?開更好的車?住更大的房子?
  這些鬼東西就是我的人生麼?


一、回顧編寫驅動的三種方法

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就要來了!拭目以待~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章