總線設備驅動模型的極簡框架

分離:把硬件相關的東西抽出來;把相對穩定的軟件部分抽出來。
分層:input.c 向上提供統一給 APP 操作的統一接口。每一層專注於自已的事件。
在這裏插入圖片描述

一邊的“device”結構體和另一邊的“較穩定的 drivice 代碼”的聯繫:
“device_add()”除了將“devcie”結構放到 bus 的“dev 鏈表”之外,還會從另一邊的“drv”
鏈表中取表元即某個“driver”結構,用總線裏的一個(.match)函數來作比較,看另一邊的
“driver”是否支持一邊的“device”。若是能夠支持,則接着調用軟件驅動部分的“.probe”
函數。
“driver_register()“會將“bus_drv_dev”模型中的較穩定代碼“driver”結構體放到虛擬總線的
某個鏈表(drv 鏈表)中。從另一邊的“dev”鏈表中取出每一個“device”結構用 bus 中的
“.match”函數來作比較,若支持則調用“.probe”函數。
“只不過”左右兩個註冊建立起來的一種機制。在“.probe”函數中做的事件由自已決定,
打印一句話,或註冊一個字符設備,再或註冊一個“input_dev”結構體等等都是由自已決定。
強制的把一個驅動程序分爲左右兩邊這種機制而已,可以把這套東西放在任何地方,這裏的
“driver”只是個結構體不要被這個名字迷惑,“device”也只是個結構體,裏面放什麼內容
都是由自已決定的。
第一部分:簡單框架搭建
首先,寫“平臺設備”:
Led_dev.c 設備部分:
1,定義平臺設備:
1.1,分配、設置、註冊一個 platform_device 結構體。
led_resource主要包含哪個寄存器;
LED的寄存器起始地址:
gpfcon = (volatile unsigned long *)ioremap(0x56000050,16);
LED寄存器結束地址:gpfdat = gpfcon + 1;
以及內存資源。
在這裏插入圖片描述
1.2,入口函數:註冊一個平臺設備
在這裏插入圖片描述
1.2.1,看註冊平臺設備的過程:
platform_device_register (&led_dev);
–>platform_device_add(pdev);
–>device_add(&pdev->dev); 將device放到平臺總線的“dev”鏈表中去。
1.3,出口函數:卸載平臺設備
在這裏插入圖片描述
1.4,修飾出入口函數:
在這裏插入圖片描述
以上便寫好了平臺設備部分代碼。
接着寫“平臺驅動”:
2.1, 定義平臺驅動:
2.1.1,分配、設置、註冊一個 platform_driver 結構體。定義一個平臺驅動.因爲平臺總線的.match 函數比較的是"平臺設備"和"平臺驅動"的名字.所以兩邊名字要相同這樣纔會認爲這個 drv 能支持這個 dev。纔會調用平臺驅動裏面的”.probe"函數。
在這裏插入圖片描述
2.2,構造平臺驅動結構中的“.probe”函數:
2.2.1,平臺驅動結構中的”.probe"函數.這個函數是自已按照自已的要求寫的。首先、根據 platform_device 的資源進行 ioremap,其次、註冊字符設備驅動程序
在這裏插入圖片描述
2.3,構造平臺驅動結構中的“.remove”函數:做與“.probe”相反的事件。首先、根據 platform_device 的資源進行 iounmap。其次、卸載字符設備驅動程序
在這裏插入圖片描述
2.4,入口函數:註冊一個臺平臺驅動。
在這裏插入圖片描述
2.5,出口函數:卸載平臺驅動。
在這裏插入圖片描述
2.6,修飾出入口函數:
在這裏插入圖片描述
進行編譯加載
在這裏插入圖片描述
單板掛接 NFS 文件系統:
註冊"led_platform_drv.ko":
在這裏插入圖片描述
這時候 insmod led_platform_dev.ko 後沒有任何輸入,是因爲只是把平臺驅動結構放到了 bus
平臺總線的“drv”鏈表中。而此時另一邊的“設備鏈表”中還沒有同名的“device”。接着
再註冊“led_platform_dev.ko”
在這裏插入圖片描述
卸載時,就會打印“platform_driver led_drv”結構的“.remove = led_remove”函數:
platform_driver led_drv->(.remove = led_remove)
–>int led_remove(struct platform_device *pdev)
–>printk(“led_remove, remove led\n”);
卸載是“void led_drv_exit(void)”
–>platform_driver_unregister (&led_drv);
–>driver_unregister(&drv->driver);
–>bus_remove_driver(drv);
卸載是從平臺總線的“derive”鏈表上取下注冊上的平臺設備結構,根據設備的“同名名字”
找到“平臺驅動”層之前相對應的“平臺驅動結構”,調用裏面的“.remove”函數。
卸載時出錯:提示爲沒有“release()”函數。
在這裏插入圖片描述
平臺設備 結構體定義中有一個“device”結構,這個“device”結構在“device.h”中定義:
其中有定義“void (*release)(struct device * dev);”。我們要提供這個 relase 函數,這裏
什麼都不用做。以後可以放一些硬件相關的到裏面。這個例子裏暫時不做任何事情。
修改代碼如下:
在這裏插入圖片描述
重新註冊“dev.ko”後,是將一個平臺設備結構註冊到平臺總線下的“平臺設備”鏈表,這
時另一方“平臺驅動”通過“設備名”匹配到一個“平臺驅動”結構後,調用此結構下的“.probe”
函數,爲這個“平臺設備”作相關的處理;當“insmod xx_dev.ko”後,是從“平臺設備”
結構鏈表中刪除了 這個“xx_dev.ko”,這時另一端相關同名的“平臺驅動”就調用自已結構
中的“.remove”函數作相關清理工作。
在這裏插入圖片描述
第二部分:實用代碼填充
2.1在“.probe”函數中做有意義的事情:註冊字符設備。定義主設備號並構造一個 file_operations 結構體
在這裏插入圖片描述
2.2創建‘類,讓系統自動創建‘設備節點
在這裏插入圖片描述
2.3根據 platform_device 的資源進行 ioremap。獲得資源: led_dev中有IORESOURC_MEM 內存資源, IERSOURCE_IRQ中斷資源。
在這裏插入圖片描述
2.4file_operations led_fops 結構中的 open 函數的處理。open 後要把這些引腳配置成“輸出”引腳。
在這裏插入圖片描述
2.5file_operations led_fops 結構中的 write 函數的處理。open 後要把這些引腳配置成“輸出”引腳。在這裏插入圖片描述
2.6出口函數的完善。首先,卸載平臺驅動。其次,在cls類下面創建設備,則要卸載掉類設備。接着,去掉類、卸載字符設備、"iounmap()"卸載
在這裏插入圖片描述
最後進行測試:
在這裏插入圖片描述
這兩個頭文件要包含。
在這裏插入圖片描述
接着再編譯再裝載:
在這裏插入圖片描述
要是想測試其他 LED 的情況,則修改“led_dev.c”中的引腳資源而“led_drv.c”就可以保持不動。
在這裏插入圖片描述
總結:分層是每一層專注做自已的事情。分離經常使用的就是“bus_drv_dev 模型”中,這個模型只是提供一種機制,在這個機制中做什麼事件是由自已定義的,在“.probe”函數中的操作完全 是由自已決定的(.probe 中的操作是核心內容)。

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