91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

處理器電源管理主要實(shí)現(xiàn)方式是什么?

lhl545545 ? 來源:RTThread物聯(lián)網(wǎng)操作系統(tǒng) ? 作者:RTThread物聯(lián)網(wǎng)操作 ? 2020-06-09 15:27 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

電源管理組件

嵌入式系統(tǒng)低功耗管理的目的在于滿足用戶對性能需求的前提下,盡可能降低系統(tǒng)能耗以延長設(shè)備待機(jī)時間。高性能與有限的電池能量在嵌入式系統(tǒng)中矛盾最為突出,硬件低功耗設(shè)計與軟件低功耗管理的聯(lián)合應(yīng)用成為解決矛盾的有效手段?,F(xiàn)在的各種 MCU 都或多或少的在低功耗方面提供了管理接口。比如對主控時鐘頻率的調(diào)整、工作電壓的改變、總線頻率的調(diào)整甚至關(guān)閉、外圍設(shè)備工作時鐘的關(guān)閉等。有了硬件上的支持,合理的軟件設(shè)計就成為節(jié)能的關(guān)鍵,一般可以把低功耗管理分為三個類別:

處理器電源管理主要實(shí)現(xiàn)方式:對 CPU 頻率的動態(tài)管理,以及系統(tǒng)空閑時對工作模式的調(diào)整。

設(shè)備電源管理主要實(shí)現(xiàn)方式:關(guān)閉個別閑置設(shè)備

系統(tǒng)平臺電源管理主要實(shí)現(xiàn)方式:針對特定系統(tǒng)平臺的非常見設(shè)備具體定制。

隨著物聯(lián)網(wǎng)IoT) 的興起,產(chǎn)品對功耗的需求越來越強(qiáng)烈。作為數(shù)據(jù)采集的傳感器節(jié)點(diǎn)通常需要在電池供電時長期工作,而作為聯(lián)網(wǎng)的 SOC 也需要有快速的響應(yīng)功能和較低的功耗。

在產(chǎn)品開發(fā)的起始階段,首先考慮是盡快完成產(chǎn)品的功能開發(fā)。在產(chǎn)品功能逐步完善之后,就需要加入電源管理 (Power Management,以下簡稱 PM) 功能。為了適應(yīng) IoT 的這種需求,RT-Thread 提供了電源管理組件。電源管理組件的理念是盡量透明,使得產(chǎn)品加入低功耗功能更加輕松。

PM 組件介紹

RT-Thread 的 PM 組件采用分層設(shè)計思想,分離架構(gòu)和芯片相關(guān)的部分,提取公共部分作為核心。在對上層提供通用的接口同時,也讓底層驅(qū)動對組件的適配變得更加簡單。

處理器電源管理主要實(shí)現(xiàn)方式是什么?

主要特點(diǎn)

RT-Thread PM 組件主要特點(diǎn)如下所示:

基于模式來管理功耗,空閑時動態(tài)調(diào)整工作模式,支持多個等級的休眠。

對應(yīng)用透明,組件在底層自動完成電源管理。

支持運(yùn)行模式下動態(tài)變頻,根據(jù)模式自動更新設(shè)備的頻率配置,確保在不同的運(yùn)行模式都可以正常工作。

支持設(shè)備電源管理,根據(jù)模式自動管理設(shè)備的掛起和恢復(fù),確保在不同的休眠模式下可以正確的掛起和恢復(fù)。

支持可選的休眠時間補(bǔ)償,讓依賴 OS Tick 的應(yīng)用可以透明使用。

向上層提供設(shè)備接口,如果打開了 devfs 組件,那么也可以通過文件系統(tǒng)接口訪問。

工作原理

低功耗的本質(zhì)是系統(tǒng)空閑時 CPU 停止工作,中斷或事件喚醒后繼續(xù)工作。在 RTOS 中,通常包含一個 IDLE 任務(wù),該任務(wù)的優(yōu)先級最低且一直保持就緒狀態(tài),當(dāng)高優(yōu)先級任務(wù)未就緒時,OS 執(zhí)行 IDLE 任務(wù)。一般地,未進(jìn)行低功耗處理時,CPU 在 IDLE 任務(wù)中循環(huán)執(zhí)行空指令。RT-Thread 的電源管理組件在 IDLE 任務(wù)中,通過對 CPU 、時鐘和設(shè)備等進(jìn)行管理,從而有效降低系統(tǒng)的功耗。

處理器電源管理主要實(shí)現(xiàn)方式是什么?

在上圖所示,當(dāng)高優(yōu)先級任務(wù)運(yùn)行結(jié)束或被掛起時,系統(tǒng)將進(jìn)入 IDLE 任務(wù)中。在 IDLE 任務(wù)執(zhí)行后,它將判斷系統(tǒng)是否可以進(jìn)入到休眠狀態(tài)(以節(jié)省功耗)。如果可以進(jìn)入休眠, 將根據(jù)芯片情況關(guān)閉部分硬件模塊,OS Tick 也非常有可能進(jìn)入暫停狀態(tài)。此時電源管理框架會根據(jù)系統(tǒng)定時器情況,計算出下一個超時時間點(diǎn),并設(shè)置低功耗定時器,讓設(shè)備能夠在這個時刻點(diǎn)喚醒,并進(jìn)行后續(xù)的工作。當(dāng)系統(tǒng)被(低功耗定時器中斷或其他喚醒中斷源)喚醒后,系統(tǒng)也需要知道睡眠時間長度是多少,并對OS Tick 進(jìn)行補(bǔ)償,讓系統(tǒng)的OS tick值調(diào)整為一個正確的值。

低功耗狀態(tài)和模式

RT-Thread PM 組件將系統(tǒng)劃分為兩種狀態(tài):運(yùn)行狀態(tài)(RUN)和休眠狀態(tài)(Sleep)。運(yùn)行狀態(tài)控制 CPU 的頻率,適用于變頻場景;休眠狀態(tài)根據(jù) SOC 特性實(shí)現(xiàn)休眠 CPU,以降低功耗。兩種狀態(tài)分別使用不同的 API 接口,獨(dú)立控制。

休眠狀態(tài)休眠狀態(tài)也就是通常意義上的低功耗狀態(tài),通過關(guān)閉外設(shè)、執(zhí)行 SOC 電源管理接口,降低系統(tǒng)功耗。休眠狀態(tài)又分為六個模式,呈現(xiàn)為金字塔的形式。隨著模式增加,功耗逐級遞減的特點(diǎn)。下面是休眠狀態(tài)下模式的定義,開發(fā)者可根據(jù)具體的 SOC 實(shí)現(xiàn)相應(yīng)的模式,但需要遵循功耗逐級降低的特點(diǎn)。

處理器電源管理主要實(shí)現(xiàn)方式是什么?

運(yùn)行狀態(tài)運(yùn)行狀態(tài)通常用于改變 CPU 的運(yùn)行頻率,獨(dú)立于休眠模式。當(dāng)前運(yùn)行狀態(tài)劃分了四個等級:高速、正常、中速、低速,如下:

處理器電源管理主要實(shí)現(xiàn)方式是什么?

PM組件的實(shí)現(xiàn)接口

在 RT-Thrad PM 組件中,外設(shè)或應(yīng)用通過投票機(jī)制對所需的功耗模式進(jìn)行投票,當(dāng)系統(tǒng)空閑時,根據(jù)投票數(shù)決策出合適的功耗模式,調(diào)用抽象接口,控制芯片進(jìn)入低功耗狀態(tài),從而降低系統(tǒng)功耗。當(dāng)未進(jìn)行進(jìn)行任何投票時,會以默認(rèn)模式進(jìn)入(通常為空閑模式)。

pm組件的控制塊:

static struct rt_pm _pm;

API接口:

請求休眠模式

void rt_pm_request(uint8_t sleep_mode);

sleep_mode 取以下枚舉值:

enum { /* sleep modes */ PM_SLEEP_MODE_NONE = 0, /* 活躍狀態(tài) */ PM_SLEEP_MODE_IDLE, /* 空閑模式(默認(rèn)) */ PM_SLEEP_MODE_LIGHT, /* 輕度睡眠模式 */ PM_SLEEP_MODE_DEEP, /* 深度睡眠模式 */ PM_SLEEP_MODE_STANDBY, /* 待機(jī)模式 */ PM_SLEEP_MODE_SHUTDOWN, /* 關(guān)斷模式 */ PM_SLEEP_MODE_MAX, };

調(diào)用該函數(shù)會將對應(yīng)的模式計數(shù)加1,并鎖住該模式。此時如果請求更低級別的功耗模式,將無法進(jìn)入,只有釋放(解鎖)先前請求的模式后,系統(tǒng)才能進(jìn)入更低的模式;向更高的功耗模式請求則不受此影響。該函數(shù)需要和 rt_pm_release 配合使用,用于對某一階段或過程進(jìn)行保護(hù)。下面是具體代碼實(shí)現(xiàn):

void rt_pm_request(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; if (_pm_init_flag == 0) return; if (mode 》 (PM_SLEEP_MODE_MAX - 1)) return; level = rt_hw_interrupt_disable(); pm = &_pm; if (pm-》modes[mode] 《 255) pm-》modes[mode] ++;//將對應(yīng)的模式計數(shù)加1 rt_hw_interrupt_enable(level); }

釋放休眠模式

void rt_pm_release(uint8_t sleep_mode);

調(diào)用該函數(shù)會將對應(yīng)的模式計數(shù)減1,配合 rt_pm_request 使用,釋放先前請求的模式。下面是具體代碼實(shí)現(xiàn):

void rt_pm_release(rt_uint8_t mode) { rt_ubase_t level; struct rt_pm *pm; if (_pm_init_flag == 0) return; if (mode 》 (PM_SLEEP_MODE_MAX - 1)) return; level = rt_hw_interrupt_disable(); pm = &_pm; if (pm-》modes[mode] 》 0) pm-》modes[mode] --;//將對應(yīng)的模式計數(shù)減1 rt_hw_interrupt_enable(level); }

特殊情況下,比如某個階段并不允許系統(tǒng)進(jìn)入更低的功耗模式,此時可以通過 rt_pm_request 和 rt_pm_release 對該過程進(jìn)行保護(hù)。如 I2C 讀取數(shù)據(jù)期間,不允許進(jìn)入深度睡眠模式(可能會導(dǎo)致外設(shè)停止工作),因此可以做如下處理:

/* 請求輕度睡眠模式(I2C外設(shè)該模式下正常工作) */ rt_pm_request(PM_SLEEP_MODE_LIGHT); /* 讀取數(shù)據(jù)過程 */ /* 釋放該模式 */ rt_pm_release(PM_SLEEP_MODE_LIGHT);

設(shè)置運(yùn)行模式

int rt_pm_run_enter(uint8_t run_mode);

run_mode 可以取以下枚舉值:

enum { /* run modes*/ PM_RUN_MODE_HIGH_SPEED = 0, /* 高速 */ PM_RUN_MODE_NORMAL_SPEED, /* 正常(默認(rèn)) */ PM_RUN_MODE_MEDIUM_SPEED, /* 中速 */ PM_RUN_MODE_LOW_SPEED, /* 低速 */ PM_RUN_MODE_MAX, };

調(diào)用該函數(shù)改變 CPU 的運(yùn)行頻率,從而降低運(yùn)行時的功耗。此函數(shù)只提供級別,具體的 CPU 頻率應(yīng)在移植階段視實(shí)際情況而定。

下面是具體代碼實(shí)現(xiàn):

int rt_pm_run_enter(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; if (_pm_init_flag == 0) return -RT_EIO; if (mode 》 PM_RUN_MODE_MAX) return -RT_EINVAL; level = rt_hw_interrupt_disable(); pm = &_pm; if (mode 《 pm-》run_mode) { /* change system runing mode */ pm-》ops-》run(pm, mode); /* changer device frequency */ _pm_device_frequency_change(mode); } else { pm-》flags |= RT_PM_FREQUENCY_PENDING; } pm-》run_mode = mode; rt_hw_interrupt_enable(level); return RT_EOK; }

設(shè)置進(jìn)入/退出休眠模式的回調(diào)通知

void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), void *data);

event 為以下兩個枚舉值,分別標(biāo)識進(jìn)入/退出休眠模式。

enum { RT_PM_ENTER_SLEEP = 0, /* 進(jìn)入休眠模式 */ RT_PM_EXIT_SLEEP, /* 退出休眠模式 */ };

在應(yīng)用進(jìn)入/退出休眠模式會觸發(fā)回調(diào)通知。下面是具體代碼實(shí)現(xiàn):

void rt_pm_notify_set(void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data), void *data) { _pm_notify.notify = notify; _pm_notify.data = data; }

注冊PM設(shè)備

void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops)

與應(yīng)用不同,某些外設(shè)可能在進(jìn)入低功耗狀態(tài)時執(zhí)行特定操作,退出低功耗時采取措施恢復(fù),此時可以通過注冊PM設(shè)備來實(shí)現(xiàn)。通過注冊 PM 設(shè)備,在進(jìn)入低功耗狀態(tài)之前,會觸發(fā)注冊設(shè)備的 suspend 回調(diào),開發(fā)者可在回調(diào)里執(zhí)行自己的操作;類似地,從低功耗狀態(tài)退出時,也會觸發(fā) resume 回調(diào)。運(yùn)行模式下的頻率改變同樣會觸發(fā)設(shè)備的 frequency_change 回調(diào)。下面是具體代碼實(shí)現(xiàn):

void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops) { rt_base_t level; struct rt_device_pm *device_pm; RT_DEBUG_NOT_IN_INTERRUPT; level = rt_hw_interrupt_disable(); device_pm = (struct rt_device_pm *)RT_KERNEL_REALLOC(_pm.device_pm, (_pm.device_pm_number + 1) * sizeof(struct rt_device_pm)); if (device_pm != RT_NULL) { _pm.device_pm = device_pm; _pm.device_pm[_pm.device_pm_number].device = device; _pm.device_pm[_pm.device_pm_number].ops = ops; _pm.device_pm_number += 1; } rt_hw_interrupt_enable(level); }

設(shè)置進(jìn)入/退出休眠模式的回調(diào)通知和注冊為設(shè)備的回調(diào)通知流程:

處理器電源管理主要實(shí)現(xiàn)方式是什么?

首先應(yīng)用設(shè)置進(jìn)出休眠狀態(tài)的回調(diào)函數(shù),然后調(diào)用 rt_pm_request 請求休眠模式,觸發(fā)休眠操作;PM 組件在系統(tǒng)空閑時檢查休眠模式計數(shù),根據(jù)投票數(shù)給出推薦的模式;接著 PM 組件調(diào)用 notfiy 通知應(yīng)用,告知即將進(jìn)入休眠模式;然后對注冊的 PM 設(shè)備執(zhí)行掛起操作,返回 OK 后執(zhí)行 SOC 實(shí)現(xiàn)的的休眠模式,系統(tǒng)進(jìn)入休眠狀態(tài)(如果使能時間補(bǔ)償,休眠之前會先啟動低功耗定時器)。此時 CPU 停止工作,等待事件或者中斷喚醒。當(dāng)系統(tǒng)被喚醒后,由于全局中斷為關(guān)閉狀態(tài),系統(tǒng)繼續(xù)從該處執(zhí)行,獲取睡眠時間補(bǔ)償系統(tǒng)的心跳,依次喚醒設(shè)備,通知應(yīng)用從休眠模式退出。如此一個周期執(zhí)行完畢,退出,等待系統(tǒng)下次空閑。模式的切換代碼實(shí)現(xiàn):當(dāng)任務(wù)進(jìn)入到空閑線程,最終是調(diào)用此函數(shù)進(jìn)入低功耗和喚醒的

static void _pm_change_sleep_mode(struct rt_pm *pm, rt_uint8_t mode) { rt_tick_t timeout_tick, delta_tick; rt_base_t level; int ret = RT_EOK; if (mode == PM_SLEEP_MODE_NONE) { pm-》sleep_mode = mode; pm-》ops-》sleep(pm, PM_SLEEP_MODE_NONE); } else { level = rt_pm_enter_critical(mode); /* Notify app will enter sleep mode */ if (_pm_notify.notify) _pm_notify.notify(RT_PM_ENTER_SLEEP, mode, _pm_notify.data); /* Suspend all peripheral device */ ret = _pm_device_suspend(mode); if (ret != RT_EOK) { _pm_device_resume(mode); if (_pm_notify.notify) _pm_notify.notify(RT_PM_EXIT_SLEEP, mode, _pm_notify.data); rt_pm_exit_critical(level, mode); return; } /* Tickless*/ if (pm-》timer_mask & (0x01 《《 mode)) { timeout_tick = rt_timer_next_timeout_tick(); if (timeout_tick == RT_TICK_MAX) { if (pm-》ops-》timer_start) { pm-》ops-》timer_start(pm, RT_TICK_MAX); } } else { timeout_tick = timeout_tick - rt_tick_get(); if (timeout_tick 《 RT_PM_TICKLESS_THRESH) { mode = PM_SLEEP_MODE_IDLE; } else { pm-》ops-》timer_start(pm, timeout_tick); } } } /* enter lower power state */ pm-》ops-》sleep(pm, mode); /* wake up from lower power state*/ if (pm-》timer_mask & (0x01 《《 mode)) { delta_tick = pm-》ops-》timer_get_tick(pm); pm-》ops-》timer_stop(pm); if (delta_tick) { rt_tick_set(rt_tick_get() + delta_tick); rt_timer_check(); } } /* resume all device */ _pm_device_resume(pm-》sleep_mode); if (_pm_notify.notify) _pm_notify.notify(RT_PM_EXIT_SLEEP, mode, _pm_notify.data); rt_pm_exit_critical(level, mode); } }

移植的實(shí)現(xiàn)原理

RT-Thread 低功耗管理系統(tǒng)從設(shè)計上分離運(yùn)行模式和休眠模式,獨(dú)立管理,運(yùn)行模式用于變頻和變電壓,休眠調(diào)用芯片的休眠特性。對于多數(shù)芯片和開發(fā)來說,可能并不需要考慮變頻和變電壓,僅需關(guān)注休眠模式。底層功能的實(shí)現(xiàn)已經(jīng)有Sunwancn大神對STM32做了全系列的適配,以下是底層實(shí)現(xiàn)原理,用戶也可以自行根據(jù)自身情況對底層進(jìn)行裁剪或增強(qiáng)。(注意: 驅(qū)動可能有更新,移植請到gitee下載最新pm驅(qū)動。地址在pm-ports-stm32-new 分支:https://gitee.com/sunwancn/rt-thread/tree/pm-ports-stm32-new)

PM 組件的底層功能都是通過struct rt_pm_ops結(jié)構(gòu)體里的函數(shù)完成:

/** * low power mode operations */ struct rt_pm_ops { void (*sleep)(struct rt_pm *pm, uint8_t mode); void (*run)(struct rt_pm *pm, uint8_t mode); void (*timer_start)(struct rt_pm *pm, rt_uint32_t timeout); void (*timer_stop)(struct rt_pm *pm); rt_tick_t (*timer_get_tick)(struct rt_pm *pm); };

移植休眠模式移植休眠模式僅需關(guān)注 sleep 接口,下面是具體的實(shí)現(xiàn):

void stm32_sleep(struct rt_pm *pm, rt_uint8_t mode) { switch (mode) { case PM_SLEEP_MODE_NONE: break; case PM_SLEEP_MODE_IDLE: if (pm-》run_mode == PM_RUN_MODE_LOW_SPEED) { /* Enter LP SLEEP Mode, Enable low-power regulator */ HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI); } else { /* Enter SLEEP Mode, Main regulator is ON */ HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); } break; case PM_SLEEP_MODE_LIGHT: if (pm-》run_mode == PM_RUN_MODE_LOW_SPEED) { __HAL_FLASH_SLEEP_POWERDOWN_ENABLE(); /* Enter LP SLEEP Mode, Enable low-power regulator */ HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI); __HAL_FLASH_SLEEP_POWERDOWN_DISABLE(); } else { /* Enter SLEEP Mode, Main regulator is ON */ HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); } break; case PM_SLEEP_MODE_DEEP: /* Disable SysTick interrupt */ CLEAR_BIT(SysTick-》CTRL, (rt_uint32_t)SysTick_CTRL_TICKINT_Msk); if (pm-》run_mode == PM_RUN_MODE_LOW_SPEED) { /* Clear LPR bit to back the normal run mode */ CLEAR_BIT(PWR-》CR1, PWR_CR1_LPR); /* Enter STOP 2 mode */ HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI); /* Set Regulator parameter to lowpower run mode */ SET_BIT(PWR-》CR1, PWR_CR1_LPR); } else { /* Enter STOP 2 mode */ HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI); } /* Enable SysTick interrupt */ SET_BIT(SysTick-》CTRL, (rt_uint32_t)SysTick_CTRL_TICKINT_Msk); /* Re-configure the system clock */ systemclock_reconfig(pm-》run_mode); break; case PM_SLEEP_MODE_STANDBY: __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); /* Enter STANDBY mode */ HAL_PWR_EnterSTANDBYMode(); break; case PM_SLEEP_MODE_SHUTDOWN: __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); /* Enter SHUTDOWNN mode */ HAL_PWREx_EnterSHUTDOWNMode(); break; default: RT_ASSERT(0); break; } }

移植時間補(bǔ)償接口某些情況下,我們可能需要系統(tǒng)在空閑時進(jìn)入 Stop 模式,以達(dá)到更低的降功耗效果。根據(jù)手冊可知,Stop 2 模式會關(guān)閉系統(tǒng)時鐘,當(dāng)前的 OS Tick 基于內(nèi)核的 Systick 定時器。那么在系統(tǒng)時鐘停止后,OS Tick 也會停止,對于某些依賴 OS Tick 的應(yīng)用,在進(jìn)入 Stop 2 模式,又被中斷喚醒后,就會出現(xiàn)問題,因此需要在系統(tǒng)喚醒后,對 OS Tick 進(jìn)行補(bǔ)償。Stop 2 模式下,絕大多數(shù)外設(shè)都停止工作,僅低功耗定時器 1(LP_TIM1)和RTC,選擇 LSI 作為時鐘源后,仍然能正常運(yùn)行,所以可以選擇 LP_TIM1 或者RTC 作為 Stop 2 模式的時間補(bǔ)償定時器。

休眠的時間補(bǔ)償需要實(shí)現(xiàn)三個接口,分別用于啟動低功耗定時器、停止定時器、喚醒后獲取休眠的 Tick,下面是具體的實(shí)現(xiàn):

static void stm32_pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout) { RT_ASSERT(pm != RT_NULL); RT_ASSERT(timeout 》 0); if (timeout != RT_TICK_MAX) { /* Convert OS Tick to PM timer timeout value */ timeout = stm32_pm_tick_from_os_tick(timeout); if (timeout 》 stm32_pmtim_get_tick_max()) { timeout = stm32_pmtim_get_tick_max(); } /* Enter PM_TIMER_MODE */ stm32_pmtim_start(timeout); } }

static void stm32_pm_timer_stop(struct rt_pm *pm) { RT_ASSERT(pm != RT_NULL); /* Reset PM timer status */ stm32_pmtim_stop(); }

static rt_tick_t stm32_pm_timer_get_tick(struct rt_pm *pm) { rt_uint32_t timer_tick; RT_ASSERT(pm != RT_NULL); timer_tick = stm32_pmtim_get_current_tick(); return stm32_os_tick_from_pm_tick(timer_tick); }

休眠時間補(bǔ)償?shù)囊浦蚕鄬Σ⒉粡?fù)雜,根據(jù) Tick 配置低功耗定時器超時,喚醒后獲取實(shí)際休眠時間并轉(zhuǎn)換為OS Tick,告知 PM 組件即可。

移植運(yùn)行模式移植休眠模式僅需關(guān)注 run接口,下面是具體的實(shí)現(xiàn):

void stm32_run(struct rt_pm *pm, rt_uint8_t mode) { static rt_uint32_t last_mode; static char *run_str[] = PM_RUN_MODE_NAMES; struct rcc_conf_struct sconf = _rcc_conf[mode]; if (mode == last_mode) return; if (stm32_run_freq[mode][0] != stm32_run_freq[last_mode][0]) { if (_rcc_conf[last_mode].low_pow_run_en && !sconf.low_pow_run_en) { /* Disable the Low-power Run mode */ HAL_PWREx_DisableLowPowerRunMode(); } systemclock_msi_on(last_mode); if (mode 《 last_mode) { /* Frequency increase */ HAL_PWREx_ControlVoltageScaling(sconf.volt_scale); _set_sysclock[mode](); } else { /* Frequency reduce */ _set_sysclock[mode](); HAL_PWREx_ControlVoltageScaling(sconf.volt_scale); } if (sconf.volt_scale == PWR_REGULATOR_VOLTAGE_SCALE2 || _osc_conf.osc_type == RCC_OSCILLATORTYPE_MSI) { /* Configure the wake up from stop clock to MSI */ __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); } else { /* Configure the wake up from stop clock to HSI */ __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI); } if (sconf.low_pow_run_en) { /* Enable the Low-power Run mode */ HAL_PWREx_EnableLowPowerRunMode(); } systemclock_msi_off(mode); #if defined(RT_USING_SERIAL) /* Re-Configure the UARTs */ uart_console_reconfig(); #endif /* Re-Configure the Systick time */ HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / RT_TICK_PER_SECOND); /* Re-Configure the Systick */ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); } last_mode = mode; rt_kprintf(“switch to %s mode, frequency = %d %sHz ”, run_str[mode], stm32_run_freq[mode][0], (stm32_run_freq[mode][1] == 1) ? “M” : “K”); if ((stm32_run_freq[mode][0] / stm32_run_freq[mode][1]) 》 OSC_CONF_SYS_FREQ_MAX) rt_kprintf(“warning: The frequency has over than %d MHz ”, OSC_CONF_SYS_FREQ_MAX); }

自定義運(yùn)行級別時鐘樹配置函數(shù)PM 組件驅(qū)動在給定運(yùn)行頻率時,已經(jīng)盡量自動最優(yōu)化配置時鐘樹,但有時外設(shè)時鐘還是沒有達(dá)到自己想要的頻率,這時可以自己配置時鐘樹,在 board.c 添加以下單個或所有函數(shù),代碼可參考 SystemClock_Config() 函數(shù):

rt_uint16_t stm32_run_freq[PM_RUN_MODE_MAX][2] = { /* The actual frequency is 1/divisor MHz, divisor = {1, 1000} */ /* {sysclk frequency, divisor} */ {/* 配置高頻運(yùn)行時的時鐘 */, /* 分頻系數(shù) */}, /* High speed */ {/* 配置普通運(yùn)行時的時鐘 */, /* 分頻系數(shù) */}, /* Normal speed */ {/* 配置中低運(yùn)行時的時鐘 */, /* 分頻系數(shù) */}, /* Medium speed */ {/* 配置低頻運(yùn)行時的時鐘 */, /* 分頻系數(shù) */}, /* Low speed, MSI clock 2.0 MHz */ }; void stm32_systemclock_high(void) { /* 添加代碼,配置高頻運(yùn)行時的時鐘樹 */ } void stm32_systemclock_normal(void) { /* 添加代碼,配置普通速度運(yùn)行時的時鐘樹 */ } void stm32_systemclock_medium(void) { /* 添加代碼,配置中低頻運(yùn)行時的時鐘樹 */ } void stm32_systemclock_low(void) { /* 添加代碼,配置低頻運(yùn)行時的時鐘樹 */ }

當(dāng)?shù)退俚念l率小于2MHz時,要注意以下2點(diǎn):

串口波特率如果設(shè)置過高,將不能正常通信

在時鐘頻率很低時,要適當(dāng)減小 RT_TICK_PER_SECOND 值,不然由于 OS_tick 過短,某些線程將不能完成任務(wù),從而不能進(jìn)入低功耗模式

初始化PM組件注意:休眠模式的時間補(bǔ)償需要在初始化階段通過設(shè)置 timer_mask 的對應(yīng)模式的 bit 控制開啟。例如需要開啟 Deep Sleep 模式下的時間補(bǔ)償,在實(shí)現(xiàn) timer 相關(guān)的 ops 接口后,初始化時設(shè)置相應(yīng)的bit:

int drv_pm_hw_init(void) { static const struct rt_pm_ops _ops = { stm32_sleep, stm32_run, stm32_pm_timer_start, stm32_pm_timer_stop, stm32_pm_timer_get_tick }; rt_uint8_t timer_mask = 0; /* Enable Power Clock */ __HAL_RCC_PWR_CLK_ENABLE(); /* initialize timer mask */ timer_mask = 1UL 《《 PM_SLEEP_MODE_DEEP; /* initialize system pm module */ rt_system_pm_init(&_ops, timer_mask, RT_NULL); return 0; } INIT_BOARD_EXPORT(drv_pm_hw_init);

void rt_system_pm_init(const struct rt_pm_ops *ops, rt_uint8_t timer_mask, void *user_data) { struct rt_device *device; struct rt_pm *pm; pm = &_pm; device = &(_pm.parent); device-》type = RT_Device_Class_PM; device-》rx_indicate = RT_NULL; device-》tx_complete = RT_NULL; #ifdef RT_USING_DEVICE_OPS device-》ops = &pm_ops; #else device-》init = RT_NULL; device-》open = RT_NULL; device-》close = RT_NULL; device-》read = _rt_pm_device_read; device-》write = _rt_pm_device_write; device-》control = _rt_pm_device_control; #endif device-》user_data = user_data; /* register PM device to the system */ rt_device_register(device, “pm”, RT_DEVICE_FLAG_RDWR); rt_memset(pm-》modes, 0, sizeof(pm-》modes)); pm-》sleep_mode = _pm_default_sleep; pm-》run_mode = RT_PM_DEFAULT_RUN_MODE; pm-》timer_mask = timer_mask; pm-》ops = ops; pm-》device_pm = RT_NULL; pm-》device_pm_number = 0; _pm_init_flag = 1; }

STM32L4 移植 PM

STM32L4 的低功耗模式簡介:

STM32L4系列 是 ST 公司推出的一款超低功耗的 Crotex-M4 內(nèi)核的 MCU,支持多個電源管理模式,其中最低功耗 Shutdown 模式下,待機(jī)電流僅 30 nA。ST 公司 把 L4系列 的電管管理分為很多種,但各個模式的并非功耗逐級遞減的特點(diǎn),下面是各個模式之間的狀態(tài)轉(zhuǎn)換圖:

處理器電源管理主要實(shí)現(xiàn)方式是什么?

盡管 STM32L4系列 的低功耗模式很多,但本質(zhì)上并不復(fù)雜,理解它的原理有助于我們移植驅(qū)動,同時更好的在產(chǎn)品中選擇合適的模式。最終決定 STM32L4系列 系統(tǒng)功耗的主要是三個因素:穩(wěn)壓器(voltage regulator)、CPU 工作頻率、芯片自身低功耗的處理,下面分別對三個因素進(jìn)行闡述。

穩(wěn)壓器L4 使用兩個嵌入式線性穩(wěn)壓器為所有數(shù)字電路、待機(jī)電路以及備份時鐘域供電,分別是主穩(wěn)壓器(main regulator,下文簡稱 MR)和低功耗穩(wěn)壓器(low-power regulator,下文簡稱 LPR)。穩(wěn)壓器在復(fù)位后處于使能狀態(tài),根據(jù)應(yīng)用模式,選擇不同的穩(wěn)壓器對 Vcore 域供電。其中,MR 的輸出電壓可以由軟件配置為不同的范圍(Range 1 和 Rnage 2)。穩(wěn)壓器應(yīng)用場合

穩(wěn)壓器應(yīng)用場合

MR(Range 1)Vcore = 1.2V,用于運(yùn)行模式、睡眠模式和停止模式0,MR 未 Vcore 域提供全功率

MR(Range 2)Vcore = 1.0V,使用的場景同上

LPR用于低功耗運(yùn)行模式、低功耗休眠模式、停止模式 1、停止模式2

OFFStandby 和 Shutdown 模式下,MR 和 LPR 都被關(guān)閉

CPU 工作頻率通過降低 CPU 的主頻達(dá)到降低功耗的目的:MR 工作在 Range 1 正常模式時,SYSCLK 最高可以工作在 80M;MR 工作在 Range 2 時,SYSCLK 最高不能超過 26 M;低功耗運(yùn)行模式和低功耗休眠模式,即 Vcore 域由 LPR 供電,SYSCLK 必須小于 2M。

芯片本身的低功耗處理芯片本身定義了一系列的休眠模式,如 Sleeep、Stop、Standby 和 Shutdown,前面的四種模式功耗逐漸降低,實(shí)質(zhì)是芯片內(nèi)部通過關(guān)閉外設(shè)和時鐘來實(shí)現(xiàn)。

配置工程

配置 PM 組件:

配置內(nèi)核選項(xiàng):使用 PM 組件需要更大的 IDLE 線程的棧,這里使用了1024 字節(jié)

在空閑線程中會調(diào)用rt_system_power_manager接口來進(jìn)入低功耗模式:

/** * This function will enter corresponding power mode. */ void rt_system_power_manager(void) { rt_uint8_t mode; if (_pm_init_flag == 0) return; /* CPU frequency scaling according to the runing mode settings */ _pm_frequency_scaling(&_pm); /* Low Power Mode Processing */ mode = _pm_select_sleep_mode(&_pm); _pm_change_sleep_mode(&_pm, mode); }

保存后,可以看到pm.c已經(jīng)被添加到了工程:

處理器電源管理主要實(shí)現(xiàn)方式是什么?

然后添加PM組件的設(shè)備驅(qū)動,驅(qū)動的最新地址:pm-ports-stm32-new 分支:https://gitee.com/sunwancn/rt-thread/tree/pm-ports-stm32-new注意: 目前所使用的驅(qū)動不是最新版本,移植請到gitee下載最新pm驅(qū)動。

從 t-threadspstm32librariesHAL_Drivers,拷貝如下四個文件到工程的drivers文件夾下:

本項(xiàng)目選擇的是使用RTC作為STOP后的時間補(bǔ)償,所以需要打開rtc設(shè)備和所使用的宏:

處理器電源管理主要實(shí)現(xiàn)方式是什么?

注: 如果沒有使用RTT的自身的RTC函數(shù)的話,前面2個宏可以不要。
責(zé)任編輯:pj

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 電源
    +關(guān)注

    關(guān)注

    185

    文章

    18910

    瀏覽量

    264040
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    20296

    瀏覽量

    253467
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    深入剖析 MAX8893A/MAX8893B/MAX8893C μPMICs:為多媒體應(yīng)用處理器提供高效電源管理

    深入剖析 MAX8893A/MAX8893B/MAX8893C μPMICs:為多媒體應(yīng)用處理器提供高效電源管理 在當(dāng)今的電子設(shè)備中,電源管理
    的頭像 發(fā)表于 03-16 11:40 ?121次閱讀

    NXP PF3000:助力i.MX處理器的高效電源管理方案

    NXP PF3000:助力i.MX處理器的高效電源管理方案 在電子設(shè)備的設(shè)計中,電源管理是至關(guān)重要的一環(huán)。一個優(yōu)秀的
    的頭像 發(fā)表于 03-15 17:05 ?475次閱讀

    探索NXP PF3001:為i.MX處理器量身定制的電源管理解決方案

    電源管理集成電路(PMIC),專為NXP i.MX 7和i.MX 6 SoloLite/SoloX/UltraLite應(yīng)用處理器設(shè)計,為多種應(yīng)用場景提供了強(qiáng)大的電源支持。作為電子工程師
    的頭像 發(fā)表于 03-11 17:10 ?515次閱讀

    STPMIC1:高度集成的微處理器電源管理IC

    STPMIC1:高度集成的微處理器電源管理IC 在當(dāng)今的電子設(shè)備設(shè)計中,電源管理是至關(guān)重要的一環(huán)。一款優(yōu)秀的
    的頭像 發(fā)表于 02-28 15:50 ?144次閱讀

    NXP PF3001電源管理集成電路:為i.MX處理器打造的完美搭檔

    NXP PF3001電源管理集成電路:為i.MX處理器打造的完美搭檔 在電子設(shè)備的設(shè)計中,電源管理是至關(guān)重要的一環(huán)。一個優(yōu)秀的
    的頭像 發(fā)表于 02-28 15:15 ?235次閱讀

    探索ADM6384:微處理器電源監(jiān)控的得力助手

    電路——ADM6384。 文件下載: ADM6384.pdf 一、ADM6384概述 ADM6384是一款用于基于微處理器系統(tǒng)的監(jiān)控電路,主要功能是監(jiān)測電源電壓水平。當(dāng)電源電壓上升到預(yù)
    的頭像 發(fā)表于 02-27 10:55 ?185次閱讀

    MAX8620Y:便攜式設(shè)備微處理器或DSP的理想μPMIC

    MAX8620Y:便攜式設(shè)備微處理器或DSP的理想μPMIC 在便攜式設(shè)備的設(shè)計中,電源管理是一個關(guān)鍵環(huán)節(jié)。今天我們來探討一款專為便攜式設(shè)備中的低電壓微處理器或DSP供電的
    的頭像 發(fā)表于 02-05 16:15 ?336次閱讀

    深入剖析PCA9452:i.MX 93應(yīng)用處理器的理想電源管理方案

    深入剖析PCA9452:i.MX 93應(yīng)用處理器的理想電源管理方案 在汽車電子應(yīng)用的浪潮中,電源管理集成電路(PMIC)的性能直接影響著整個
    的頭像 發(fā)表于 12-24 14:45 ?404次閱讀

    NICE接口和協(xié)處理器之間怎樣實(shí)現(xiàn)通信?

    NICE接口和協(xié)處理器之間怎樣實(shí)現(xiàn)通信
    發(fā)表于 11-05 12:42

    利用Verdi調(diào)試協(xié)處理器實(shí)現(xiàn)步驟

    本次給大家介紹的是利用Verdi調(diào)試協(xié)處理器實(shí)現(xiàn)步驟。 有時為了觀察協(xié)處理器運(yùn)行情況,需要查看協(xié)處理器接口的信號波形,此時可以用Verdi來查看主
    發(fā)表于 10-30 08:26

    基于E203 NICE協(xié)處理器擴(kuò)展指令

    1、實(shí)現(xiàn)功能 基于官方提供的demo nice的硬件代碼,設(shè)計一個基于e203 nice協(xié)處理的加法器。 2NICE協(xié)處理器理論學(xué)習(xí) nice協(xié)處理器的作用
    發(fā)表于 10-21 14:35

    基于E203 NICE協(xié)處理器擴(kuò)展指令2.0

    實(shí)現(xiàn)功能:基于官方提供的demo nice的硬件代碼,設(shè)計一個基于e203 nice協(xié)處理的加法器。 NICE協(xié)處理器理論學(xué)習(xí) nice協(xié)處理器的作用
    發(fā)表于 10-21 10:39

    TPS650830 用于 Skylake 處理器的可編程中間輸入電壓范圍電源管理IC數(shù)據(jù)手冊

    The TPS650830 是專為最新 Intel 處理器設(shè)計的單芯片解決方案電源管理 IC 面向具有 NVDC 或非 NVDC 電源架構(gòu)的平板電腦、超極本和筆記本電腦,使用 2S、3
    的頭像 發(fā)表于 04-26 14:42 ?805次閱讀
    TPS650830 用于 Skylake <b class='flag-5'>處理器</b>的可編程中間輸入電壓范圍<b class='flag-5'>電源</b><b class='flag-5'>管理</b>IC數(shù)據(jù)手冊

    TPS659037 用于 ARM Cortex A15 處理器電源管理 IC (PMIC)數(shù)據(jù)手冊

    TPS659037 器件是一款集成電源管理 IC (PMIC)。該器件提供 7 個可配置的降壓轉(zhuǎn)換,輸出電流高達(dá) 6 A,用于存儲、處理器
    的頭像 發(fā)表于 04-26 11:27 ?967次閱讀
    TPS659037 用于 ARM Cortex A15 <b class='flag-5'>處理器</b>的<b class='flag-5'>電源</b><b class='flag-5'>管理</b> IC (PMIC)數(shù)據(jù)手冊

    TPS3705 處理器管理引擎,帶電源故障和集成看門狗定時數(shù)據(jù)手冊

    TPS370x-xx 系列微處理器電源電壓監(jiān)控提供電路初始化和定時監(jiān)控功能,主要用于 DSP 和基于處理器的系統(tǒng)。 上電期間,當(dāng)
    的頭像 發(fā)表于 04-12 17:12 ?1018次閱讀
    TPS3705 <b class='flag-5'>處理器</b><b class='flag-5'>管理</b>引擎,帶<b class='flag-5'>電源</b>故障和集成看門狗定時<b class='flag-5'>器</b>數(shù)據(jù)手冊