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下電源管理結構
每個電源管理適配器(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 系統休眠
控制所有支持休眠功能的外設進入休眠狀態,同時內核進入休眠狀態。
[html] view plain copy print?
1. VOID Lw_PowerM_Suspend(VOID);
2.1.2 系統喚醒
控制所有支持休眠功能的外設從休眠狀態恢復正常狀態,同時內核恢復正常狀態。
[html] view plain copy print?
1. VOID Lw_PowerM_Resume(VOID);
2.1.3 設置CPU節能參數
設置多核系統中運行的CPU核數目以及CPU能耗級別,系統根據參數關閉或打開CPU核,同時設置CPU能耗級別,設置CPU以不同的主頻運行,進入節能模式時降低主頻,反之則升高主頻。本函數還會將CPU參數的改變通知到所有支持電源管理的外設。
[html] view plain copy print?
1. VOID Lw_PowerM_CpuSet(ULONG ulNCpus, UINT uiPowerLevel);
其中參數:參數 ulNCpus是運行態的CPU核個數;
參數 uiPowerLevel是CPU能耗級別。
2.1.4 獲取CPU節能參數
該函數獲得當前運行的CPU個數和CPU能耗級別。
[html] view plain copy print?
1. VOID Lw_PowerM_CpuGet(ULONG *pulNCpus, UINT *puiPowerLevel);
其中參數:參數 pulNCpus返回運行態的CPU核個數;
參數 puiPowerLevel返回CPU能耗級別。
2.1.5 系統進入省電模式
使系統進入省電模式。控制所有支持電源管理的設備進入省電模式,同時設置運行的CPU核數目以及能耗級別。
[html] view plain copy print?
1. VOID Lw_PowerM_SavingEnter(ULONG ulNCpus, UINT uiPowerLevel);
其中參數:參數 ulNCpus是運行態的CPU核個數;
參數 uiPowerLevel是CPU能耗級別。
2.1.6 系統退出省電模式
控制系統退出省電模式,控制所有支持電源管理的設備退出省電模式,同時設置運行的CPU核數目以及能耗級別。
[html] view plain copy print?
1. VOID Lw_PowerM_SavingExit(ULONG ulNCpus, UINT uiPowerLevel);
其中參數:參數 ulNCpus是運行態的CPU核個數;
參數 uiPowerLevel是CPU能耗級別。
2.2 系統接口實現
2.2.1 系統休眠和喚醒
統在進行休眠或者喚醒操作時,首先遍歷電源設備管理鏈表,對鏈表中支持電源管理的設備進行休眠或者喚醒操作,然后對系統內核進行休眠或喚醒操作。系統接口實現流程
1. 系統休眠
對系統進行休眠操作,需調用API_PowerMSuspend系統接口,實現外設和系統內核進入休眠狀態。函數原型如程序清單 2 - 1所示。
程序清單2 - 1 系統休眠
[html] view plain copy print?
1. VOID API_PowerMSuspend (VOID)
2. {
3. PLW_LIST_LINE plineTemp;
4. PLW_PM_DEV pmdev;
5.
6. __POWERM_LOCK();
7. /*
8. * 遍歷電源管理鏈表,對鏈表中設備進行休眠處理
9. */
10. for (plineTemp = _G_plinePMDev;
11. plineTemp != LW_NULL;
12. plineTemp = _list_line_get_next(plineTemp)) {
13. pmdev = _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
14. if (pmdev->PMD_pmdfunc &&
15. pmdev->PMD_pmdfunc->PMDF_pfuncSuspend) {
16. pmdev->PMD_pmdfunc->PMDF_pfuncSuspend(pmdev);
17. }
18. }
19.
20. __POWERM_UNLOCK();
21.
22. API_KernelSuspend(); /* 內核休眠處理 */
23. }
該函數實現以下功能:
1.
遍歷電源設備管理鏈表中支持電源管理的設備;
2.
3.
調用PMDF_pfuncSuspend函數,對加入電源管理鏈表中的外設依次進行休眠處理;
4.
5.
調用API_KernelSuspend函數,使內核進入休眠狀態。
6.
2. 系統喚醒
系統從休眠狀態喚醒,需調用API_PowerMResume系統接口,實現外設和內核從休眠狀態喚醒,函數原型如程序清單2- 2所示。
程序清單2 - 2 系統喚醒
[cpp] view plain copy print?
1. VOID API_PowerMResume (VOID)
2. {
3. PLW_LIST_LINE plineTemp;
4. PLW_PM_DEV pmdev;
5.
6. __POWERM_LOCK();
7.
8. /*
9. * 遍歷電源管理鏈表,對鏈表中設備進行喚醒處理
10. */
11. for (plineTemp = _G_plinePMDev;
12. plineTemp != LW_NULL;
13. plineTemp = _list_line_get_next(plineTemp)) {
14.
15. pmdev = _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
16. if (pmdev->PMD_pmdfunc &&
17. pmdev->PMD_pmdfunc->PMDF_pfuncResume) {
18. pmdev->PMD_pmdfunc->PMDF_pfuncResume(pmdev);
19. }
20. }
21. __POWERM_UNLOCK();
22.
23. API_KernelResume(); /* 內核喚醒處理 */
24. }
該函數實現以下功能:
1.遍歷電源設備管理鏈表中支持電源管理的設備;
2.調用PMDF_pfuncResume函數,對加入電源管理鏈表中的外設進行喚醒處理;
3.調用API_KernelResume函數,使內核從休眠中喚醒。
2.2.2 CPU節電參數設置和獲取
CPU節電參數的設置,根據傳入參數對CPU核進行關閉和打開,然后設置CPU能耗等級。獲取CPU節電參數,首先獲取當前系統運行CPU核個數,然后獲取CPU能耗等級。系統接口實現流程
1. 設置CPU節電參數
設置CPU節電參數,需調用API_PowerMCpuSet系統接口,函數原型如程序清單2-3所示。
程序清單2 - 3 設置CPU節電參數
[html] view plain copy print?
1. VOID API_PowerMCpuSet (ULONG ulNCpus, UINT uiPowerLevel)
2. {
3. PLW_LIST_LINE plineTemp;
4. PLW_PM_DEV pmdev;
5. UINT uiOldPowerLevel;
6.
7. #if LW_CFG_SMP_EN > 0
8. ULONG i;
9. ULONG ulActCnt = 0;
10. #endif /* LW_CFG_SMP_EN > 0 */
11. if (ulNCpus == 0) {
12. _ErrorHandle(EINVAL);
13. return;
14. }
15. if (ulNCpus > LW_NCPUS) {
16. ulNCpus = LW_NCPUS;
17. }
18.
19. #if LW_CFG_SMP_EN > 0
20. for (i = 0; i < LW_NCPUS; i++) { /* 獲取當前系統運行CPU數 */
21. if (API_CpuIsUp(i)) {
22. ulActCnt++;
23. }
24. }
25.
26. if (ulActCnt > ulNCpus) { /* 需要關閉一些 CPU */
27. #if LW_CFG_SMP_CPU_DOWN_EN > 0
28. ULONG ulDownCnt = ulActCnt - ulNCpus;
29. for (i = 1; i < LW_NCPUS; i++) {
30. if (API_CpuIsUp(i)) {
31. API_CpuDown(i);
32. ulDownCnt--;
33. }
34. if (ulDownCnt == 0) {
35. break;
36. }
37. }
38. #endif /* LW_CFG_SMP_CPU_DOWN_EN > 0 */
39.
40. } else if (ulActCnt < ulNCpus) { /* 需要打開一些 CPU */
41. ULONG ulUpCnt = ulNCpus - ulActCnt;
42. for (i = 1; i < LW_NCPUS; i++) {
43. if (!API_CpuIsUp(i)) {
44. API_CpuUp(i);
45. ulUpCnt--;
46. }
47.
48. if (ulUpCnt == 0) {
49. break;
50. }
51. }
52. }
53. #endif /* LW_CFG_SMP_EN > 0 */
54.
55. API_CpuPowerGet(&uiOldPowerLevel); /* 獲得CPU運行能級 */
56. if (uiOldPowerLevel != uiPowerLevel) {
57. API_CpuPowerSet(uiPowerLevel); /* 設置CPU運行能級 */
58. __POWERM_LOCK();
59. /*
60. * 遍歷電源管理鏈表,將節電參數通知支持電源管理的外設
61. */
62. for (plineTemp = _G_plinePMDev;
63. plineTemp != LW_NULL;
64. plineTemp = _list_line_get_next(plineTemp)) {
65. pmdev = _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
66. if (pmdev->PMD_pmdfunc &&
67. pmdev->PMD_pmdfunc->PMDF_pfuncCpuPower) {
68. pmdev->PMD_pmdfunc->PMDF_pfuncCpuPower(pmdev);
69. }
70. }
71.
72. __POWERM_UNLOCK();
73. }
74. }
該函數實現以下功能:
1.
獲取當前系統運行的CPU核數;
2.
3.
若傳入參數小于當前系統運行CPU核數,則關閉一些CPU核;
4.
5.
若傳入參數大于當前系統運行CPU核數,則打開一些CPU核;
6.
獲取當前CPU能耗等級,根據傳入參數設置CPU能耗等級;
7.
8.
遍歷電源管理設備鏈表,將CPU節電參數通知所有支持電源管理的外設。
9.
2. 獲取CPU節電參數
獲取CPU節電參數,需調用API_PowerMCpuGet系統接口,函數原型如程序清單2-4所示。
程序清單2-4 獲取CPU節電參數
[html] view plain copy print?
1. VOID API_PowerMCpuGet (ULONG *pulNCpus, UINT *puiPowerLevel)
2. {
3. #if LW_CFG_SMP_EN > 0
4. ULONG i;
5. ULONG ulActCnt = 0;
6. /*
7. * 獲取CPU運行核數
8. */
9. if (pulNCpus) {
10. for (i = 0; i < LW_NCPUS; i++) {
11. if (API_CpuIsUp(i)) {
12. ulActCnt++;
13. }
14. }
15. *pulNCpus = ulActCnt;
16. }
17. #else
18. if (pulNCpus) {
19. *pulNCpus = 1ul;
20. }
21. #endif /* LW_CFG_SMP_EN > 0 */
22. if (puiPowerLevel) {
23. API_CpuPowerGet(puiPowerLevel); /* 獲取CPU運行能級 */
24. }
25. }
該函數實現以下功能:
1.
獲取當前系統CPU核數;
2.
3.
獲取當前系統CPU運行能級。
4.
2.2.3 系統省電模式進入和退出
系統進入或退出省電模式,首先通知所有支持電源管理的外設進入或者退出省電模式,然后根據傳入參數設置CPU節電參數。系統接口實現流程
1. 進入省電模式
系統進入省電模式,需調用API_PowerMSavingEnter系統接口,函數原型如程序清單2 - 5所示。
程序清單2 - 5 進入省電模式
[html] view plain copy print?
1. VOID API_PowerMSavingEnter (ULONG ulNCpus, UINT uiPowerLevel)
2. {
3. PLW_LIST_LINE plineTemp;
4. PLW_PM_DEV pmdev;
5.
6. if (ulNCpus == 0) {
7. _ErrorHandle(EINVAL);
8. return;
9. }
10. __POWERM_LOCK();
11. /*
12. * 遍歷電源管理鏈表,使外設進入省電模式
13. */
14. for (plineTemp = _G_plinePMDev;
15. plineTemp != LW_NULL;
16. plineTemp = _list_line_get_next(plineTemp)) {
17. pmdev = _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
18. if (pmdev->PMD_pmdfunc &&
19. pmdev->PMD_pmdfunc->PMDF_pfuncPowerSavingEnter) {
20. pmdev->PMD_pmdfunc->PMDF_pfuncPowerSavingEnter(pmdev);
21. }
22. }
23.
24. _G_bPowerSavingMode = LW_TRUE;
25. __POWERM_UNLOCK();
26.
27. API_PowerMCpuSet(ulNCpus, uiPowerLevel); /* CPU節電參數設置 */
28. }
該函數實現以下功能:
1.
遍歷電源管理鏈表,把電源管理鏈表中所有支持電源管理的設備設置為省電模式;
2.
3.
設置CPU節電參數,根據傳入參數,對CPU節電參數進行設置,調用2.2.2節中API_PowerMCpuSet接口函數。
4.
2. 退出省電模式
系統退出省電模式,需調用API_PowerMSavingExit系統接口,函數原型如程序清單2 - 6所示。
程序清單2 - 6 退出省電模式
[html] view plain copy print?
1. VOID API_PowerMSavingExit (ULONG ulNCpus, UINT uiPowerLevel)
2. {
3. PLW_LIST_LINE plineTemp;
4. PLW_PM_DEV pmdev;
5.
6. if (ulNCpus == 0) {
7. _ErrorHandle(EINVAL);
8. return;
9. }
10. __POWERM_LOCK();
11. /*
12. * 遍歷電源管理鏈表,使外設外設省電模式
13. */
14. for (plineTemp = _G_plinePMDev;
15. plineTemp != LW_NULL;
16. plineTemp = _list_line_get_next(plineTemp)) {
17. pmdev = _LIST_ENTRY(plineTemp, LW_PM_DEV, PMD_lineManage);
18. if (pmdev->PMD_pmdfunc &&
19. pmdev->PMD_pmdfunc->PMDF_pfuncPowerSavingExit) {
20. pmdev->PMD_pmdfunc->PMDF_pfuncPowerSavingExit(pmdev);
21. }
22. }
23. _G_bPowerSavingMode = LW_FALSE;
24. __POWERM_UNLOCK();
25.
26. API_PowerMCpuSet(ulNCpus, uiPowerLevel); /* CPU節電參數設置 */
27. }
該函數實現以下功能:
1.
遍歷電源管理鏈表,把電源管理鏈表中所有支持電源管理的設備退出省電模式;
2.
3.
設置CPU節電參數,根據傳入參數,對CPU節電參數進行設置,調用2.2.2節中API_PowerMCpuSet接口函數。
4.
3. 小結
本文檔介紹了SylixOS向應用層提供的電源管理系統接口,以及接口的實現流程。應用層可以調用這些系統接口,實現系統的電源管理工作。