在以往的軟體開發中,在結構上吃了不少的虧。慢慢的對結構方面逐步重視起來,下面我寫一些關結構方面的認識,希望大家指導批評。這樣在不段指正下成長 方能造就出,可靠性高,移植性強,維護方便的程式出來。
個人感覺,在寫代碼時,盡量做到模組化。Ucos是個很好的平台,他可以讓所有的功能化分為多個模組。在其之間有很好的獨立性,就是說只要給你一個任務,就可以完成一個功能。可是任務間有時也會牽扯到資料互動的問題,這個時候就使用模組介面。別人在載入您的模組介面標頭檔時後,所有的資料都可以通過介面傳遞了,這樣塊的封裝就可以做的非常獨立。這樣在功能的刪除和增加會變的很簡單。不用再為兩個模組 重複的枚舉,宏而擔心。因為所有的變數,都是本地的(靜態)。嘿嘿,本地模組是你的,你就可以隨心所欲。當然在保證編程規範的前提下。最主要的是介面函數,要清晰明了。別人看一眼也大概是什麼功能,就很到位了。
到這裡,就不得不說下在用ucos整個軟體的層次了。筆者以往是採用四層的方式,硬體相關層,驅動介面層,應用介面層,應用程式層。好的分層會讓軟體開發相對獨立化,分工同步進行。下面是以前找資料看到的結構,感覺很不錯。
所有的硬體被抽象化,應用程式層的程式,基本上不用再考慮硬體的問題,也就是說,在硬體完全更換的情況下,只要硬體相關層被更新,完全可以等同原先的所實現的功能。這樣就極大成度上方便了移植。要做到完全的劃分,下面逐步對這幾層做一個說明。
硬體相關層:在這層中,要盡量所有硬體相關都囊括在其中。不管是GPIO還是定時器,或串列介面。只要提供標準統一的介面,就可以讓上層會因此而變的很瀟洒。這其中有三個最為重要的介面Open,Close,Ctrl。 Open主要來完成對應硬體初始化,形參中包括了些,初始化的相關參數。Close失能硬體。Ctrl來實現一些控制的修改如:優先順序,中斷回呼函數等等,硬體的不同,內容也大為不同。
驅動介面層:其實在上一層也算是驅動層,只不過因為硬體相關,而把他分離。這層中會用到一個或多個硬體層的介面,進行組合來實現特定功能的程式。這部分程式可舉例進行說明。以Flash為列,它這裡主要調用硬體層的SPI函數介面,但是主要的寫,讀指令都是在這裡函數中完成的。在這層中需要提供5個標準統一的介面函數:
XXXOpen
XXXClose
XXXWrite
XXXRead
XXXIoCtl
沒有被用到的函數,可以為空白。本來還需要Install函數來進行動態載入和刪除,因為stm32記憶體一般都很有限,所以捨棄動態分配。而把這5個函數用常量的形式直接編譯到ROM中。在驅動的抽象介面層中可以做選擇,哪些驅動要載入到核心,哪些不需要。不要的驅動不參與編譯。這樣有限的資源 可以得到合理的應用。這一層大部分工作可以說屬於一次性投入。
應用介面層:主要串連驅動和應用。又是串連應用程式層模組與模組之間的一層, 這一塊有很強的特殊性,第一包括了驅動抽象介面層,第二包括了模組與模組的介面層。第三又與應用程式層密不可分。
先說下驅動抽象介面,在驅動層時也有提過,這個介面 其實就是通過ID去訪問那ID對應的那五個函數。抽象介面也是一次性投入的函數,在設計時對其可靠性要很重視。
模組與模組的介面層,包括模組的介面標頭檔,這些標頭檔要求是非常獨立的,不能載入模組內的內部標頭檔,應該包括介面函數的函式宣告,在介面中盡量少用到全域變數。如果非要用到可以使用函數的方式進行傳遞,或ucos訊息佇列方式。最好用ucos進行傳遞,因為有很好的互斥保護功能。
應用程式層:這裡所有模組都算是應用程式層,在前面以經提到過,在模組內所有變數,或函數(介面除處)應該都本地化。在模組內可以有本模組化共用的主標頭檔,來方便本模組的維護。對硬體的訪問其實直接調用應用介面就可完成。
到些主要的結構就算是大概總結完畢,希望給大家一點點協助,也希望大家給一定的指正和完善。