天天看点

物联网实时操作系统zephyr的电源管理子系统



Power Management

电源管理的基础设施包括电源管理子系统提供的接口。这个子系统提供的接口用于实现电源管理应用并实现不同的省电策略。

Terminology

PMA

PMA(PowerManagement Application).系统集成商提供PMA。PMA维护一些电源管理的策略和基于这些策略执行电源管理相关的动作。PMA必须集成到到zephyr的主应用当中。

LPS

LPS(Lower PowerState).指的是任何CPU所支持的不同的电源管理状态。

SoC Power State

Soc电源管理状态描述了处理器和设备的电源管理状态在SoC层面的实现。

Hook function

Hook函数是由一个组建实现的且由另外一个组建调用。比如,PMA实现的函数由内核调用。

Architecture and SoC dependent PowerStates:

On x86:

Active

     The CPU is active and running in thehardware defined C0 C-state.

Idle

          The CPU is not running but still be powered.The CPU may be in one of any lower C-sates: C1, C2, etc.

Deep Sleep

      The Power is off to the processor andsystem clock.RAM is retained.

On ARM

Active

    The CPU is active and running.

Idle

     Stops the processor clock.

Deep Sleep

          Stops the system clock and switches off thePLL and flash memory. RAM is retained.

ON ARC

     Active

                   The CPU is currently active and running in theSS0 state

    Idle

        Defined as the SS1 and SS2 states.

这里只是简单介绍了三种架构的电源管理状态,当编写PMA代码的时候,请参考SoC的数据手册,获取电源管理状态的细节。

Overview

         Zephyr电源管理子系统提供了接口用于系统集成去创建PMA。PMA确保需要的电源管理策略。设计的哲学是确保内核里不实现具体的策略,而是将策略在PMA中,这样PMA更加的灵活。

         提供的基础设施和架构相关。无论是microkernel还是nanokernel当系统将要进入和退出Idle状态。PMA在这些通知中可以执行具体的电源管理策略。

Policies

         当电源管理子系统通知PMA,告诉PMA内核即将进入idle状态。PMA会执行相关的操作在此期间。PMA可以执行不同的操作。比如,将处理器和SoC进入低功耗状态,关闭一些外设和门控时钟,通过这些操作的组合,PMA可以创造出更精细的电源管理策略。

         这些细粒度的电源管理策略会有不同的省电功耗和唤醒延迟。通常,越省电的操作,唤醒延迟也越大。当决定策略的时候,PMA选择最省电的操作与此同时,也必须满足电源管理子系统分配的进入idle的总的执行时间。

         Zephyr电源管理子系统将策略基于相对功率节省和唤醒延迟进行了分类。这些策略也松散地映射到通用处理器和系统的状态,在支持的架构。PMA应该映射细粒度的定制策略到电源管理子系统的策略分类。电源管理子系统定义了一下三种分类。

SYS_PM_LOW_POWER_STATE

SYS_PM_DEEP_SLEEP

SYS_PM_DEVICE_SUSPEND_ONLY

SYS_PM_LOW_POWER_STATE

在这一策略范畴,PMA提供电源管理相关的操作于一些或全部设备,并将处理器进入一个低功耗状态。设备的电源管理操作可以是关闭外设和门控时钟。当这些操作如果引起设备寄存器相关状态丢失,则这些状态必须保存和恢复。PMA应该映射细粒度的策略和相对较小的唤醒延迟,对于这个分类。唤醒延迟更大的对应的是SYS_PM_DEEP_SLEEP。这个分类策略的低功耗状态的退出时通过外部中断,PMA的唤醒事件或者是PM subsystem分配的idle time 超时。

SYS_PM_DEEP_SLEEP

在这一策略范畴类,PMA让处理器进入深睡眠状态通过SoCs,在这种状态下,系统时钟会被关闭掉。处理器也会关闭且丢失状态。RAM被期望用于保存现场和恢复处理器状态。只有设备唤醒系统从深睡眠状态停留。SoC关闭所有设备的电源。PMA应该映射细粒度的策略并按照最高的唤醒延迟。这种电源管理状态退出可以通过唤醒事件。

SYS_PM_DEVICE_SUSPEND_ONLY

在这一策略范畴内,PMA相关的电源操作只作用于一些设备。没有在处理器和SoC电源状态的转变。PMA应该映射细粒度的策略,这个状态对应的唤醒延迟是最小的。通过外部中断或者分配的idle time超时可以退出,

 一些策略的名字和处理器和SOC的状态相似,比如SYS_PM_DEEP_SLEEP,然而,他们必须被视为政策类别,并没有表明任何处理器或系统自身进入的电源状态。

Power Management Hook Infrastructure

这些基础设施包括PMA实现的钩子函数。在内核进入或者退出idle状态的时候PM子系统调用这些钩子函数,换句话说,当内核没有任务调度的时候。一下章节提供了钩子函数的通用概率和通用概述。参考具体的API章节了解这个API的细节。

Suspend Hook function

int _sysy_soc_suspend(int32_t ticks);

当内核即将进入idle状态时,电源管理子系统调用 __sys_soc_suspend()函数。通知PMA内核准备进入idle状态。

与此同时,内核开始禁止中断和计算系统能够保存idle的最大ticks数目。该函数通过系统能够保持空闲的PMA随着时间通知。接到通知后,PMA选择并执行一个细粒度的电源管理策略,可以在规定的时间内执行。这个函数的返回值有以下几种:

SYS_PM_NOT_HANDLED

没有电源管理相关的操作,PMA没有实现任何动作在内核分配的时间内。

SYS_PM_DEVICE_SUSPEND_ONLY

只有设备是suspended。暗示PMA执行了设备相关的操作。不包括对任何处理器或SoC相关的操作。

SYS_PM_LOW_POWER_STATE

进入LPS,暗示PMA能够让处理器进入低功耗状态

SYS_PM_DEEP_SLEEP

进入深睡眠状态,暗示PMA可以让SOC进入深睡眠状态

Resume Hook function

Void  _sys_soc_resume(void)

当内核退出一个空闲状态或者低功耗状态,会调用此钩子函数。基于哪个策略PMA在__sys_soc_suspend函数中执行的,PMA提供了必须的恢复操作在此函数中,由于钩子函数被调用的时候是关中断的,PMA应该保证它的操作尽可能快,因此,PMA确保内核的调度策略不会被中断。

Device PowerManagement Infrastructure

设备的电源管理基础设施包括zephyr设备模型提供的接口,这些接口保证设备的suspend和resume.

Device Power Management Operations

驱动可以实现处理函数取执行相关的suspend和resume函数。PMA提供必要的电源管理操作是通过调用每一个驱动的suspend和resume函数。

sruct dev_pm_ops{

         Int (*suspend)(struct device*device,int pm_policy);

    Int (*resume)(uct device *device, intpm_policy

}

这个结构体包含了suspend和resume函数指针,设备驱动会初始化这些指针并且实现对应的函数。

Default Initializer Function

Intdevice_pm_nop(struct device *unused_device,int unused_policy);

当驱动程序不执行任何操作时,该驱动程序可以使用该函数初始化相应的指针。这个默认的初始化函数不应该用来代替执行驱动程序中的填充函数来避免代码浪费内存。

Device SuspendOperation Handler Function

Intsuspend(struct device *device,int policy);

这个驱动程序实现此功能来执行设备的挂起操作。PMA调用这个函数和通过电源管理测策略去执行。设备驱动程序执行必要的处理转变和PMA指定的电源管理状态一致。下面是设备驱动程序执行的一些示例操作。

保存设备状态

门控时钟

关闭外设

函数返回0表示成功,否则,返回错误值errno值

Device ResumeOperation Handler Function

Int resume(struct device *device,int policy);

PMA调用此函数唤醒设备,之前执行了相应的suspend操作。设备驱动提供必要的唤醒操作。紧接着参数是为看指定指定的电源管理策略。

函数如果返回0,表示成功,否则,返回errno值。

Device Modelwith Power Management Support(电源管理支持的设备模型)

         驱动初始化设备使用宏。宏的扩展的版本提供了驱动对电源管理的支持。这些宏使用了额外的参数初始化这些指针以实现电源管理的相关函数。

这些宏应该被使用

DEVICE_AND_API_INIT_PM

    USE this macro in place of theDEVICE_AND_API_INIT macro.

DEVICE_INIT_PM

         Use this macro in place of theDEVICE_INIT macro

SYS_INIT_PM

    Use this macro in place of the SYS_INITmacro.

Device Power Management API for the PMA

PMA的设备电源管理接口

PMA使用以下APIs 提供设备的suspend和resume相关的操作

Get Device List

void device_list_get(struct device **device_list,int *device_count);

zephyr 内核内部维护了全体设备的链表在系统中。PMA的使用者可以通过这个API去获得设备链表。PMA可以使用这个链表去标识哪个设备应该执行电源管理相关的操作。

PMA可以使用这个链表去创建一个排序好的基于设备的依赖关系。PMA创建设备组以执行不同的策略对于每个组,

 确保PMA不改变原始链表,因为内使用了原始链表,并不会去改变它。

PMA DeviceSuspend API

Intdevice_suspended(struct device *device ,int policy);

调用由设备驱动程序实现的suspend()处的理函数。

PMA DeviceResume API

Intdevice_resume(struct device *device,int pm_policy);

调用由设备驱动实现的resume()函数。

Busy Status Indication(忙碌的状态显示)

PMA执行一些电源管理策略,这些策略有的是关闭设备的电源,使它们会丢失自己的状态信息。如果设备正在一些硬件的转变之中,比如写内存时候被下电,这样的会导致一些不一致的状态。这些基础设施保证了这些转变去告诉PMA设备是否处于一种硬件转化的中间状态。

当_sys_power_suspend被调用的时候,PMA检查设备是否繁忙。PMA可以决定是否去执行策略,而不是去深睡眠还是其他的电源管理相关的操作直到在下一个_sys_power_suspend()。

如果其他的恢复和检索方法到位,驱动可以避免保护食物。并不是所有的硬件转变都必须谨慎。Zephyr内核提供以下的设备驱动程序的APIs和PMA来决定是否一个特定的转变必须谨慎的。

Indicate Busy Status API

void device_busy_set(struct device *busy_dev);

设置一个bit位和设备保持一致,在内核中维护了一个数据结构,暗示设备是否处于转变的中间状态

    Clear Busy Status API

void device_busy_clear(struct device *busy_dev);

清除内核中维护的数据结构中的设备的位,用以指示设备不处于一个转变的中间状态。

Check BusyStatus of Single Device API

Intdevice_busy_check(struct device *chk_dev);

Checks whether adevice is busy. The API returns 0 if the device is not busy.

Check BusyStatus of all devices API

Intdevice_any_busy_check(void)

检查所有的设备是否繁忙,如果返回0表示没有设备忙。

Power ManagementConfiguration Flags

CONFIG_SYS_POWER_MANAGEMENT

The flagsenables the power management subsystem.

CONFIG_SYS_POWER_LOW_POWER_STATE

    PMA使能这个flag去使用SYS_PM_LOW_POWER_STATE策略。

CONFIG_SYS_POWER_DEEP_SLEEP

    这个标志使能支持 SYS_PM_DEEP_SLEEP策略。

CONFIG_DEVICE_POWER_MANAGEMENT

    这个标志使能PMA和设备支持的电源管理状态。

Writing a Power Management Application(写一个电源管理相关的应用)

一个典型的PMA通过电源管理的接口执行策略。这个章节描述了不同的场景可以用来帮助开发者编写他们定制的PMAs.

 PMA是个比较大的应用程序,不仅仅局限于电源管理。此章节聚焦在电源管理的角度。

Initial Setup(初始化)

 为了使能电源管理支持,首先按照以下步骤操作:

  1. 使能标志CONFIG_SYS_POWER_MANAGEMENT
  2. 使能其他标志。
  3. 实现具体的钩子函数。

    DeviceList and Policies

    PMA通过使用device_list_get()函数获得系统中所有使能设备的设备链表。因为PMA是应用的一部分,系统中所有的设备初始化之后PMA才会启动。因此,当应用开始的时候,设备链表已经不在变化。

              当设备链表被检索或存储时,PMA基于设备依赖关系填充设备组和已排序的设备链表。PMA使用电源管理的各种操作去组合设备链表以及根据唤醒延迟去创建定制不同的电源管理策略。最终这些定制的策略被电源管理子系统进行了分了,并在策略一章节进行了描述。

    ScenariosDuring Suspend

              当电源管理子系统调用__sys_soc_suspend()函数,PMA可以选择以下各中国不同的场景。

    Scenario 1

    对于任何的电源管理分配的时间太短

    PMA使得中断禁止,返回SYS_PM_NOT_HANDLED。这个动作允许Zephyr内核继续进入正常的idling处理过程。

    Scenario2

    分配的时间允许关闭一些设备

    调用device_suspend()函数对于每个设备。当所有的设备都差不多关闭之后。

    如果时间足够进入SYS_PM_LOW_POWER_STATE:

  1. PMA设置wake event,让CPU进入LPS,与此同时重使能中断
  2. 返回SYS_PM_LOWER_POWER_STATE

如果时间不够进入SYS_PM_LOW_POWER_STATE策略,PMA返回SYS_PM_DEVICE_SUSPEND_ONLY

如果有一个设备没有suspend。PMA会进入一下的操作

如果系统集成者确定该设备不是关键影响suspend进程的设备,可以忽略这个设备的错误。

如果系统集成商任务这个设备在suspend的过程中是非常重要的,PMA应该采取任何的恢复动作,同时返回SYS_PM_NOT_HANDLED

Scenario 3

时间足够所有的devices suspended

PMA调用device_suspend()函数对于每个device

当所有的设备可能在suspended之后,且分配的时间是足够进入SYS_PM_DEEP_SLEEP策略的,PMA执行以下的操作:

  1. 调用device_any_busy_check()函数去获取设备的状态,如果设备忙,PMA必须选择一个除了SYS_PM_DEEP_SLEEP之外的状态
  2. 设置唤醒事件
  3. 置SoC于deep sleep状态
  4. 重新使能中断
  5. 返回SYS_PM_DEEP_SLEEP

    如果,另外一种情况是,如果时间只够进入SYS_PM_LOW_POWER_STATE策略,PMA执行以下的策略:

  1. 设置唤醒事件
  2. 与此同时,让CPU进入LPS和re-enabling interrupts

    如果分配的时间不够进入CPU和SoC电源管理的状态,PMA返回SYS_PM_DEVICE_SUSPEND_ONLY

    当一个设备没有成功的suspend,PMA会执行以下操作:

  1. 如果系统集成者确定单个设备对整个系统的suspend进程不是非常关键的话,PMA会忽略错误
  2. 如果系统集成者确定设备对suspend的进程非常关键的话,PMA采取必要的措施后返回SYS_PM_NOT_HANDLED

继续阅读