加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • cpuidle framework
    • 数据结构
    • 流程
    • PSCI
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

CPU 进入 IDLE 都做了啥?

2022/01/10
1703
阅读需 11 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

cpuidle framework

每一个 CPU 核心都会有一个 idle 进程,idle 进程是当系统没有调度 CPU 资源的时候,会进入 idle 进程,而 idle 进程的作用就是不使用 CPU,以此达到省电的目的。

在ARM64架构中,当CPU Idle时,会调用WFI指令(wait for interrupt),关掉CPU的Clock以便降低功耗,当有外设中断触发时,CPU又会恢复回来。

cpuidle core 是 cpuidle framework 的核心模块,负责抽象出 cpuidle device、cpuidle driver 和 cpuidle governor 三个实体,如下所示:

 

cpuidle core 抽象出了 cpuidle device、cpuidle driver 和 cpuidle governor 三个数据结构。

数据结构

cpuidle_device

针对每个CPU核都对应一个struct cpuidle_device结构,主要字段介绍如下

struct cpuidle_device {
 //该cpu核是否注册进内核中
 unsigned int  registered:1;
 //该cpu核是否已经使能
 unsigned int  enabled:1;
 unsigned int  use_deepest_state:1;
 //对应的cpu number
 unsigned int  cpu;

 //该cpu核上一次停留在cpuidle状态的时间(us)
 int   last_residency;
 //记录每个cpuidle状态的统计信息,包括是否使能、进入该cpuidle状态的次数,停留在该cpuidle状态的总时间(us)
 struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
  ......
};

对应的注册接口是 cpuidle_register_device。

cpuidle_driver

cpuidle driver用于驱动一个或多个CPU核,关键字段描述如下:

struct cpuidle_driver {
 const char  *name;
 struct module   *owner;
 int                     refcnt;

 //用于驱动注册时判断是否需要设置broadcast timer
 unsigned int            bctimer:1;
 //用于描述cpuidle的状态,需要按照功耗从大到小来排序,具体有多少个cpuidle状态
 struct cpuidle_state states[CPUIDLE_STATE_MAX];
  ......
};

//CPU有多种不同的idle级别。这些idle级别有不同的功耗和延迟,从而可以在不同的场景下使用
//主要包括exit_latency、power_usage、target_residency。这些特性是governor制定idle策略的依据
struct cpuidle_state {
 char  name[CPUIDLE_NAME_LEN];
 char  desc[CPUIDLE_DESC_LEN];

 unsigned int flags;
 //CPU从该idle state下返回运行状态的延迟,单位为us。它决定了CPU在idle状态和run状态之间切换的效率,如果延迟过大,将会影响系统性能;
 unsigned int exit_latency; /* in US */
 //CPU在该idle state下的功耗,单位为mW
 int  power_usage; /* in mW */
 //期望的停留时间,单位为us。进入和退出idle state是需要消耗额外的能量的,如果在idle状态停留的时间过短,节省的功耗少于额外的消耗,则得不偿失。governor会根据该字段,结合当前的系统情况(如可以idle多久),选择idle level;
 unsigned int target_residency; /* in US */
 bool  disabled; /* disabled on all CPUs */

 //进入该state的回调函数
 int (*enter) (struct cpuidle_device *dev,
   struct cpuidle_driver *drv,
   int index);

 //CPU长时间不需要工作时(称作offline),可调用该回调函数。
 int (*enter_dead) (struct cpuidle_device *dev, int index);
  ......
};

对应的注册接口是 cpuidle_register_driver。

cpuidle_governor

governor 结构主要提供不同的回调函数,最终由 menu_governor 填充,主要字段如下:

struct cpuidle_governor {
 char   name[CPUIDLE_NAME_LEN];
 struct list_head  governor_list;
 //governor的级别,正常情况下,kernel会选择系统中rating值最大的governor作为当前governor
 unsigned int  rating;

  //在设备驱动注册和注销的时候调用
 int  (*enable)  (struct cpuidle_driver *drv,
     struct cpuidle_device *dev);
 void (*disable)  (struct cpuidle_driver *drv,
     struct cpuidle_device *dev);

 //根据当前系统的运行状况,以及各个idle state的特性,选择一个state(即决策)
 int  (*select)  (struct cpuidle_driver *drv,
     struct cpuidle_device *dev,
     bool *stop_tick);
 //通过该回调函数,可以告知governor,系统上一次所处的idle state是哪个
 void (*reflect)  (struct cpuidle_device *dev, int index);
};

对应的注册接口是 cpuidle_register_governor。

流程

我们先看下设备和驱动的注册过程:

注册之后便将设备和驱动建立起连接关系了,最终 cpuidle framework 的用户便可通过接口来调用下层的接口,进而完成具体的硬件操作。

下面看下 CPU 进入 idle 状态的流程图:

可以看出,最终是通过 PSCI 来实现 CPU 的 suspend。

PSCI

PSCI, Power State Coordination Interface,由ARM定义的电源管理接口规范,通常由Firmware来实现,而Linux系统可以通过smc/hvc指令来进入不同的Exception Level,进而调用对应的实现。

PSCI 支持如下功能:

  • CPU hotplug (on/off)CPU idle (suspend/resume)System suspend/resumeSystem shutdown and reset

每个功能和ATF之间的调用接口如下所示:

 

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
P82B715TD,118 1 NXP Semiconductors P82B715 - I2C-bus extender SOIC 8-Pin

ECAD模型

下载ECAD模型
$4.97 查看
ATXMEGA128A3U-AU 1 Microchip Technology Inc IC MCU 8BIT 128KB FLASH 64TQFP

ECAD模型

下载ECAD模型
$8.03 查看
AT32UC3A0512-ALUT 1 Microchip Technology Inc IC MCU 32BIT 512KB FLASH 144LQFP

ECAD模型

下载ECAD模型
$11.33 查看

相关推荐

电子产业图谱