例程代碼路徑:ELF 1開發(fā)板資料包3-例程源碼3-2 驅(qū)動例程源碼6_platformplatform
示例源碼
#include <linux/init.h>
#include <linux/module.h> #include <linux/platform_device.h> static int my_platform_probe(struct platform_device *pdev) { printk(KERN_INFO "my_platform_probe: Platform device probedn"); return 0; } static int my_platform_remove(struct platform_device *pdev) { printk(KERN_INFO "my_platform_remove: Platform device removedn"); return 0; } static const struct of_device_id of_platform_match[] = { { .compatible = "platform", }, {}, }; static struct platform_driver my_platform_driver = { .driver = { .name = "my_platform_driver", .owner = THIS_MODULE, .of_match_table = of_platform_match, }, .probe = my_platform_probe, .remove = my_platform_remove, }; module_platform_driver(my_platform_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Platform Driver Example"); |
上述示例定義了一個名為 "my_platform_driver" 的平臺驅(qū)動程序。驅(qū)動程序中的 my_platform_probe() 函數(shù)是探測函數(shù),my_platform_remove() 函數(shù)是移除函數(shù)。還定義了一個platform_driver類型的結(jié)構(gòu)體,結(jié)構(gòu)體定義如下:
struct platform_driver {
int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t); int (*resume)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; bool prevent_deferred_probe; }; |
定義說明:
(一)probe:驅(qū)動探測函數(shù)指針,當設(shè)備與驅(qū)動匹配時調(diào)用。它接收一個指向structplatform_device的指針作為參數(shù),返回一個整數(shù)類型的值。
(二)remove:驅(qū)動移除函數(shù)指針,當設(shè)備被移除時調(diào)用。它接收一個指向structplatform_device的指針作為參數(shù),返回一個整數(shù)類型的值。
(三)shutdown:關(guān)機回調(diào)函數(shù)指針,當系統(tǒng)關(guān)機時調(diào)用。它接收一個指向struct platform_device的指針作為參數(shù),無返回值。
(四)suspend:掛起回調(diào)函數(shù)指針,當系統(tǒng)進入掛起狀態(tài)時調(diào)用。它接收一個指向struct platform_device的指針和pm_message_t類型的參數(shù)作為輸入,返回一個整數(shù)類型的值。
(五)resume:恢復回調(diào)函數(shù)指針,當系統(tǒng)從掛起狀態(tài)恢復時調(diào)用。它接收一個指向struct platform_device的指針作為參數(shù),返回一個整數(shù)類型的值。
(六)driver:包含了驅(qū)動的名稱、擁有者等信息的 struct device_driver 結(jié)構(gòu)體。
(七)id_table:一個指向平臺設(shè)備ID表的指針,用于與設(shè)備匹配。它可以為空,或者指向一個以NULL結(jié)尾的數(shù)組。
(八)prevent_deferred_probe:一個布爾值,用于指示是否禁止推遲的探測。如果設(shè)置為true,則在設(shè)備匹配時不會推遲探測過程。
通過使用module_platform_driver宏,我們可以將驅(qū)動程序的注冊和注銷過程簡化為一行代碼。宏會自動為驅(qū)動程序注冊和注銷函數(shù),并處理必要的初始化和清理工作。
需要注意的是,驅(qū)動程序中的probe和remove回調(diào)函數(shù)必須與平臺驅(qū)動程序的結(jié)構(gòu)體字段對應(yīng),以正確地處理設(shè)備的探測和移除。
of_platform_match[]數(shù)組中定義了設(shè)備兼容性匹配項,當內(nèi)核在設(shè)備初始化過程中加載驅(qū)動時,會遍歷設(shè)備樹中的設(shè)備節(jié)點,并將每個設(shè)備節(jié)點的compatible屬性與驅(qū)動中的兼容屬性進行匹配。只有當匹配成功時,才會執(zhí)行相應(yīng)的probe函數(shù)。
編譯
復制上一節(jié)驅(qū)動中的Makefile文件,將其中的myirq_key.o修改為platform.o,效果如下:
. /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
elf@ubuntu:~/work/test/06_platform/platform$?make |
將編譯生成的platform.ko模塊拷貝到開發(fā)板中
修改設(shè)備樹
在設(shè)備樹根節(jié)點下添加設(shè)備,否則無法進行匹配。打開arch/arm/boot/dts/imx6ull-elf1-emmc.dts添加如下內(nèi)容:
my_device {
compatible = "platform"; }; |
添加后效果如下:
編譯設(shè)備樹,單獨替換設(shè)備樹并重啟。
測試
root@ELF1:~# insmod platform.ko
my_platform_probe: Platform device probed root@ELF1:~# rmmod platform.ko my_platform_remove: Platform device removed |
可以看到在驅(qū)動加載時,進入到了probe函數(shù),在驅(qū)動卸載時進入到了remove函數(shù)。從上面示例中可以了解到使用 module_platform_driver 宏可以大大簡化平臺驅(qū)動程序的編寫過程,并提高代碼的可讀性和可維護性。