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