在上一篇文章《Arm Cortex-M低功耗模式基本原理(Arm Cortex-M low-power mode fundamentals)》中,探討了在每種Arm Cortex-M處理器上可以找到的低功耗模式的基本原理,以及如何使用WFI和WFE指令讓處理器進入睡眠模式。實際上我們真正要瞭解的是,低功耗模式如何在真正的微控制器(MCU)上實現?這些模式如何影響嵌入式系統?在這篇文章中,將更詳細探討如何讓微控制器進入睡眠狀態,並看看到底能夠節省多少能耗。

低功耗模式實驗

探索低功耗模式的最佳方法是選擇一個微控制器並以各種低功耗模式實際執行該處理器。本文中,筆者決定翻出積塵已久的NXP Kinetis-L Freedom電路板,我曾經不僅用它進行過實驗,而且還應用於許多產品、應用和課程。無論對錯,我決定不僅要測量微控制器的能耗,還要測量整個開發板的能耗。微控制器通常是電路板上的耗能大戶之一,但測量整個系統的電流經常提醒我它並不是電路板上唯一的耗電元件。微控制器的最佳化長路迢迢,但其實它並不是唯一需要最佳化能耗的元件。

從基線測量開始

每當我努力最佳化一個產品的能耗時,首先會從基線能量測量開始。通常我會透過分析幾秒或幾分鐘內設備的電流消耗來瞭解應該從哪裡開始,在我的開發板實驗中,將Kinetis-L置於運作模式,無睡眠模式,所有周邊均運作並設置電路板定期切換LED。透過採用IAR嵌入式工作台的I-Jet除錯器,以及I-Scope,可以為該電路板配置一個簡單基線,即LED關閉時電流消耗大約為16.9mA,LED打開時大約為18.0mA,如圖1所示。顯然,從哪裡開始進行測量很重要,否則分析結果可能明顯偏離。

20190815TA31P1 圖1 開發板的電流測量,LED每秒切換一次。(資料來源:作者)

採用等待模式和深度睡眠模式最佳化能耗

節省能耗最快的方法是執行等待或深度睡眠模式。研究Kinetis-L處理器的資料表可以得出,等待模式的能耗在3V電壓下的電流介於3.7和5.0mA之間。在此模式下,CPU和周邊時脈被禁用,而快閃記憶體處於休眠模式,此時允許處理器在中斷時間範圍內(12~15個時脈週期)仍然可以被喚醒。等待模式易於實現,設置進入等待模式的程式碼如下所示:

void Sleep_Wait(void)

{

SCB_SCR &=~ SCB_SCR_SLEEPDEEP_MASK;

asm(“WFI”);

}

只需這兩行程式碼,開發板的電流消耗就從18.0mA降至15.9mA。電流消耗減少了11.6%。如果電路板由680mA電池供電,則該設備的電池壽命將從37.8小時變為42.8小時,兩行程式碼就可以將電池壽命延長五小時。

這些高階電源模式的好處在於可以輕鬆地再向前邁一步。可以使用以下程式碼將處理器置於深度睡眠等待模式,而不僅僅是等待模式:

void Sleep_Deep(void)

{

SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK;

asm(“WFI”);

}

我們所做的僅僅是調整了SCB_SCR寄存器中的1位元,就已經將最初的18mA電流消耗減少為14.8mA。電流消耗減少了17.8%。同樣,假設電路板由680mA電池供電,電池壽命現在已經從37.8小時增長為46小時,只需幾行程式碼就可以節省大量能耗,而這只是冰山一角。

利用Stop模式和VLLS模式實現微安級電流消耗

採用停止模式可以禁用核心和系統時脈,這有可能將微控制器電流消耗再進一步降低2mA。 你會發現,功耗模式越低,實現它所需的程式碼就越多,而喚醒系統恢復工作的程式碼就越複雜。使Kinetis-L進入停止模式的程式碼如下所示:

void Sleep_Stop(void)

{

volatile unsigned int dummyread = 0;

SMC_PMCTRL &=~ SMC_PMCTRL_STOPM_MASK;

SMC_PMCTRL |= SMC_PMCTRL_STOPM(0);

dummyread = SMC_PMCTRL;

Sleep_Deep();

}

請注意,停止模式透過電源管理控制寄存器控制,一旦狀態被設置,就會調用Sleep_Deep函數來完成電源模式的設置並執行WFI。

到目前為止,本文一直在談論1~2mA的微控制器能耗,現代微控制器將提供僅消耗μA甚至nA的電源模式。Kinetis-L處理器於2013年左右首次亮相,其超低漏電停止(VLLS)模式僅耗能135~496μA。初始化此電源模式的程式碼如下所示:

void Sleep_VLLS1(void)

{

volatile unsigned int dummyread = 0;

SMC_PMCTRL &=~ SMC_PMCTRL_STOPM_MASK;

SMC_PMCTRL |= SMC_PMCTRL_STOPM(0x4);

SMC_VLLSTRL = SMC_VLLSCTRL_LLSM(1);

dummyread = VLLS_CTRL;

Sleep_Deep();

}

講到這裡,你會發現微控制器已經幾乎不消耗任何能量了!

...完整閱讀請連結EE Times Taiwan網站