嵌入式Linux系統:驅動編程_註冊驅動到平臺總線

        在 Linux2.6 之後,Linux 設備驅動分爲三個實體:總線、設備、驅動,平臺總線將設備和驅動匹配。在系統註冊任意一個驅動的時候,都會尋找對應的設備;當系統註冊設備的時候,系統也會尋找對應的驅動進行匹配。

        在 Linux 系統中,任何一個 Linux 設備和 Linux 驅動都是需要掛載到一種總線中。有一些常規的大家容易理解的總線,例如 media 總線、spi 總線、hid 輸入子系統總線、eMMC 存儲設備總線等等。假如說設備本身就是一個總線設備,那麼掛載到對應的總線上,那是容易理解的。

        但是還有一些例如 led、蜂鳴器等等一些設備,都不是從字面上理解的總線設備。針對這個情況,Linux 創立了一種虛擬總線,也叫平臺總線或者 platform 總線,這個總線也有對應的設備 platform_device,對應的驅動叫 platform_driver。

        這裏介紹的平臺總線,不能夠直接和常規的總線對應,只是 Linux 系統提供的一種附加手段,防止 linux 驅動的碎片化,降低 Linux 的使用難度。

        下圖是總線、設備、驅動的框架圖。

        這裏只討論先註冊設備再註冊驅動的情況。在註冊驅動的時候,系統會通過 platform_match 函數匹配設備和驅動。
        註冊設備的結構體爲 platform_device,註冊驅動的結構體爲 platform_driver。設備和和驅動結構體的成員 name 字段,相同則匹配。如果匹配了則會調用 platform_driver 中的 probe 函數,註冊驅動。也就是在上圖註冊驅動的時候要添加一個判斷,如下圖所示。

        本文在已向系統註冊設備(hello_ctl)的基礎上展開。可參見上一篇(嵌入式Linux系統:驅動編程_註冊驅動到平臺總線 )。

 

驅動註冊——頭文件

        驅動註冊使用結構體platform_driver,該結構體在頭文件“include/linux/platform_device.h”中定義。
        驅動註冊platform_driver_register,驅動卸載函數platform_driver_unregister也在這個頭文件中– 這兩個函數的參數都只有結構體platform_driver。
 

驅動註冊——註冊結構體

        驅動常見的幾種狀態,初始化,移除,休眠,復位– 就像PC一樣,有的驅動休眠之後無法使用,有的可以使用;有的系統喚
醒之後,驅動需要重新啓動才能正常工作,也有直接就可以使用等等。

        probe函數– platform_match函數匹配之後,驅動調用的初始化函數。

        remove函數– 移除驅動函數。 

        suspend函數– 懸掛(休眠)驅動函數。

        resume函數– 休眠後恢復驅動。

        device_driver數據結構的兩個參數:– name和註冊的設備name要一致;– owner一般賦值THIS_MODULE。
 

#include <linux/init.h>
#include <linux/module.h>

/*驅動註冊的頭文件,包含驅動的結構體和註冊和卸載的函數*/
#include <linux/platform_device.h>

#define DRIVER_NAME "hello_ctl"

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("TOPEET");

static int hello_probe(struct platform_device *pdv){
	
	printk(KERN_EMERG "\tinitialized\n");
	
	return 0;
}

static int hello_remove(struct platform_device *pdv){
	
	return 0;
}

static void hello_shutdown(struct platform_device *pdv){
	
	;
}

static int hello_suspend(struct platform_device *pdv){
	
	return 0;
}

static int hello_resume(struct platform_device *pdv){
	
	return 0;
}

struct platform_driver hello_driver = {
	.probe = hello_probe,
	.remove = hello_remove,
	.shutdown = hello_shutdown,
	.suspend = hello_suspend,
	.resume = hello_resume,
	.driver = {
		.name = DRIVER_NAME,
		.owner = THIS_MODULE,
	}
};


static int hello_init(void)
{
	int DriverState;
	
	printk(KERN_EMERG "HELLO WORLD enter!\n");
	DriverState = platform_driver_register(&hello_driver);
	
	printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_EMERG "HELLO WORLD exit!\n");
	
	platform_driver_unregister(&hello_driver);	
}

module_init(hello_init);
module_exit(hello_exit);

        代碼中,定義的宏變量 DRIVER_NAME  “hello_ctl”,和前面註冊的 hello 設備的名稱相同。

        設備和驅動匹配成功就會進入函數 hello_probe 打印“initialized”。

        接着需要修改一下 Makefile 文件,將”mini_linux_module.o ”改爲“probe_linux_module.o”,註釋部分用戶可以自己修改,如下圖所示。

       

        在 Ubuntu 中的目錄“/home/topeet”中新建目錄“probe_linux_module”,拷貝驅動文件“probe_linux_module.c”和編譯文件“Makefile”到新建中,如下圖所示。

       

        進入“probe_linux_module”目錄,使用命令“make”編譯“probe_linux_module.c”,如下圖所示,生成模塊文件“probe_linux_module.ko”。

 

        啓動開發板,拷貝“probe_linux_module.ko”到 U 盤,將 U 盤插入開發板,加載驅動文件“probe_linux_module.ko”,如下圖所示,可以看到打印出了“initialized”,表明進入了probe 函數。

 

        使用命令“rmmod probe_linux_module”卸載驅動,可以看到打印“HELLO WORLD exit!”,表明卸載成功。

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