SylixOS電源管理概述以及接口介紹


1.概述

電源管理是操作系統中重要的一部分。要實現電源管理功能首先需要設備本身支持電源管理操作其次是操作系統支持電源管理操作。

SylixOS支持電源管理功能電源管理分爲兩大部分CPU功耗管理和外設功耗管理。

1.1 CPU功耗管理

SylixOS中CPU功耗管理分爲三個能級

1.正常運行(Running)CPU正常執行指令。

2.省電模式(PowerSaving)所有具有電源管理功能的設備進入 PowerSaving 模式同時CPU主頻降低多核CPU僅保留一個CPU運行。

3.休眠模式(Sleep)系統休眠所有具有電源管理功能的設備進入 Suspend 模式系統需要通過指定事件喚醒休眠模式系統會從復位向量處恢復需要 bootloader/BIOS 程序配合。

需要的注意的是在SMP多核中可以動態調整CPU運行的核心數。

1.2 外設功耗管理

SylixOS中外設功耗管理分爲四個狀態

1.正常運行狀態設備被打開驅動程序請求電源管理適配器連通設備電源與時鐘開始工作。

2.設備關閉狀態設備被關閉驅動程序請求電源管理適配器斷開設備電源與時鐘停止工作。

3.省電模式狀態系統進入省電模式請求高能耗設備進入省電模式。

4.設備空閒狀態設備功耗管理單元具有看門狗功能一旦空閒時間超過設置,系統會將設備變爲空閒狀態。

1.3 系統框架

SylixOS下電源管理結構如圖1-1所示。

 

圖 1-1 電源管理系統框架

每個電源管理適配器(PM Adapter)可以管理多個設備由相應的通道號區分電源管理適配器管理的通道號總數決定這個適配器可以管理多少個設備。應用層可以對支持電源管理的設備進行進入休眠模式、進入省電模式、恢復正常模式等電源管理操作。

2.系統接口及實現

2.1 系統接口概述

SylixOS中電源管理部分提供了下面6個函數接口供應用層使用如表2-1所示。


        表 2-1 電源管理系統接口

系統接口功能
API_PowerMSuspend系統休眠
API_PowerMResume系統喚醒
API_PowerMCpuSet設置CPU節電參數
API_PowerMCpuGet獲取CPU節電參數
API_PowerMSavingEnter系統進入省電模式
API_PowerMSavingExit系統退出省電模式

2.1.1 系統休眠

控制所有支持休眠功能的外設進入休眠狀態同時內核進入休眠狀態。

VOIDLw_PowerM_Suspend(VOID);

2.1.2 系統喚醒

控制所有支持休眠功能的外設從休眠狀態恢復正常狀態同時內核恢復正常狀態。

VOIDLw_PowerM_Resume(VOID);

2.1.3 設置CPU節能參數

設置多核系統中運行的CPU核數目以及CPU能耗級別系統根據參數關閉或打開CPU核同時設置CPU能耗級別設置CPU以不同的主頻運行進入節能模式時降低主頻反之則升高主頻。本函數還會將CPU參數的改變通知到所有支持電源管理的外設。

VOIDLw_PowerM_CpuSet(ULONG ulNCpus, UINT uiPowerLevel);

其中參數:    參數 ulNCpus是運行態的CPU核個數

            參數 uiPowerLevel是CPU能耗級別。

2.1.4 獲取CPU節能參數

該函數獲得當前運行的CPU個數和CPU能耗級別。

VOIDLw_PowerM_CpuGet(ULONG *pulNCpus, UINT *puiPowerLevel);

其中參數: 參數 pulNCpus返回運行態的CPU核個數

參數 puiPowerLevel返回CPU能耗級別。

2.1.5 系統進入省電模式

使系統進入省電模式。控制所有支持電源管理的設備進入省電模式同時設置運行的CPU核數目以及能耗級別。

VOIDLw_PowerM_SavingEnter(ULONG ulNCpus,UINT uiPowerLevel);

其中參數: 參數 ulNCpus是運行態的CPU核個數

參數 uiPowerLevel是CPU能耗級別。

2.1.6 系統退出省電模式

控制系統退出省電模式控制所有支持電源管理的設備退出省電模式同時設置運行的CPU核數目以及能耗級別。

VOIDLw_PowerM_SavingExit(ULONG ulNCpus,UINT uiPowerLevel);

其中參數:  參數 ulNCpus是運行態的CPU核個數

 參數 uiPowerLevel是CPU能耗級別。


2.2 系統接口實現

2.2.1 系統休眠和喚醒

系統在進行休眠或者喚醒操作時首先遍歷電源設備管理鏈表對鏈表中支持電源管理的設備進行休眠或者喚醒操作

然後對系統內核進行休眠或喚醒操作。系統接口實現流程如圖2-1所示。

圖2-1 系統休眠或喚醒流程

1. 系統休眠

對系統進行休眠操作需調用API_PowerMSuspend系統接口實現外設和系統內核進入休眠狀態。函數原型如程序清單2-1所示。

 程序清單2-1 系統休眠

VOID  API_PowerMSuspend  (VOID)
{
    PLW_LIST_LINE       plineTemp;
PLW_PM_DEV        pmdev;
 
    __POWERM_LOCK();
    /*
    *  遍歷電源管理鏈表,對鏈表中設備進行休眠處理
    */
    for(plineTemp   = _G_plinePMDev;
        plineTemp !=  LW_NULL;
        plineTemp  = _list_line_get_next(plineTemp)) {
       pmdev= _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
       if(pmdev->PMD_pmdfunc && 
           pmdev->PMD_pmdfunc->PMDF_pfuncSuspend) {
           pmdev->PMD_pmdfunc->PMDF_pfuncSuspend(pmdev);
       }
}
 
__POWERM_UNLOCK();
 
    API_KernelSuspend();                                          /*  內核休眠處理              */
}

該函數實現以下功能

  1.  遍歷電源設備管理鏈表中支持電源管理的設備

  2.  調用PMDF_pfuncSuspend函數對加入電源管理鏈表中的外設依次進行休眠處理

  3.  調用API_KernelSuspend函數使內核進入休眠狀態。

     

2. 系統喚醒

系統從休眠狀態喚醒需調用API_PowerMResume系統接口實現外設和內核從休眠狀態喚醒函數原型如程序清單2-2所示。

 程序清單2-2 系統喚醒

VOID  API_PowerMResume (VOID)
{
    PLW_LIST_LINE        plineTemp;
PLW_PM_DEV         pmdev;
 
    __POWERM_LOCK();
    /*
    *  遍歷電源管理鏈表,對鏈表中設備進行喚醒處理
    */
    for(plineTemp   = _G_plinePMDev;
        plineTemp != LW_NULL;
        plineTemp  = _list_line_get_next(plineTemp)) {
       pmdev= _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
       if(pmdev->PMD_pmdfunc && 
           pmdev->PMD_pmdfunc->PMDF_pfuncResume) {
           pmdev->PMD_pmdfunc->PMDF_pfuncResume(pmdev);
       }
}
 
__POWERM_UNLOCK();
 
    API_KernelResume();                                           /*  內核喚醒處理             */
}

該函數實現以下功能

1.遍歷電源設備管理鏈表中支持電源管理的設備

2.調用PMDF_pfuncResume函數對加入電源管理鏈表中的外設進行喚醒處理

3.調用API_KernelResume函數使內核從休眠中喚醒。

 

2.2.2 CPU節電參數設置和獲取

CPU節電參數的設置根據傳入參數對CPU核進行關閉和打開然後設置CPU能耗等級。獲取CPU節電參數首先獲取當前系統運行CPU核個數然後獲取CPU能耗等級。系統接口實現流程如圖2-2所示

圖2-2 CPU節電參數設置、獲取流程

1. 設置CPU節電參數

設置CPU節電參數需調用API_PowerMCpuSet系統接口函數原型如程序清單2-3所示。

程序清單2-3 設置CPU節電參數

VOID  API_PowerMCpuSet (ULONG  ulNCpus, UINT  uiPowerLevel)
{
    PLW_LIST_LINE   plineTemp;
    PLW_PM_DEV      pmdev;
    UINT            uiOldPowerLevel;

#if LW_CFG_SMP_EN > 0
    ULONG           i;
    ULONG           ulActCnt = 0;
#endif                                                                  /*  LW_CFG_SMP_EN > 0           */

    if (ulNCpus == 0) {
        _ErrorHandle(EINVAL);
        return;
    }

    if (ulNCpus > LW_NCPUS) {
        ulNCpus = LW_NCPUS;
    }

#if LW_CFG_SMP_EN > 0
    for (i = 0; i < LW_NCPUS; i++) {
        if (API_CpuIsUp(i)) {
            ulActCnt++;
        }
    }
    if (ulActCnt > ulNCpus) {                                           /*  需要關閉一些 CPU            */
#if LW_CFG_SMP_CPU_DOWN_EN > 0
        ULONG   ulDownCnt = ulActCnt - ulNCpus;
        for (i = 1; i < LW_NCPUS; i++) {
            if (API_CpuIsUp(i)) {
                API_CpuDown(i);
                ulDownCnt--;
            }
            if (ulDownCnt == 0) {
                break;
            }
        }
#endif                                                                  /*  LW_CFG_SMP_CPU_DOWN_EN > 0  */

    } else if (ulActCnt < ulNCpus) {                                    /*  需要打開一些 CPU            */
        ULONG   ulUpCnt = ulNCpus - ulActCnt;
        for (i = 1; i < LW_NCPUS; i++) {
            if (!API_CpuIsUp(i)) {
                API_CpuUp(i);
                ulUpCnt--;
            }
            if (ulUpCnt == 0) {
                break;
            }
        }
    }
#endif                                                                  /*  LW_CFG_SMP_EN > 0           */


    API_CpuPowerGet(&uiOldPowerLevel);                               /*  需要打開一些 CPU            */
    if (uiOldPowerLevel != uiPowerLevel) {
        API_CpuPowerSet(uiPowerLevel);                              /*  需要打開一些 CPU            */
        
        __POWERM_LOCK();
        /*
         * 遍歷
         */
        for (plineTemp  = _G_plinePMDev;
             plineTemp != LW_NULL;
             plineTemp  = _list_line_get_next(plineTemp)) {
             
            pmdev = _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
            if (pmdev->PMD_pmdfunc && 
                pmdev->PMD_pmdfunc->PMDF_pfuncCpuPower) {
                pmdev->PMD_pmdfunc->PMDF_pfuncCpuPower(pmdev);
            }
        }
        __POWERM_UNLOCK();
    }
}

    該函數實現以下功能:

1. 獲取當前系統運行的CPU核數;

2.若傳入參數小於當前系統運行CPU核數,則關閉一些CPU核;

3.若傳入參數大於當前系統運行CPU核數,則打開一些CPU核;

4.獲取當前CPU能耗等級,根據傳入參數設置CPU能耗等級;

5.遍歷電源管理設備鏈表,將CPU節電參數通知所有支持電源管理的外設。

2. 獲取CPU節電參數

    獲取CPU節電參數,需調用API_PowerMCpuGet系統接口,函數原型如程序清單2-4所示。

程序清單2-4 獲取CPU節電參數

VOID  API_PowerMCpuGet (ULONG  *pulNCpus, UINT  *puiPowerLevel)
{
#if LW_CFG_SMP_EN > 0
    ULONG   i;
    ULONG   ulActCnt = 0;

    if (pulNCpus) {
        for (i = 0; i < LW_NCPUS; i++) {
            if (API_CpuIsUp(i)) {
                ulActCnt++;
            }
        }
        *pulNCpus = ulActCnt;
    }
#else
    if (pulNCpus) {
        *pulNCpus = 1ul;
    }
#endif                                                                  /*  LW_CFG_SMP_EN > 0           */

    if (puiPowerLevel) {
        API_CpuPowerGet(puiPowerLevel);
    }
}

該函數實現以下功能

  1.  獲取當前系統CPU核數

  2.  獲取當前系統CPU運行能級。

2.2.3 系統省電模式進入和退出

系統進入或退出省電模式首先通知所有支持電源管理的外設進入或者退出省電模式然後根據傳入參數設置CPU節電參數。系統接口實現流程如圖2-3所示。

                      圖2-3 進入、退出省電模式流程

1. 進入省電模式

系統進入省電模式需調用API_PowerMSavingEnter系統接口函數原型如程序清單2-5所示。

程序清單2-5 進入省電模式

VOID  API_PowerMSavingEnter (ULONG  ulNCpus, UINT  uiPowerLevel)
{
    PLW_LIST_LINE   plineTemp;
    PLW_PM_DEV      pmdev;
    
    if (ulNCpus == 0) {
        _ErrorHandle(EINVAL);
        return;
    }
    
    __POWERM_LOCK();
    for (plineTemp  = _G_plinePMDev;
         plineTemp != LW_NULL;
         plineTemp  = _list_line_get_next(plineTemp)) {
         
        pmdev = _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
        if (pmdev->PMD_pmdfunc && 
            pmdev->PMD_pmdfunc->PMDF_pfuncPowerSavingEnter) {
            pmdev->PMD_pmdfunc->PMDF_pfuncPowerSavingEnter(pmdev);
        }
    }
    _G_bPowerSavingMode = LW_TRUE;
    __POWERM_UNLOCK();
    
    API_PowerMCpuSet(ulNCpus, uiPowerLevel);
}

該函數實現以下功能

  1.  遍歷電源管理鏈表把電源管理鏈表中所有支持電源管理的設備設置爲省電模式

  2.  設置CPU節電參數根據傳入參數對CPU節電參數進行設置調用2.2.2節中API_PowerMCpuSet接口函數。

2. 退出省電模式

系統退出省電模式需調用API_PowerMSavingExit系統接口函數原型如程序清單2-6所示。

程序清單2-6 退出省電模式

VOID  API_PowerMSavingExit (ULONG  ulNCpus, UINT  uiPowerLevel)
{
    PLW_LIST_LINE   plineTemp;
    PLW_PM_DEV      pmdev;
    
    if (ulNCpus == 0) {
        _ErrorHandle(EINVAL);
        return;
    }
    
    __POWERM_LOCK();
    for (plineTemp  = _G_plinePMDev;
         plineTemp != LW_NULL;
         plineTemp  = _list_line_get_next(plineTemp)) {
         
        pmdev = _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
        if (pmdev->PMD_pmdfunc && 
            pmdev->PMD_pmdfunc->PMDF_pfuncPowerSavingExit) {
            pmdev->PMD_pmdfunc->PMDF_pfuncPowerSavingExit(pmdev);
        }
    }
    _G_bPowerSavingMode = LW_FALSE;
    __POWERM_UNLOCK();
    
    API_PowerMCpuSet(ulNCpus, uiPowerLevel);
}

該函數實現以下功能

  1.  遍歷電源管理鏈表把電源管理鏈表中所有支持電源管理的設備退出省電模式

  2.  設置CPU節電參數根據傳入參數對CPU節電參數進行設置調用2.2.2節中API_PowerMCpuSet接口函數。

3. 小結

本文檔介紹了SylixOS嚮應用層提供的電源管理系統接口以及接口的實現流程。應用層可以調用這些系統接口實現系統的電源管理工作。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章