2017年8月3日 星期四

系統架構設計實例分析(I)





菜鳥『你花了好多時間在說明系統架構的重要性,我大部分都能理解,但心裡還是有點虛虛的;因為實際上每個專案的特性與要求都不一樣,我實在沒有把握當自己碰到新的應用或硬體配置時,也能設計出正確的系統架構!』

PM『我們作產品的並沒有所謂的正確的最好的系統架構,一來業界並沒有評估系統架構優劣的標準,而且執行電子產品開發追求的應該是種足夠好的水準;所以實作上系統架構的設計總是循序漸進的,資深如我也沒把握一次就把系統架構考慮周全,畢竟CPU的運算能力、記憶體的size、應用的複雜程度、可投入專案的資源、公司之前是否有相關技術累積等都可能會影響到系統架構。

好吧,今天我花點時間講講兩個我們之前作過的案子,這兩個案子相當具有代表性,在設計系統架構時都經歷了一番討論與取捨。』

Case study (I) – 8bit MCU + NAND 的系統架構

PM『首先我們來說一個computing powermemory size嚴重受限的例子,其硬體架構如下:

 CPU8bit MCU (e.g. 8051相容),定址空間最大為64KB
 DSP:因為CPU計算能力實在太弱,所以需要一顆DSP負責影音資料的解碼
 Memory40KB(程式執行與runtime資料所需的空間都在這40KB內,甚至比CPU位址空間的極限64KB還要小)
 NAND FlashGB等級
 Boot ROM inside CPUboot-ROM會自NAND Flash的特定位置載入一小段程式到SRAM裡執行

因為memory size實在太小,最後真的是寸土必爭,而且都是以byte為單位;再加上每新增一組的API就會多出一些函數,勢必要付出code size增加的代價,因此所有工程師都認為在這個狀況下還要去作模組化是不現實的,所以當時的PM就決定以土法煉鋼的方式硬幹下去了。後來在同仁們的努力下,這個專案確實也拼出來了。

但真正的困難出現在接續的專案上,沒考慮模組化的code本來就較難以maintain,而且幾乎每個功能都曾專門為code size的問題作過調整,所以導致新專案想要重複使用前專案的研發成果並不容易;再經過幾個同性質的專案作下來,面對新功能導致的code size問題只能挖東牆補西牆,最後整個系統簡直是到處貼滿了狗皮膏藥,新進工程師的學習曲線相當陡峭,這種案子變成PM間的燙手山芋。

當我還是菜鳥PM時,這個燙手山芋丟到了我的手上;我研究了一陣子,終於決定斷尾求生,開始組織同仁重新進行系統架構設計。如果是由你負責這個案子,你會想怎麼設計系統架構?試著在紙上把方塊圖畫出來。』

菜鳥『以前聽你說過這個案子,似乎曾把大家搞得灰頭土臉,幸好我們現在的專案用的是32bit CPU,記憶體是MB等級的,不用跟一個個BYTE奮戰。

以硬體配置來看,我認為首先要解決的問題是:程式的footprint(包含code data size)遠大於SRAMsize(40KB)。既然NAND Flash的空間那麼大,我們可以把所有的產品功能切分為一個個獨立的程式並儲存在NAND flash內,而這些程式的footprint必須控制在40KB內,需要時可自NAND Flash載入SRAM執行;透過不斷的切換,應該就可以完成最終產品所需的功能,我的系統架構如下圖,我將其稱之為Program-Switch Arch.。』
 

菜鳥『首先SRAM中必須有一塊永遠不會被置換出去的程式,我稱之為Basic System,負責作Program之間的切換;而當我們把所有程式燒入NAND Flash後,必須將這些programsize與在NAND Flash內的位置紀錄在一張表格(稱之program index table),並寫入NAND Flash中,則basic systemruntime時才知道去哪裡載入program

如何,這個架構應該可行吧?

PM『不錯,這個架構不但可行,還實際用在了幾個專案。』

菜鳥『難道你剛剛說造成最後很難maintain的架構就是長成這樣?』

PM『是的,當初的分析結果也是認為code size是最大的問題,最直覺的作法的確就是如你所設計的架構。用這個架構來完成第一個專案確實也沒什麼大問題,但後續專案要沿用此系統就會碰到一個個麻煩。

舉例來說,當碰到code size問題時,只要把當前program切成兩個program即可;而這兩個program可能都需要用到同一個模組,但可用memory size實在太少,無法在每個programlink完整的模組,亦即模組提供的功能多寡必須依使用者(caller)而異。

我們作系統時總是禀持著一個基本原則:底層的系統必須盡量可以支援各種不同應用,所以系統的性質是比較一般化的,它不該與使用者有太深的關係,否則一旦換了使用者,系統的運作就可能會出問題。所以上面的作法,導致系統與應用程式的耦合度太高,破壞了模組化的基本精神;所以之後的maintain與擴充都會非常麻煩!』

菜鳥『有聽沒有懂,可以舉個例子嗎?』

PM『我們有個功能是MP3播放,播放時有兩個主要的功能,一個是顯示歌詞或頻譜,另一個是顯示檔案列表,讓使用者可以瀏覽檔案或換曲;顯然40KB作這些功能是遠遠不足的,所以我們使用兩個program來實現這個應用,會用到的系統模組有:1. drivers2. Play Engine(負責播放MP3)3. File System(負責檔案的存取)4. UI Common (提供簡單的視窗系統功能)

請參考下圖,兩個program都無法把這些完整的模組塞入40KB中。因為第一個programMP3時還要作歌詞同步,但同一時間只需要access一個檔案,所以它需要較多Play Engine,與較少的File System;第二個program恰恰相反,它需要較少Play Engine,與較多的File System。』




 
PM『為了滿足這樣的需求,於是所有系統模組的程式就會變成像下面的程式一樣,就一個字 – “!原本應該功能單純的模組,為了滿足不同programcode size的需求,裡面加了一堆#ifdef…#else..#endif;這還是一個專案的狀況,如果用同一個系統run了多個專案後,你能想像系統程式會亂成什麼樣子嗎?

程式毫無可讀性可言,且難以維護,但這還不是最糟糕的狀況!



菜鳥『這個程式真的很難一眼看出某個程式段到底會不會被執行,對不熟的工程師來說,確實很容易因此犯錯,但你說這還不是最糟的?』

Ref: Link

沒有留言:

張貼留言