時間:2018-08-27 00:00:00 來源:信盈達(dá) 作者:信盈達(dá)
做嵌入式應(yīng)用開發(fā),如果沒有好的應(yīng)用架構(gòu)會是一個很大的煩惱,信盈達(dá)小編帶大家分享嵌入式程序設(shè)計的一些思路
如果沒有好的架構(gòu),移植將會是一件很痛苦的事情。
如果沒有好的架構(gòu),復(fù)用是最大的難題,沒法更大限度的復(fù)用原有的代碼。
如果沒有好的架構(gòu),一旦驅(qū)動改了,所有的地方都要改,費(fèi)時費(fèi)力且很容易出錯。
如果沒有好的架構(gòu),應(yīng)用層中穿插著硬件驅(qū)動層的代碼,看著會是一片混亂,邏輯不清,代碼維護(hù)起來會很困難。
?
現(xiàn)在的小朋友都愛玩搭積木的游戲,一個模塊一個模塊的拼裝起來,快速組成各種不同的模型?,F(xiàn)在的產(chǎn)品設(shè)計也很少從零開始。大都復(fù)用現(xiàn)有成熟的模塊,專注于某個擅長領(lǐng)域。
要做到嵌入式應(yīng)用的代碼邏輯清晰,且避免重復(fù)的造輪子,沒有好的應(yīng)用架構(gòu)怎么行!
把API分為驅(qū)動層和應(yīng)用層API,而不是所有程序都調(diào)用驅(qū)動層API。(整個應(yīng)用中都調(diào)用驅(qū)動層API會導(dǎo)致應(yīng)用中驅(qū)動調(diào)用隨處可見,無法移植和最大限度的復(fù)用)
先把一個應(yīng)用進(jìn)行功能模塊劃分,并對整體結(jié)構(gòu)進(jìn)行分層,然后設(shè)計出功能獨立的各個模塊(如算法模塊,文件庫模塊,通信庫模塊),在模塊之上開放公共接口。
驅(qū)動層提供出公共接口供上層調(diào)用。各個功能模塊可以獨立編譯(如算法模塊純ANSI C,可在任意平臺復(fù)用),或者調(diào)用驅(qū)動層接口(文件庫模塊調(diào)用了驅(qū)動讀寫Flash),總而言之,言而總之,封裝出各個功能獨立的可復(fù)用的功能模塊。
?
總體分 硬件驅(qū)動層-->功能模塊層-->應(yīng)用接口層-->業(yè)務(wù)邏輯層-->應(yīng)用層
總體結(jié)構(gòu)示意框圖:
?
應(yīng)用層,為程序的總體的運(yùn)行框架,組織調(diào)用業(yè)務(wù)邏輯??梢杂媚撤N嵌入式操作系統(tǒng)實現(xiàn)幾種任務(wù) 。如定時任務(wù),卡處理任務(wù),菜單任務(wù),通信任務(wù)。
?
業(yè)務(wù)邏輯層,如CPU卡處理,交通部卡處理,銀聯(lián)卡處理,M1卡處理,通信記錄上傳,黑名單下載,票價參數(shù)下載等。
?
應(yīng)用接口層,提供公共的api接口供應(yīng)用接口供上層調(diào)用。這些接口也可由下層的功能模塊開放出來,應(yīng)用接口層負(fù)責(zé)匯總。
?
功能模塊層,可以封裝不同的功能模塊。如算法庫,文件庫,通信庫,銀聯(lián)庫,向上提供應(yīng)用接口層的接口,向下調(diào)用驅(qū)動接口。
?
硬件驅(qū)動層,由各個驅(qū)動模塊組成,向上提供統(tǒng)一的接口。
?
遵循一些約定:
1.每個模塊提供出的接口要統(tǒng)一,后續(xù)只能增,不能改原來的接口。
2.模塊與模塊之間相互獨立,互不影響,不能相互調(diào)用,只能調(diào)用它下層的接口。
3.由模塊構(gòu)成層,層與層之間不能跨級調(diào)用。如在應(yīng)用層中不能看到直接調(diào)用驅(qū)動層的代碼。
4.模塊中又可以繼續(xù)分層,如接口層,驅(qū)動層,硬件層。
?
如果驅(qū)動變動了,或者換不同平臺,只需更改驅(qū)動層,應(yīng)用層不受影響。
?
如果功能模塊變動了,只需升級功能功能模塊,其他的模塊不受影響,應(yīng)用層也不受影響。
?
按照這種邏輯設(shè)計好之后,主要的工作就是在業(yè)務(wù)邏輯層。應(yīng)用層則為程序的總體流程和框架,主要調(diào)用業(yè)務(wù)邏輯層實現(xiàn)不同的功能。
?
我們現(xiàn)在的代碼結(jié)構(gòu),基本是按這個思路來的。
?
硬件驅(qū)動層-->功能模塊層-->應(yīng)用接口層-->業(yè)務(wù)邏輯層-->應(yīng)用層。
?
看看以下兩種風(fēng)格的代碼,你更喜歡哪個。
?
另一種風(fēng)格:
?
同樣是保存參數(shù),非要拆成 AlgCRC16 ?,WritePraFlash( (unsigned char *)&NetPra , NETPRA_ADDR , sizeof(_NetPra) )兩步嗎?
?
還有AH_Para_Verify這個,在應(yīng)用層中真是多余啊,檢測失敗又從Flash讀取。關(guān)于參數(shù),一開機(jī)就應(yīng)該檢測合法性了。
?
既然都是要保存參數(shù),就應(yīng)該做個封裝,如上圖所示,把系統(tǒng)用到的不同參數(shù)做個規(guī)劃。應(yīng)用層調(diào)用APP_Open_UseFile 或者APP_Read_UseFile,而不是直接的去讀寫Flash。
?
來看看赫赫有名的谷歌的android架構(gòu),雖然很復(fù)雜,但從框圖上看,也像是搭積木,各個功能模塊獨立,層次分明。最低層建立在linux Kernel基礎(chǔ)上,然后是各個組件庫libraries,再往上是應(yīng)用框架和應(yīng)用。
?
?
?
以NC_FileLib,文件庫模塊為例,如果要用在其他平臺,如EH0918手持機(jī)設(shè)備,只需要移植幾個硬件層接口即可。
?
NC_FileSys文件庫,跟硬件相關(guān)的接口在Hook文件夾,
重新實現(xiàn)以下幾個函數(shù)即可:
void HW_FRAM_Init( void )
unsigned int HW_FRAM_Read( unsigned int ???addr,unsigned int ???size,unsigned char ???*buffer)
unsigned int HW_FRAM_Write( unsigned int ???addr, unsigned int ???size,unsigned char ???*buffer )
//擦除FLASH一頁 (FLASH擦除的最小單元)
unsigned int HW_Flash_PageErase( unsigned int page )
unsigned int HW_Flash_Read( unsigned int addr, unsigned int size, unsigned char *buffer )
unsigned int HW_Flash_NotEraseWrite( unsigned int addr, unsigned int size, unsigned char *buffer )
//擦除FLASH一頁 (FLASH擦除的最小單元)
unsigned int HW_Flash_PageErase( unsigned int page )
?
按照以上模塊化設(shè)計思想,很容易實現(xiàn)一模擬pos機(jī):
以開發(fā)一個智能pos應(yīng)用為例:
一個智能pos涉及到的功能模塊有:
讀寫卡功能,保存與讀取消費(fèi)記錄,查找保存黑名單,界面顯示,菜單顯示,通信下載參數(shù)上傳記錄等。
在電腦上實現(xiàn)一模擬pos用到的功能模塊有 文件存儲模塊,卡處理模塊,算法模塊,銀聯(lián)庫模塊。我把這些模塊移植到電腦上。
?
只是功能上的實現(xiàn),完成刷卡消費(fèi),記錄存儲,記錄上傳,黑名單,票價下載等功能。界面為Dos窗口。后續(xù)如果用QT把界面也做出來,就是一功能齊全的模擬POS機(jī),不過得把荒廢多年的C++重新拾起來了。可以繼續(xù)完善做一個上位機(jī)模擬pos,改變編譯器在上位機(jī)仿真調(diào)試并交叉編譯后運(yùn)行在真實POS上。
?
關(guān)于卡處理模塊的實現(xiàn),由于電腦上沒讀卡頭,于是用外接讀卡器。把讀卡器串口接電腦上。電腦上做一讀寫卡服務(wù),提供TCP接口的讀寫卡接口。
?
移植文件庫,嵌入式程序中是操作的flash,在電腦上把文件庫中用到的接口用讀寫文件的形式替換。
?
移植算法庫,算法庫都是c寫的,直接用gcc在windows平臺重新編譯即可。
?
各個功能模塊,又可以進(jìn)一步細(xì)分為子模塊。
?
拿通信庫舉例:
嵌入式設(shè)備都需要支持各種不同的通訊模塊。比如硬件設(shè)備有A701、A801、B502等,通訊模塊有GL868、MG323、MC8630、N710、ZIGBEE等,這些設(shè)備分別支持全部或部分通訊模塊。
?
整體架構(gòu)分為如下:
?
?
?
驅(qū)動大致分為三層:
1、接口層:為用戶提供統(tǒng)一的接口,比如:Connect、TxData、RxData、Disconnect等。
2、驅(qū)動層:向接口層暴露統(tǒng)一的接口,這些接口用于完成實際的連接斷開和數(shù)據(jù)收發(fā)等,比如:DevConnect、DevTxData、RxData、Disconnect等。該層只會和支持的通訊模塊相關(guān),不會直接訪問任何硬件功能,包括串口通訊、GPIO控制全部通過底層的設(shè)備層實現(xiàn)。
3、設(shè)備層:向驅(qū)動層提供統(tǒng)一的接口,這些接口通過訪問物理硬件來實現(xiàn)和模塊的通訊,比如:XXXPowerOn、SerialSend、SerialReceive等,并定義該設(shè)備支持哪些模塊。
?
對于部分編寫通訊模塊驅(qū)動常用的功能,模塊中提供了一系列的輔助函數(shù),避免重復(fù)勞動。
信盈達(dá)2008年在深圳特區(qū)南山高新科技園成立。自成立至今近九年來專注為企業(yè)和個人提供高端方案設(shè)計、高端嵌入式/Android培訓(xùn)等服務(wù)。公司下設(shè)信盈達(dá)實訓(xùn)學(xué)院、信盈達(dá)研發(fā)中心、信盈達(dá)教學(xué)儀器三大業(yè)務(wù)板塊。九年來公司堅持"技術(shù)領(lǐng)先、服務(wù)領(lǐng)先",以雄厚的實力和專業(yè)的品質(zhì)成為國內(nèi)唯一有實力從產(chǎn)品最底層研發(fā)到系統(tǒng)層開發(fā)的嵌入式實訓(xùn)、產(chǎn)品解決方案提供商。為中國IT行業(yè)提供最具價值的職業(yè)教育服務(wù)。專業(yè)培訓(xùn)嵌入式、物聯(lián)網(wǎng)、人工智能、Java、單片機(jī)等課程,想了解更多信息點擊立馬咨詢
免費(fèi)領(lǐng)取試聽卡
申請已經(jīng)提交
老師會馬上給您安排試聽課程!
申請出錯了
您可以加老師QQ:914865590報名咨詢!