新聞中心

EEPW首頁 > 嵌入式系統 > 牛人業話 > MCU資源受限 怎么面對編程的挑戰

MCU資源受限 怎么面對編程的挑戰

作者:光華居士時間:2019-05-10來源:電子產品世界收藏

心有多大,舞臺就有多大,夢想有多大,你的世界就有多大。

本文引用地址:http://www.aejfsk.live/article/201905/400449.htm

這句濃濃的雞湯實在是太“唯心主義”了。因為,如果資源非常有限,軟件工程師的心再大,也沒有舞臺施展自己的斧鉞鉤叉。

在廣闊的人生舞臺上才能大有作為,面對廣袤的世界,大開大合地書寫自己的人生,這種揮灑、寫意的疏闊沒有人不喜歡。可是,如果你要在一個資源受限的上編程,就像是在一個空間狹小的舞臺上演話劇,你需要反復思量,才能應對空間的局促,半分揮灑就會讓劇情漫出舞臺之外。為了利用好每一寸空間,你需要反復斟酌、再斟酌,調整、再調整,哪里還有半分寫意可得?!

說實話,這種感覺實在壞透了。在一次產品開發中,筆者就切身體會過這種地獄般的局促和捉襟見肘,現在想來,還有幾絲寒意漫上心頭......

1

順利的開始等于成功的一半。筆者開始開發中控鎖模塊時,就有這種美好的感覺。因為,從功能上來看,中控鎖相當于車身控制器的一個子模塊,筆者有車身控制器的開發經驗,把它刀劈斧砍,擇菜式地弄出來個中控鎖,還不是小菜一碟?

事實證明,這還真是小菜一碟。因為我們這款用在某個國產車上的中控鎖的功能實在太簡單了,就是三大塊:機械鑰匙解鎖、閉鎖+遙控鑰匙解鎖、閉鎖+車身防盜功能,所謂車身防盜,就是車門被撬開時用轉向燈和喇叭報警。

在以往開發車身控制器的歷史積累中,開關檢測模塊、定時器管理模塊、遙控接收解析模塊都是現成的,無非是從之前的上搬過來,稍微移植一下即可。開發難度,自然是沒有的,所以深諳內情的領導把整個產品的開發周期定為三個月。

在這三個月的時間里,硬件開發和軟件開發是同步進行的,首要的工作自然是MCU的選型。

timg (2).jpg

所有成功決定的背后都是對若干關鍵因素的權衡,MCU的選型也不例外,MCU的資源、成本、性能、生命周期、供貨能力都是必須考慮的因素。其中,資源是最為軟件工程師看重的指標。

最初,領導并沒有插手MCU選型的工作,這項任務落在了我和硬件工程師張工的頭上。我個人比較青睞于飛思卡爾的單片機,因為我之前從事的所有產品的開發都用飛思卡爾系列,代碼移植起來比較方便,可是張工卻傾向于微芯的一顆MCU。反復論戰之后,報領導裁決,領導決定使用微芯方案,選用的MCU是微芯的PIC16F1509,原因無它,便宜!

這個芯片內置512字節RAM,8K字節程序Flash,和之前用過的MCU比起來確實袖珍得可以。最初打眼一看,RAM和Flash的數量好像有點少,資源到底夠用不夠用,說實話我心里是沒譜的,帶著這種忐忑的心情,我開始了代碼的移植工作。

雖然之前沒有用過微芯的產品,但是畢竟中控鎖的功能太簡單,而這顆MCU也太小巧玲瓏了,所以移植工作進行地順風順水,在硬件電路板還沒有拿到手之前,我就完成了初步編程工作。板子到手后,一頓操作猛如虎,調試、運行、修改三板斧下來,最終軟件基本定型時,RAM用了300個字節左右,Flash更是用了不到4K。

當然,這并不能說明我水平有多高,只能說明這個產品實在太簡單了。

2

我本以為,這將是我有史以來用過的資源最少的一款MCU,不曾想,這個記錄很快就被我自己打破了。

項目啟動兩個月后,軟硬件開發工作就結束了,提前了原計劃整整一個月的時間。在隨后召開的項目會議上,我帶著憶苦思甜的幸福感,向領導匯報了代碼移植、調試工作,并表達了最初對MCU資源的忐忑之情。

透過厚厚的鏡片,領導滴溜溜地轉了一下眼睛,詢問了一下RAM和Flash的具體使用量,老實、不帶任何戒心的我如實地告知了領導具體數字。那一刻我還不知道,正是這種誠實讓我在接下來的一個月里度過了一段不堪回首、雞飛狗跳的日子。

從我這里得知RAM、Flash的具體使用量之后,領導歪了歪憨態可掬的脖子,把頭轉向張工,問起PIC16F1508的資源來。看著張工沉思的樣子,我心中火光電閃,瞬間‘領會了’領導的意圖。領導做硬件出身,MCU選型也是他平時主抓的業務工作之一,他無非是想知道pin to pin兼容、成本更低的PIC16F1508能不能替換更貴的PIC16F1509罷了。

不等張工發言,我已經在內心里盤算了一下:‘1508的Flash是4K字節,程序空間是夠用的,但是它的RAM是256字節,明顯不夠用。’一念至此,我舒了一口氣,給張工眨了眨眼睛,于是,張工如實地告知了領導1508的資源。

我本以為事情到此就結束了,卻不曾想,領導又把他那扎煞在硬硬的衣領里面的脖子朝我轉過來,向我交待了一個匪夷所思的任務:

把代碼改改,把RAM使用量降到256字節以下,用PIC16F1508能便宜一塊多吶!

timg (5).jpg

領導接著笑言:“項目合作方要求降成本,我都答應人家了,正好不知道從哪里下手呢!”

3

代碼基本定型,這時要精簡掉將近20%左右的RAM使用量,腫么辦?

筆者首先想到的是那些取值范圍有限的全局變量,這些變量之前都是用uint8_t類型定義的,在這種定義下,MCU會用一個8位的字節來存儲它。這對于一個實際上當成布爾量使用的變量來說絕對是一種浪費,顯然,用一個‘位’來存儲它更節約空間。還有那些取值范圍不超過7的,都可以用3位存儲,不超過15的,可以用4位存儲,以此類推。

具體實現方式也很簡單,像MCU的硬件寄存器定義一樣,定義一個位域形式的結構體,把這些變量以結構體中位域形式的成員變量的形式來表示。通過這番操作,筆者居然省掉了整整20來個字節的RAM空間。

當然這也不是沒有代價的,那些“干脆利落”的變量名稱不見了,結構體.成員變量形式的“麻煩啰嗦”的名稱倒是隨處可見,散布在源代碼各個角落,甚是扎眼。

革命尚未成功,同志仍需努力,要把RAM使用量降到256字節以下,還需要繼續精簡。我的目光在各個源文件之間流連不斷,內心不斷地做著權衡和取舍。我深深地知道:要省RAM,必須修改某些模塊的實現方式,而這必然要付出犧牲代碼閱讀性的代價。

主動絞殺閱讀上的美感,這種感覺實在是難受極了。

目光所及之處,正是定時器管理模塊的“軟件定時器結構體”,這里有個成員變量是“定時回調函數”,這是一個16位指針變量,指向回調函數首地址。定時器啟動時,把回調函數首地址賦給該變量,等計時滿時,定時器管理模塊會“自動”調用該回調函數,這是一種多么優美的設計!當然,優美的代價是每一個軟件定時器節點都需要安排兩個字節存儲該回調函數首地址,10個定時器節點就對應整整20個字節。

當斷不斷反受其亂,我懷著無比悲壯的心情修改了定時器管理模塊的設計,把這個成員變量刪掉,代之以一個表示定時超時的標志flag,這個flag用一個位變量表示即可,通過和軟件定時器結構體中臨近成員變量(正好也是一個位變量)的結合,這個flag實際上不會引入任何額外的存儲需求。在定時器管理模塊設計中,通過查詢超時標志flag,“手動”調用相應的回調函數,一樣可以滿足程序功能要求。

通過這種方式,我又節省了20個字節。目標越來越近了,我也越來越欲減乏術了。

4

這一天,距離256個字節的目標只剩下10個字節了,我默默地躺在床上,盯著頭頂的天花板,久久無法入眠。

這是最孤寂的時刻,在靜靜的午夜,宇宙向它的聆聽者展示著廣漠的荒涼。

我不禁想起了大劉在《三體》中寫過的智子工程-將一個9維空間的質子展開為2維,然后在這個展開后變得無比巨大的2維質子上蝕刻微觀集成電路。。。我要是能把RAM展開就好了!

RAM展開?還能展開到Flash里面去嗎?這時,‘RAM不夠,Flash來湊’的八字真言奇跡般地出現在我眼前,我隱約覺得哪里有些變量實際上只取一些固定值了,那么,把這些變量直接定義成常量,它就不消耗RAM空間了,轉而去消耗Flash空間了!對,明天就這么干。

果不其然,第二天,我就在遙控鑰匙的解析接收程序里找到了一個四字節的數組變量,它在實際運行中只取常量值。改掉它之后,距離目標只剩下6個字節了!

勝利在望,但是接下來的每一步都將無比艱難。為了完成領導安排的任務,我做好了重寫所有代碼的準備,拼了。

1557473596613040.jpg

然后,救星突然降臨了。領導過來詢問了RAM精簡的情況后,沉思片刻后,悠悠地說了一句:

算了,RAM空間必須得有20-30%的余量,要不以后功能升級怎么辦?

喜從天降,竟是這么令人猝不及防,我張著空洞洞的嘴巴,把沖到嗓子眼想罵人的話生生咽了下去,配合著領導,說了一句總結陳詞:

MCU資源受限,編程成了巨大的挑戰啊!

領導卻不置可否,優雅地一個轉身,留給我一個高大的背影,慢慢踱開了去。他的背影竟而越變越大,壓得我有些窘慌,似乎要擠出我藏在棉衣下的那個‘小’來!



關鍵詞: MCU 嵌入式

評論


相關推薦

技術專區

關閉
七星彩走势图综合版