简介

Zephyr2.0的版本之后对电源管理子系统做了一个框架性的修改,因此如果你用的是Zephyr2.0以下的版本,请参考官方的文档,本篇介绍的2.0版本以后的电源管理框架。
电源管理子系统提供的接口API设计为独立于体系结构SOC。这使得电源管理实现能够轻松适应不同的SOC和架构。

电源管理的原理

一般情况下OSthread有效工作时间是不能占满CPU工作时间的,在其等待的时候有一个idle thread会占用CPU,将idle thread占用CPU的运行时间转为CPU idle,达到省电的目的。
21.Zephyr的电源管理介绍 - 图1
上图示例了一个跑了3个thread: Ta,Tb,Tc。这三个thread根据实际的应用情况调度,在t1,t2,t3这三个时间段这3个thread都不需要工作,在Normal的状态下,Idle thread将占用这3个时间段的CPU,让CPU空转。当引入电源管理后,一旦3个thread不工作转到idle时,idle thread会自动检测下一次thread工作的时间,设置timer,然后让CPU进入idle,当timer超时就唤醒CPU,继续调度工作。以t1为例:当Tc调度结束后进入idle thread, idle thread计算到下一次Tb被调度的时间间隔t1, 以t1设置timer,然后让CPU进入idlet1时间到后timer中断产生唤醒CPU,切换到Tb开始运行。

系统电源管理状态

源码路径在include/pm/state.h:

  1. enum pm_state {
  2. /**
  3. * @brief Runtime active state
  4. *
  5. * The system is fully powered and active.
  6. *
  7. * @note This state is correlated with ACPI G0/S0 state
  8. */
  9. PM_STATE_ACTIVE,
  10. /**
  11. * @brief Runtime idle state
  12. *
  13. * Runtime idle is a system sleep state in which all of the cores
  14. * enter deepest possible idle state and wait for interrupts, no
  15. * requirements for the devices, leaving them at the states where
  16. * they are.
  17. *
  18. * @note This state is correlated with ACPI S0ix state
  19. */
  20. PM_STATE_RUNTIME_IDLE,
  21. /**
  22. * @brief Suspend to idle state
  23. *
  24. * The system goes through a normal platform suspend where it puts
  25. * all of the cores in deepest possible idle state and *may* puts peripherals
  26. * into low-power states. No operating state is lost (ie. the cpu core
  27. * does not lose execution context), so the system can go back to where
  28. * it left off easily enough.
  29. *
  30. * @note This state is correlated with ACPI S1 state
  31. */
  32. PM_STATE_SUSPEND_TO_IDLE,
  33. /**
  34. * @brief Standby state
  35. *
  36. * In addition to putting peripherals into low-power states all
  37. * non-boot CPUs are powered off. It should allow more energy to be
  38. * saved relative to suspend to idle, but the resume latency will
  39. * generally be greater than for that state. But it should be the same
  40. * state with suspend to idle state on uniprocesser system.
  41. *
  42. * @note This state is correlated with ACPI S2 state
  43. */
  44. PM_STATE_STANDBY,
  45. /**
  46. * @brief Suspend to ram state
  47. *
  48. * This state offers significant energy savings by powering off as much
  49. * of the system as possible, where memory should be placed into the
  50. * self-refresh mode to retain its contents. The state of devices and
  51. * CPUs is saved and held in memory, and it may require some boot-
  52. * strapping code in ROM to resume the system from it.
  53. *
  54. * @note This state is correlated with ACPI S3 state
  55. */
  56. PM_STATE_SUSPEND_TO_RAM,
  57. /**
  58. * @brief Suspend to disk state
  59. *
  60. * This state offers significant energy savings by powering off as much
  61. * of the system as possible, including the memory. The contents of
  62. * memory are written to disk or other non-volatile storage, and on resume
  63. * it's read back into memory with the help of boot-strapping code,
  64. * restores the system to the same point of execution where it went to
  65. * suspend to disk.
  66. *
  67. * @note This state is correlated with ACPI S4 state
  68. */
  69. PM_STATE_SUSPEND_TO_DISK,
  70. /**
  71. * @brief Soft off state
  72. *
  73. * This state consumes a minimal amount of power and requires a large
  74. * latency in order to return to runtime active state. The contents of
  75. * system(CPU and memory) will not be preserved, so the system will be
  76. * restarted as if from initial power-up and kernel boot.
  77. *
  78. * @note This state is correlated with ACPI G2/S5 state
  79. */
  80. PM_STATE_SOFT_OFF
  81. };
  • PM_STATE_ACTIVE: 设备运行状态
  • PM_STATE_RUNTIME_IDLE: 运行时空闲空闲状态,
  • PM_STATE_SUSPEND_TO_IDLE: 挂起到空闲状态
  • PM_STATE_STANDBY: 低功耗状态,外设会进入低功耗,且cpu下电
  • PM_STATE_SUSPEND_TO_RAM: 系统资源被放置在RAM中,唤醒需要重启后操作RAM来进行恢复
  • PM_STATE_SUSPEND_TO_DISK: 系统资源被放置在DISK中,唤醒需要重启后操作DISK来进行恢复
  • PM_STATE_SOFT_OFF: 完全断电

以上的设备状态按照数值大小进行排序,数值约到降低的功耗越多。

设备电源管理状态

源码路径zephyr/include/pm/device.h

  1. /** @brief Device power states. */
  2. enum pm_device_state {
  3. /** Device is in active or regular state. */
  4. PM_DEVICE_STATE_ACTIVE,
  5. /**
  6. * Device is in low power state.
  7. *
  8. * @note
  9. * Device context is preserved.
  10. */
  11. PM_DEVICE_STATE_LOW_POWER,
  12. /**
  13. * Device is suspended.
  14. *
  15. * @note
  16. * Device context may be lost.
  17. */
  18. PM_DEVICE_STATE_SUSPENDED,
  19. /**
  20. * Device is suspended (forced).
  21. *
  22. * @note
  23. * Device context may be lost.
  24. */
  25. PM_DEVICE_STATE_FORCE_SUSPEND,
  26. /**
  27. * Device is turned off (power removed).
  28. *
  29. * @note
  30. * Device context is lost.
  31. */
  32. PM_DEVICE_STATE_OFF,
  33. /** Device is being resumed. */
  34. PM_DEVICE_STATE_RESUMING,
  35. /** Device is being suspended. */
  36. PM_DEVICE_STATE_SUSPENDING,
  37. };
  • PM_DEVICE_STATE_ACTIVE: 设备处于活动状态
  • PM_DEVICE_STATE_SUSPENDED: 设备已挂起
  • PM_DEVICE_STATE_FORCE_SUSPEND: 设备强制挂起
  • PM_DEVICE_STATE_SUSPENDING: 设备正在挂起
  • PM_DEVICE_STATE_OFF: 设备以断电,上下文丢失
  • PM_DEVICE_STATE_LOW_POWER: 设备进入低功耗
  • PM_DEVICE_STATE_RESUMING: 设备正在恢复
  • PM_DEVICE_STATE_SUSPENDING: 设备已经恢复中

电源状态约束

当我们在操作一些外设的时候,可能会因为IO阻塞而进入到休眠,这样可能会导致我们数据的丢死,更加糟糕的是会导致系统崩溃,因此Zephyr提供了对电源状态进行约束的API:

  1. /**
  2. * @brief Set a constraint for a power state
  3. *
  4. * @details Disabled state cannot be selected by the Zephyr power
  5. * management policies. Application defined policy should
  6. * use the @ref pm_constraint_get function to
  7. * check if given state is enabled and could be used.
  8. *
  9. * @note This API is refcount
  10. *
  11. * @param [in] state Power state to be disabled.
  12. */
  13. void pm_constraint_set(enum pm_state state);
  14. /**
  15. * @brief Release a constraint for a power state
  16. *
  17. * @details Enabled state can be selected by the Zephyr power
  18. * management policies. Application defined policy should
  19. * use the @ref pm_constraint_get function to
  20. * check if given state is enabled and could be used.
  21. * By default all power states are enabled.
  22. *
  23. * @note This API is refcount
  24. *
  25. * @param [in] state Power state to be enabled.
  26. */
  27. void pm_constraint_release(enum pm_state state);
  28. /**
  29. * @brief Check if particular power state is enabled
  30. *
  31. * This function returns true if given power state is enabled.
  32. *
  33. * @param [in] state Power state.
  34. */
  35. bool pm_constraint_get(enum pm_state state);
  • pm_constraint_set: 这是电源状态不能被电源管理策略选择,也就是说不能在此状态进入低功耗
  • pm_constraint_release: 释放电源状态,可以被电源管理策略选择
  • pm_constraint_get: 获取当前的电源状态的约束

电源管理策略

Zephyr的默认电源管理策略为Residency。该策略其实就是在进入idle任务中获取下一个调度任务的时间,然后根据时间来计算出需要进入到哪一个电源管理状态,最后根据电源管理状态来执行电源管理函数。
Zephyr同时还可以支持用户自定义的电源管理策略。在zephyr/tests/subsys/pm/power_mgmt/中给出了一个例子可以参考一下。

启动电源管理的配置

如果需要启用电源管理需要在prj.conf中设置:

  1. //启动电源管理
  2. CONFIG_PM=y
  3. //启用设备电源管理
  4. CONFIG_PM_DEVICE=y
  5. //启动运行时设备电源管理
  6. CONFIG_PM_DEVICE_RUNTIME=y
  7. //启动电源管理域
  8. CONFIG_PM_DEVICE_POWER_DOMAIN=y

电源管理的分类

目前Zephyr可以通过如下两种方式来实现电源管理:

  • 系统电源管理
  • 设备电源管理

以上两种电源管理都可以通过主动系统调用和自动系统调用两种方式来实现对电源的管理。