現狀
由于目前本人就職的公司不允許自由使用操作系統開發,且公司一般為C/C++混合開發的模式,驅動的開發也十分的草率,驅動代碼與應用代碼雜糅在一起,十分的不清晰。個人又十分喜愛RT_Thread這個系統,也翻閱過一些內核源碼,學習到了非常多的有用的開發技能。
于是我想到,為何不能自己建立一套驅動管理機制來進行統一?于是萌發了使用C++來構建RT_Thread的設備驅動框架的想法。當然,我并沒有做到完全一致,而是加入了自己的一些想法,并且也是基于了目前的開發現狀來進行了一定的修改(不允許貼源碼只能截圖哈)。
實現過程說明
RT_Thread的內核對象分為很多種類別,線程、信號量、互斥量、設備、定時器…由于借鑒了RT_Thread的源碼,故進行了刪減,只保留設備部分,且去除了對象類型和動態申請內存使用的size變量(RT_Thread的源碼這一部分代碼就不貼了),如圖:
內核對象類:
RT_Thread是把rt_object這個結構體作為雙向鏈表的元素,這里的話是把CObject這個類作為雙向鏈表的對象(C++的類其實和結構體是一樣的)。
對象的操作只保留了object_find、object_init、object_detach,修改了register和unregister的操作。type、name、usr_data保留,其中type(設備的類型)根據實際應用做了一些修改(部分定義):
鏈表的插入刪除操作原封不動“抄”了RT_Thread的源碼,如圖:
新增驅動的控制與循環
因為刪除了open和close,且考慮到有些驅動需要調用循環實現一定的功能,故新增一個驅動控制類CObjCtrl:
該類非常簡單,如果驅動未使能則循環退出,且循環的主體(ObjProcess())需要該類被繼承后進行虛函數的重寫。
新建注冊類(基本抽象類)
注冊類的作用主要就是繼承了CObjCtrl,且替代RT_Thread的register函數和unregister函數,將對象接入雙向鏈表。該類的實現如下:
需要注意的是,不在需要手動調用register和unregister這兩個注冊卸載函數了,因為在驅動類構造函數執行的時候回自動調用(見構造函數和析構函數)。GetType()和GetName()函數比較常規。構造函數需要傳入驅動的類型、名字和私有數據(私有數據的作用下面會有說明)。
因為繼承了CObjCtrl類,故需要重寫虛函數ObjProcess(),重寫的ObjProcess()函數由調用了本類的AbsLayerProcess()純虛函數,故本注冊類依然需要被繼承后重寫該純虛函數AbsLayerProcess()。
驅動抽象類
該類主要就是繼承了上述注冊類,且存在常規的read、write、control接口(虛函數)。
RT_Thread的驅動初始化是在open函數調用的時候被調用的,我去除了open和close,所以驅動的初始化放在find函數內部,通過變量b_IsInitOK來記錄是否已經進行過初始化,也可以手動調用函數DriverInitial()來進行驅動的初始化。查看構造函數可以發現,私有數據記錄了本驅動抽象類的地址(因為傳入了this指針)。
又重寫了注冊類的AbsLayerProcess()函數,該函數調用的真正需要驅動實現的循環函數DriverProcess()。
至此,設備驅動框架部分代碼全部開發完畢。
使用示例
以flash芯片AT45DB為例:
需要實現驅動的read、write、control、init函數(因為該驅動不需要循環,所以不需要重寫DriverProcess()循環函數)。構造函數傳入SPI相關信息(自己實現的代碼,不深究)和驅動類型及名字。
實例化驅動類,自動將“對象”注冊至鏈表內:
使用如下:
至此,基本的設備驅動框架已經形成,當然后面又做了一定的拓展和優化,這里不再贅述。RT_Thread實在是一個寶藏系統!
-
驅動器
+關注
關注
52文章
8241瀏覽量
146399 -
控制器
+關注
關注
112文章
16374瀏覽量
178157 -
SPI接口
+關注
關注
0文章
258瀏覽量
34386 -
C++語言
+關注
關注
0文章
147瀏覽量
6993 -
RT-Thread
+關注
關注
31文章
1290瀏覽量
40154
發布評論請先 登錄
相關推薦
評論