在許多嵌入式專案中,RAM 往往不是工程師一開始最擔心的資源。早期原型通常跑在評估板上都很順,測試用韌體隨著需求慢慢長大,記憶體用量看起來也「還算夠用」。
但現實終究會到來。
新增一個功能、診斷機制擴充、安全性更新引入新的 buffer,突然之間,RAM 用量不再只是安全邊際,而是直接成為開發瓶頸。一旦 RAM 成為限制條件,影響往往不只停留在軟體層面。
在嵌入式系統中,RAM 不夠用通常代表必須重新設計硬體、改選更大容量的 MCU,或是在專案後期重新驗證新的型號。這類變動會一路影響到整個組織,從採購、認證、製造到長期供應規劃。結果造成 BOM 成本上升、時程延誤,整體風險也隨之增加。
這也是為什麼 RAM 最佳化不只是技術問題,而是策略層級的考量。
為什麼 RAM 最佳化比以往任何時候更加重要?
與 Flash 不同,在低階與中階 MCU 上,RAM 的容量並不是線性增加的。一點點 RAM 需求的成長,往往就會被迫帶來:
升級到更高階的 MCU 系列
改用不同的封裝或腳位配置
額外的功耗增加
重新進行驗證與確認(qualification / validation)
對於長生命週期產品、感測節點、系統控制器或工業型閘道器而言,這類變更的成本往往非常高。
而讓這個問題在今天變得更嚴峻的,是 RAM 的價格與供應狀況,越來越受到嵌入式產業以外的全球市場因素影響。
來自 AI 系統與超大型資料中心的需求暴增,已經徹底改變了記憶體市場。AI 模型的訓練與部署需要大量高頻寬記憶體,迫使製造商優先投入高毛利產品,並重新分配產能。
因此:
一般商品型記憶體的製造吸引力下降
整體市場的供應配額趨於緊縮
價格壓力影響整個記憶體生態系
需要特別區分的是,這些變化對不同嵌入式架構的影響並不相同。以 MCU 為基礎的設計,多半使用晶片內建 RAM,其容量在晶片設計階段就已固定,較不直接受到外部記憶體市場影響;相對地,以 MPU 為核心的系統則仰賴外接 DDR 或 LPDDR,會更直接與其他商品型記憶體產品競爭相同的製造產能。
即使嵌入式系統本身不使用 AI 等級的記憶體,也無法完全置身事外。對於高出貨量產品來說,即便只是外部記憶體成本的小幅上漲,或供應可得性下降,都可能對 BOM、採購策略與產品長期可行性造成顯著影響。即便 MCU 受影響較間接,長期的記憶體生態系壓力,仍會逐步反映在價格、交期與架構選擇上。
主動管理 RAM 使用量的團隊,得到的價值遠不只是多出幾個 byte,而是設計彈性。他們可以在不更動硬體的情況下,承接功能成長、安全性更新與法規合規需求。
沉默的 RAM 消耗者:全域變數與靜態變數
在實際專案中,最常見的情況之一,就是全域變數與靜態變數不斷累積。一開始的出發點通常是好的:共用狀態、使用方便、存取速度快,但久而久之,它們就成了 RAM 裡的長期住戶。
由於全域與靜態物件在系統整個生命週期中都存在,它們會:
在系統啟動時就占用可用記憶體
增加初始化的負擔
掩蓋實際的執行期記憶體需求
在實務上,將變數從全域範圍移到函式內,通常不會帶來效能損失,卻能在函式結束後立即釋放 RAM。
透過 IAR 的 linker map file,這些長生命週期的配置非常容易被找出來。工程師不必再猜 RAM 用到哪裡,而是能清楚看到是哪個模組、哪個符號在消耗記憶體,並判斷是否真的需要永久配置。
資料型別:小決定,大影響
在許多嵌入式系統中,記憶體浪費往往不是來自一個大錯誤,而是成千上萬個小選擇累積而成。
在只需要 uint8_t 的地方使用 int,就是經典例子。單看一個變數差異不大,但放在陣列、結構、佇列與 stack 裡,很快就會累積成可觀的浪費。
uint8_t status;
uint16_t measurement;
選擇「最小且正確」的型別,可以:
降低 RAM 使用量
改善快取行為
往往同時提升效能並降低功耗
這在感測器密集的系統中特別重要,因為資料結構會被大量複製,任何低效率都會隨著系統複雜度被放大。
結構配置與 bitfield:隱藏的 padding 成本
即使是寫得很乾淨的程式碼,也可能因為結構 padding 與對齊(alignment)而浪費 RAM。
重新排列結構成員,並用 bitfield 來表示旗標,往往能大幅降低記憶體使用量,特別是在結構被大量實例化或放入陣列時。
typedef struct
{
uint16_t value;
uint8_t state;
uint8_t flags : 3;
} DeviceStatus;
這些最佳化在執行期幾乎感覺不到,但在 linker map file 中非常明顯,最終也會反映在 BOM 成本上。
讓常數待在該待的地方:Flash
一個出乎意料卻很常見的 RAM 浪費來源,是啟動時被複製進 RAM 的常數資料。字串、查表資料與設定資料,如果沒有妥善處理,很容易在不知不覺中吃掉大量記憶體。
透過一致性地使用 const,開發者可以確保資料留在 Flash 中,而不是佔用 RAM:
const uint16_t calibrationTable[128] = { /* Flash-resident */ };
在 IAR 工具鏈中,資料放置位置是明確且可預期的,這在受法規約束或安全關鍵的應用場景中特別重要,因為記憶體行為必須清楚被理解並文件化。
動態配置:彈性,但風險高
動態記憶體配置之所以吸引人,是因為看起來很彈性;但在嵌入式系統中,這份彈性往往代價不低:
長時間運作後產生記憶體碎裂
非決定性的配置失敗
難以除錯的 runtime 當機問題
對於需要連續運作數月甚至數年的系統來說,動態配置通常不值得承擔這些風險。
因此,許多團隊會用以下方式取代 heap:
靜態 buffer
固定大小的記憶體池
應用程式專用的配置器
這樣做的結果是記憶體行為可預期、測試更單純、系統可靠度提升,特別適合 RAM 邊際本來就很吃緊的情況。
Stack 使用量:最隱蔽的失敗模式
Stack overflow 是最難診斷的問題之一,往往只在特定條件下才會發生,例如排程與時序交錯造成的特殊情境。
大型區域變數、過深的呼叫鏈,或遞迴呼叫,都可能快速耗盡 stack,在 RTOS 系統中特別容易發生。
透過 IAR 的 stack 分析工具,開發者可以:
估算最壞情況下的 stack 使用量
合理配置各 task 的 stack 大小
避免在專案後期才出現、又難以重現的問題
編譯器與 linker 最佳化:不只是程式碼大小
編譯器的 size 最佳化(-Os)通常被認為只是省 Flash,但它其實也會直接影響 RAM 使用量:
減少暫存變數
降低 stack 壓力
減少需要初始化的資料
搭配 section garbage collection 與定期檢視 linker map file,可以避免軟體隨著演進,記憶體用量在不知不覺中膨脹。
RTOS 設定:只為實際使用的功能付出成本
RTOS kernel 功能強大,但預設設定通常偏保守。過大的 stack、未使用的功能與通用化設定,都可能吃掉大量 RAM。
逐一調整 RTOS 的設定檔與各個 task,往往就能釋放出足夠的記憶體,甚至完全避免硬體升級。
從 RAM 最佳化到 BOM 成本節省
RAM 最佳化真正的價值,不在於省下多少 byte,而在於多了多少選項。
主動管理 RAM 的團隊可以:
更長時間地維持在較小容量的 MCU
避免專案後期的硬體變更
降低供應鏈風險
在不犧牲功能的情況下降低 BOM 成本
透過 IAR 嵌入式開發平台,RAM 使用量變得可視、可預測、可管理,讓記憶體最佳化不再只是救火,而是一套可重複執行的工程流程。
總結
在嵌入式系統中,每一個 RAM byte 都有成本。有時體現在矽晶片上,有時則反映在時程、認證或供應鏈上。
在全球記憶體需求越來越被 AI 與資料中心主導的環境下,即使是「純」嵌入式系統,也無法不感受到這股壓力。
將 RAM 視為一級設計限制,並搭配合適的工具加以管理,嵌入式團隊就能打造出不僅效率高、也具備經濟韌性的系統。
接下來呢?
歡迎了解 IAR 如何協助最佳化你的嵌入式開發專案。透過互動式展示快速認識 IAR 平台,並進一步探索其進階功能與解決方案。