zoukankan      html  css  js  c++  java
  • Zephyr的Power Management

    1 关于Zephyr

    Zephyr是Linux基金会维护的微内核项目,来源于WindRiver向Zephyr捐赠的Rocket RTOS内核。主要用于开发针对物联网设备的实时操作系统。

    Zephyr操作系统很小、具有扩展性并且专为小型物联网设备设计,它的模块化设计使不论采用哪个架构创建物联网方案,都能满足所有设备的需求。

    相关资源:

    Zephyr官网提供了相关帮助文档,并且在github维护了Zephyr KernelZephyr SDK Tools

    2 Zephyr的Power Management介绍

    参考Zephyr的Power Management帮助文档总结如下。

    首先对Zephyr功耗管理相关属于进行了介绍Terminology,然后是对Zephyr功耗管理总体介绍Overview,包括Tickless Idle、系统层面的功耗管理System Power Management和设备功耗管理Device Power Management Infrastructure

    平台级的功耗机制Power Schemes包括两种SYS_PM_LOW_POWER_STATESYS_PM_DEEP_SLEEP两种。

    最后是对Zephyr功耗管理配置Power Management Configuration Flags包括一个总开关CONFIG_SYS_POWER_MANAGEMENT和针对Tickless Idle、SoC和Device的配置。

    Power Management APIs单独对System和Device相关API进行了介绍。

    2.1 相关术语

    CPU LPS(Low Power State):可以指任何CPU支持的低功耗状态。

    Deep SLeep State:此时CPU供电被切断并且会丢失执行上下文,大部分外设被断电,RAM可能处于自刷新状态。

    Idle Thread:在所有其他线程都不运行时,进入Idle线程。这里面进行了低功耗相关处理。

    Power Gating:通过关闭不被使用模块的供电来达到降低功耗。

    2.2 概述

    Zephyr的PM子系统采用了分层思想,剥离特定架构和SoC相关部分,提取公共部分作为核心。SoC特殊部分被抽象到HAL层。

    Zephyr的功耗管理主要分为三部分:Tickless Idle、System Power Management和Device Power Management。

    2.3 Tickless Idle

    Zephyr的调度器可以运行在两种模式。

    在有线程执行的正常模式,使用周期性定时器,调度器运行在周期调度模式。

    当Idle线程被调度到的时候,idle线程会将定时器修改成单次触发模式,并将睡眠值取最近一次timeout值。

    这就保证在timeout超时之前调度器已经进入周期性工作模式。

    Zephyr(Cortex-M) 初始化的时候创建了idle线程,idle线程是系统功耗处理的主要入口。

    _PrepC(reset.S)-->
        _Cstart(prep_c.c)-->
            prepare_multithreading(init.c)-->初始化内核数据结构,包括main/idle线程以及架构相关初始化
                _IntLibInit
                _main
                idle(idle.c)-->idle线程函数
    _sys_power_save_idle-->
    _sys_soc_suspend--> initialize_timeouts kernel_arch_init switch_to_main_thread(init.c)-->

    _sys_power_save_idle的参数是系统最近一次timer超时tick数。这个参数通过_get_next_timeout_expiry获取。

    /* find the closest deadline in the timeout queue */
    
    static inline s32_t _get_next_timeout_expiry(void)
    {
        struct _timeout *t = (struct _timeout *)
                     sys_dlist_peek_head(&_timeout_q);------------从_timeout_q获取最近一次timer的_timeout
    
        return t ? t->delta_ticks_from_prev : K_FOREVER;
    }

    2.4 System Power Management

    系统进入退出退出Idle的时候,会调用相关钩子函数进行suspend/resume处理。

    2.4.1 进入低功耗模式

    _sys_soc_suspend是进入系统级低功耗的入口,入参是idle可以持续时间。

    里面具体的实现是SoC相关的,根据SoC的特性采取不同的睡眠策略,在某些情况下甚至需要关闭外设。

    一般情况下都会在真正睡眠前,设置一个唤醒事件,然后才会进入睡眠。

    prepare_multithreading-->
        idle-->Idle线程
            _sys_power_save_idle-->
                _sys_soc_suspend-->SoC相关低功耗钩子函数

    __sys_soc_suspend的实现一般根据可睡眠时间来决定睡眠状态,时间长可以进入深度睡眠。

    Parameters
    ticks: the upcoming kernel idle time
    Return Value
    SYS_PM_NOT_HANDLED: If low power state was not entered.
    SYS_PM_LOW_POWER_STATE: If CPU low power state was entered.
    SYS_PM_DEEP_SLEEP: If SOC low power state was entered.

    2.4.2 退出低功耗模式

    _sys_soc_resume和_sys_soc_resume_from_deep_sleep是两个弱类型钩子函数,都是在退出低功耗模式时回调。

    _sys_soc_resume是否执行要根据_sys_pm_idle_exit_notify是否有效,在_sys_soc_suspend返回SYS_PM_NOT_HANDLED情况下需要进行特殊处理。

    _timer_int_handler-->
    _arch_isr_direct_pm-->
    _isr_wrapper-->
        _sys_power_save_idle_exit-->
            _sys_soc_resume

     _sys_soc_pm_idle_exit_notification_disable用于关闭退出低功耗模式通知。

    系统级别的低功耗模式有三种:

    状态 注释
    SYS_PM_ACTIVE_STATE 正常工作状态。
    SYS_PM_LOW_POWER_STATE 浅度低功耗模式,CPU上下文没有丢失。
    SYS_PM_DEEP_SLEEP 深度低功耗模式,CPU会被断电,并且需要保存恢复上下文。甚至需要关闭外设。

    2.5 Device Power Management Infrastructure

    Zephyr关于设备的功耗管理有两种方式:一种是各设备自觉维护的分布式方式,另一种是在suspend过程中对所有设备进行suspend处理的集中管理方式。

    每个设备自觉维护本身的低功耗状态,不但在系统运行时更加节省功耗,同时也能加速系统进入suspend状态的流程。

    设备的低功耗状态有四种:

    状态 注释
    DEVICE_PM_ACTIVE_STATE 正常工作模式,设备上下文都保持。
    DEVICE_PM_LOW_POWER_STATE 设备自身维护设备上下文,不需要驱动恢复。
    DEVICE_PM_SUSPEND_STATE 设备丢失上下文,驱动需要保存然后恢复上下文。
    DEVICE_PM_OFF_STATE 对设备断电,上下文丢失,需要重新初始化设备。

    Device Model with Power Management Support

    在注册设备的时候,如果使能Device PM的话,需要实现功耗处理函数。

    DEVICE_DEFINE在初始化驱动的时候填充pm_control_fn,就提供了设备功耗管理的接口。

    如果设备不需要功耗管理接口,使用DEVICE_AND_API_INIT。默认功耗接口就是一个空函数device_pm_control_nop

    #define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, 
                  data, cfg_info, level, prio, api) 
        
        static struct device_config _CONCAT(__config_, dev_name) __used 
        __attribute__((__section__(".devconfig.init"))) = { 
            .name = drv_name, .init = (init_fn), 
            .device_pm_control = (pm_control_fn), 
            .config_info = (cfg_info) 
        }; 
        static struct device _CONCAT(__device_, dev_name) __used 
        __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { 
             .config = &_CONCAT(__config_, dev_name), 
             .driver_api = api, 
             .driver_data = data 
        }
    
    struct device_config {
        char    *name;
        int (*init)(struct device *device);
    #ifdef CONFIG_DEVICE_POWER_MANAGEMENT
        int (*device_pm_control)(struct device *device, u32_t command,
                      void *context);
    #endif
        const void *config_info;
    };

     每个驱动都需要实现device_pm_control,其中command是DEVICE_PM_SET_POWER_STATE或者DEVICE_PM_GET_POWER_STATE,用于设置或者获取当前设备功耗状态。context是device的功耗状态。

    Device Power Management API

     获取当前系统设备列表:

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

     设置当前设备状态:

    int device_set_power_state(struct device *device, u32_t device_power_state);

     获取当前设备状态:

    int device_get_power_state(struct device *device, u32_t * device_power_state);

     其他相关API:

    void device_busy_set(struct device *busy_dev)----------置当前设备忙位
    void device_busy_clear(struct device *busy_dev)--------清当前设备忙位
    int device_any_busy_check(void)------------------------检查所有设备忙状态
    int device_busy_check(struct device *chk_dev)----------检查当前设备忙位

      2.6 Zephyr PM配置

    Flag 解释
    CONFIG_SYS_POWER_MANAGEMENT 功耗管理子系统的开关
    CONFIG_TICKLESS_IDLE Tickless Idle功能开关
    CONFIG_SYS_POWER_LOW_POWER_STATE SYS_PM_LOW_POWER_STATE机制的开关
    CONFIG_SYS_POWER_DEEP_SLEEP SYS_PM_DEEP_SLEEP 机制的开关
    CONFIG_DEVICE_POWER_MANAGEMENT 各种外设的低功耗管理开关

      3 其他相关资料

    Zephyr Project Document 1.3.0介绍了Zephyr的开发环境、内核以及应用程序开发方方面面。

  • 相关阅读:
    朱晔和你聊Spring系列S1E10:强大且复杂的Spring Security(含OAuth2三角色+三模式完整例子)
    朱晔和你聊Spring系列S1E9:聊聊Spring的那些注解
    朱晔和你聊Spring系列S1E8:凑活着用的Spring Cloud(含一个实际业务贯穿所有组件的完整例子)
    朱晔和你聊Spring系列S1E7:简单好用的Spring Boot Actuator
    朱晔和你聊Spring系列S1E6:容易犯错的Spring AOP
    朱晔和你聊Spring系列S1E5:Spring WebFlux小探
    朱晔和你聊Spring系列S1E4:灵活但不算好用的Spring MVC
    朱晔和你聊Spring系列S1E3:Spring咖啡罐里的豆子
    朱晔和你聊Spring系列S1E2:SpringBoot并不神秘
    朱晔的互联网架构实践心得S1E10:数据的权衡和折腾【系列完】
  • 原文地址:https://www.cnblogs.com/arnoldlu/p/7650583.html
Copyright © 2011-2022 走看看