在你的嵌入式項目中使用 MPU 可以為你節省大量的挫折、時間和金錢。 MPU對嵌入式開發人員的最大單一好處是它能夠在開發早期捕獲錯誤,盡早發現錯誤可顯著縮短開發時間,在項目后期修復代碼中的錯誤可以減少文檔和測試代碼所需的返工,另一方面,盡早修復錯誤將減少項目后期代碼中存在的錯誤數量,這將簡化識別和修復剩余錯誤的過程,因為同時出現多個錯誤的可能性較小,這有助于你保持更可預測的時間表并防止意外延遲。
MPU 如何實現這一點?最明顯的方法是保護所有與當前正在執行的代碼無關的數據。一個簡單的例子可以只用兩個 RTOS 任務 A 和 B 來構建。任務 A 和 B 不應相互交互,但存在一個錯誤,任務 A 可能會意外寫入任務 B 偶爾使用的某些數據,覆蓋此數據不影響任務 A 的正確運行。但是當任務 B 嘗試使用損壞的數據時,任務 B 可能會出現意外故障。如果沒有配置 MPU 來防止任務 A 寫入任務 B 的數據,這個錯誤可能需要嵌入式開發人員很長時間才能找到。如果錯誤很微妙或任務 B 很少使用該數據,則此問題將特別難以解決。然而,對于 MPU,錯誤的寫入操作會立即導致異常,從而讓你能夠確定導致錯誤的代碼行。
在某些架構上,MPU 甚至可以幫助你檢測 NULL 指針取消引用,因為你可以設置 MPU 區域以防止非特權代碼訪問 0x0 處的內存。
應用程序中設計良好的一組 MPU 區域可以明確保護重要的內存區域以防止出現特定問題。 一個很好的例子是通過將緩沖區放在 MPU 區域的末尾來防止緩沖區溢出。 你還可以將你的任務堆棧放置在任何非特權代碼無法訪問的區域。 如果這樣做,那么每個任務必須使用自己的 MPU 區域之一來明確授予自己對自己堆棧的訪問權限。 使用 MPU 迫使你真正考慮應用程序的結構,以便你在任務之間干凈地分離數據,從而產生更健壯和可維護的代碼庫。
什么時候不使用 MPU?
有兩種主要情況使嵌入式開發人員不會在處理器上使用 MPU;一個簡單的項目和一個性能關鍵的項目。第一個很簡單;一個非常簡單的應用程序可能無法從使用 MPU 所增加的復雜性中受益。無需設置涵蓋閃存、RAM 和外圍設備的 MPU 區域,你的閃爍演示可能就可以完成。
如果你需要處理器的每一滴性能,那么使用 MPU 的開銷可能會讓你大吃一驚。使用 MPU 的 FreeRTOS 端口中的任務上下文切換例程更長,因為每個任務都有多個 MPU 區域需要編程。當新任務被上下文切換時,RTOS 必須對每個任務 MPU 區域進行編程,并執行其通常的職責,例如堆疊使用過的寄存器。此外,由于內核代碼和數據受 MPU 保護,因此所有內核函數調用都必須受包裝函數保護。這個包裝函數只是在調用內核函數之前提升處理器的特權級別,然后恢復特權并返回。這不僅會增加運行代碼所需的時間,而且可能會增加任務所需的堆棧大小。任務的控制塊還必須在其 MPU 區域上存儲信息,并且在某些安全關鍵 RTOS(如 SAFERTOS)的情況下,也將存儲此數據的鏡像。
你還應該警惕,使用 MPU 可能很困難,有時甚至令人沮喪。嵌入式開發人員設計應用程序需要更多時間,因為必須為每個任務考慮 MPU 區域。這些區域中的錯誤,例如不正確的區域長度、權限或未正確鏈接應用程序的數據,可能會導致調試混亂。