4.4.10. 低功耗模式调试指南

4.4.10.1. 概述与介绍

低功耗管理系统 (Low Power Management System) 旨在通过优化电子设备的能耗,减少能源消耗以延长电池续航。它通过对硬件和软件的调节,使设备在待机状态下保持最低能耗,同时在不同使用场景中实现最佳的功耗与性能平衡。

4.4.10.2. 低功耗调试详细介绍

本系统支持三种不同的模式下工作:关闭模式 (off mode)、睡眠模式 (sleep mode)、工作模式 (work mode)。根据对应的工作状态和应用,可分为九个子电源域:

  • AON (Always On) 电源域:始终保持开启状态。

  • DSP(DSP 子系统)电源域:与数字信号处理相关。

  • SOC(芯片顶层子系统)电源域:涉及芯片的顶层子系统功能。

  • CPU(CPU 子系统)电源域:包括 CPU 相关的电源管理。

  • BPU(BPU 子系统)电源域:与处理单元相关的电源域。

  • DDR(DDR 子系统)电源域:与内存子系统相关的电源域。

  • VIDEO(视频子系统)电源域:与视频处理相关的电源域。

  • GPU(GPU 子系统)电源域:与图形处理单元相关的电源域。

  • ISP(ISP 子系统)电源域:与图像信号处理相关的电源域。

下面表格描述了当前系统的电源域划分,包含了子电源域、默认电源状态和电源切换控制模式:

Sub Power Domain Primary Power Supply Logic Domain Switch Control Default Status
AON VDD_AON RTC PMIC ON
GPIO
PMU
AON_CRM
DSP_NOC
SRAM
SLCR
APB BUS
DSP VDD_DSP DSP_DMA PMIC OFF
DSP_AXI_NOC
APB BUS
Timer
I2C
12S x2
UART
PDM
SPI
dsp_crm
SRAM0/SRMA0 CTL
SRAM1/SRMA1 CTL
TZC-400
Mailbox
DSP.HIFI5 VDD_HIFI5_SW HIFI5 SW-SWT OFF
SOC VDD_SOC display PMIC ON
camera
GPU
EMMC
SDIO/SDIO CTL
USB2
USB3
GMAC
QSPI
DMA
WDT
SYS_CTRL
ADC
Timer
PVT
E-Fuse
SPI x6
UART x5
12C x5
GPIO x16
LPWM x8
SOC.VIDEO VDD_VIDEO_SW video SW-SWT OFF
SOC.ISP VDD_ISP_SW isp8000 SW-SWT ON
CPU VDD_CPU CPU_NOC PMIC ON
asynchronous bridge
debug block
CPU.COREO VDD_CORE0_SW A55 COREO SW-SWT ON
CPU.CORE1 VDD_CORE1_SW A55 CORE1 SW-SWT OFF
CPU.CORE2 VDD_CORE2_SW A55 CORE2 SW-SWT OFF
CPU.CORE3 VDD_CORE3_SW A55 CORE3 SW-SWT OFF
CPU.CORE4 VDD_CORE4_SW A55 CORE4 SW-SWT OFF
CPU.CORE5 VDD_CORE5_SW A55 CORE5 SW-SWT OFF
CPU.CORE6 VDD_CORE6_SW A55 CORE6 SW-SWT OFF
CPU.CORE7 VDD_CORE7_SW A55 CORE7 SW-SWT OFF
DDR VDD_DDR DDR PMIC OFF
BPU VDD_BPU BPU PMIC OFF
GPU VDD_BPU BPU PMIC OFF

从这个表格中可以看出一个低功耗管理系统中的各个子电源域的电源状态、控制方式和管理结构:

  • Sub Power Domain(子电源域):表示电源域的子区域名称,每个子电源域代表系统中一部分硬件的电源管理区域。例如, AON 电源域、 DSP 电源域、 SOC 电源域等。

  • Primary Power Supply(主要电源供应):表示该电源域的主要电源供应源,即为该子电源域提供电力的主要电源。例如, AON 电源域依赖 VDD_AON 电源, DSP 电源域依赖 VDD_DSP 电源等。

  • Logic Domain(逻辑功能域):表示该电源域所管理的逻辑功能区域。即在此电源域内,管理和控制的各种功能模块。例如, AON 电源域管理 RTC(实时时钟)、 GPIO(通用输入输出)、 PMU(电源管理单元)等;而 DSP 电源域则管理数字信号处理相关的模块如 DSP_DMA、 I2C、 UART 等。

  • Switch Control(电源切换控制):表示电源域的开关控制机制,通常涉及到如何启用或关闭电源域。例如, AON 电源域通过 PMIC 控制电源开关,而 DSP.HIFI5 电源域则通过 SW-SWT(软件开关)控制。

  • Default Status(默认状态):表示电源域在系统启动或默认情况下的电源状态( ON 或 OFF)。 ON 表示该电源域在默认状态下为开启, OFF 表示该电源域在默认状态下为关闭。例如, AON 电源域的默认状态是 ON,表示该区域始终保持开启状态;而 DSP 电源域的默认状态是 OFF,表示该区域通常在待机或不需要时关闭以节省能量。

系统的电源管理基于不同的工作模式,在每个模式下会启用不同的电源域:

  • OFF(关闭模式):此模式下所有电源域关闭。

  • SLEEP(睡眠模式):在此模式下, AON、 DSP 和 HIFI5 电源域保持开启,支持硬件唤醒( RTC、 GPIO、计数器唤醒)和语音唤醒。 HIFI5 看门狗中断也可以将系统唤醒到工作模式。

  • WORK(工作模式):在工作模式下, AON、 DSP、 SOC、 CPU 和 DDR 电源域必须开启。 HIFI5 和各个 CPU 核心( CORE0 到 CORE7 )以及其他子系统(如 BPU、 GPU、 ISP、 VIDEO)可根据需要选择开启或关闭。至少有一个 A55 核心处于开启状态。系统可以通过软件配置进入睡眠模式。

为了优化功耗,系统往往需要根据不同的工作负载动态调整资源的使用状态。两种常见且有效的低功耗管理方法是动态电压频率调整( Dynamic Voltage and Frequency Scaling, DVFS)和休眠唤醒机制。 DVFS 通过实时调整处理器的电压和频率,以适应不同的工作需求,从而在保证性能的前提下有效降低功耗。而休眠唤醒机制则通过使系统在不活动时进入低功耗状态,并在需要时快速唤醒,进一步优化电力消耗。接下来,将详细探讨这两种方法的工作原理与实现方式。

4.4.10.3. 动态电压频率调整

动态调频调压 (DVFS) 是一种根据系统负载动态调整处理器及其他组件的频率和电压的技术。 DVFS 可以有效降低在不需要高性能时的功耗,从而优化系统的能效。

芯片的功耗与工作电压、时钟频率以及环境温度密切相关。在负载保持不变的情况下,电压、时钟频率和环境温度的升高通常会导致功耗增加。因此,降低功耗的有效途径包括降低电压、降低时钟频率以及改善散热。本章所讨论的低功耗方法主要集中在对电压和时钟频率的调节与控制。

除了调节电压和频率,减轻负载也是降低功耗的有效手段,客户可根据自身产品需求优化电路设计。然而需要注意的是,进入低功耗状态可能会对系统性能造成一定的负面影响,因此,是否启用低功耗模式应根据具体的使用场景来决定。

调频调压方式

在本平台中, CPU、 GPU 3D、 BPU 以及 DDR 均支持调频功能,此外, CPU 还支持调压,以便实现更灵活的功耗管理。

CPU 调频调压

  • 板端路径/sys/devices/system/cpu/cpufreq/policy0/

  • 目前支持的频率

    root@buildroot:~# cat /sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies
    300000 600000 1200000 1500000
    

    查看当前 CPU 频率:

    cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq
    

    设置 CPU 频率,可以通过以下命令:

    # 设置 CPU 频率为 1200000
    echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    echo 1200000 >/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
    
  • 超频功能: CPU 提供超频功能,超频频率为 1.8G。

    • 启用超频:

    echo 1 >/sys/devices/system/cpu/cpufreq/boost
    echo performance >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    

    1.8G 超频时, CPU 工作电压为 1V,其余频点对应的工作电压为 850mV。

    注意:仅 X5H 支持超频, X5M 不可用超频。 芯片类型可通过以下命令查看,例如以下查询的芯片是X5M

    root@buildroot:~# cat /sys/class/socinfo/soc_name
    X5M
    

    注意:如果芯片类型是”UKNOWN”,则属于是早期出厂芯片,未在eFUSE中烧写对应bit,需要根据芯片丝印区分芯片类型。

  • 目前 CPU 支持的 governor 如下

    • performance:以最高频率运行。

    • ondemand:根据负载动态调整频率。

    • userspace:用户自定义频率。

    • powersave:以最低频率运行。

    • schedutil:结合 CPU 调度器动态调整频率(当前 CPU 的默认 governor)。

    调整 CPU 的 governor,可以通过以下命令:

    echo performance >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    echo ondemand >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    echo powersave >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    echo schedutil >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    

BPU 调频

  • 板端路径/sys/class/devfreq/3a000000.bpu

  • 目前支持的频率

    root@buildroot:~# cat /sys/class/devfreq/3a000000.bpu/available_frequencies
    500000000 1000000000
    

    查看当前 BPU 频率:

    cat /sys/class/devfreq/3a000000.bpu/cur_freq
    

    调整 BPU 频率命令如下:

    echo userspace >/sys/class/devfreq/3a000000.bpu/governor
    echo 500000000 >/sys/class/devfreq/3a000000.bpu/userspace/set_freq
    
  • BPU 支持的 governor 如下

    • userspace:根据客户的配置指定频率。

    • performance:设置为最高频率(当前 BPU 的默认 governor)。

    • powersave:以最低频率运行。

    调整 BPU 的 governor,可以通过以下命令:

    echo userspace >/sys/class/devfreq/3a000000.bpu/governor
    echo performance >/sys/class/devfreq/3a000000.bpu/governor
    echo powersave >/sys/class/devfreq/3a000000.bpu/governor
    

GPU 3D 调频

  • 板端路径/sys/class/devfreq/3c000000.gc8000

  • 目前支持的频率

    root@buildroot:~# cat /sys/class/devfreq/3c000000.gc8000/available_frequencies
    200000000 400000000 750000000 1000000000
    

    查看当前频率:

    cat /sys/class/devfreq/3c000000.gc8000/cur_freq
    

    调整 GPU 3D 频率命令如下:

    echo userspace >/sys/class/devfreq/3c000000.gc8000/governor
    echo 750000000 >/sys/class/devfreq/3c000000.gc8000/userspace/set_freq
    
  • GPU 3D 支持的 governor 如下:

    • userspace:根据客户的配置指定频率。

    • performance: GPU 3D 设置为最高频率。

    • powersave:以最低频率运行。

    • simple_ondemand:结合工作负载,按需调整频率。

    若要调整 GPU 3D 的 governor,可以通过以下命令

    echo userspace >/sys/class/devfreq/3c000000.gc8000/governor
    echo performance >/sys/class/devfreq/3c000000.gc8000/governor
    echo powersave >/sys/class/devfreq/3c000000.gc8000/governor
    echo simple_ondemand >/sys/class/devfreq/3c000000.gc8000/governor
    

DDR 调频

  • 板端路径/sys/class/devfreq/soc:ddrc-freq

  • 目前支持的频率

    root@buildroot:~# cat /sys/class/devfreq/soc:ddrc-freq/available_frequencies
    266000000 2133000000 2844000000 4266000000
    

    查看当前 DDR 频率:

    cat /sys/class/devfreq/soc\:ddrc-freq/cur_freq
    

    调整 DDR 频率命令如下:

    echo userspace >/sys/class/devfreq/soc:ddrc-freq/governor
    echo 266000000 >/sys/class/devfreq/soc:ddrc-freq/userspace/set_freq
    
  • DDR 支持的 governor 如下:

    • userspace:根据客户的配置指定频率。

    • performance: DDR 设置为最高频率。

    • simple_ondemand:根据 DDR 的负载调整频率。

    • powersave:以最低频率运行。

    若要调整 ddr 的 governor,可以通过以下命令:

    echo userspace >/sys/class/devfreq/soc\:ddrc-freq/governor
    echo performance >/sys/class/devfreq/soc\:ddrc-freq/governor
    echo simple_ondemand >/sys/class/devfreq/soc\:ddrc-freq/governor
    echo powersave >/sys/class/devfreq/soc\:ddrc-freq/governor
    

动态调整说明

基于负载的动态调整

在负载较低时,系统会自动降低处理器的频率和电压,以节省能源;而在负载较高时,系统则会自动提升频率和电压,以确保处理器能够满足性能需求。操作系统通过调度策略,动态地根据系统负载来选择合适的频率。

例如,当 CPU 负载较低时,ondemand governor 会将频率降低到最低可用频率,而当负载增大时,它会自动提升频率,以保持较高的性能。下面是一个基于负载自动调节的例子:

echo ondemand >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

此时,操作系统会根据 CPU 的负载自动调整频率,用户不需要手动干预。

基于温度的动态调整

温度也是影响功耗的重要因素之一。当芯片的温度过高时,可以配置使系统自动降低频率和电压,以避免过热,保护硬件并延长使用寿命。系统会通过 thermal 机制检测温度变化并触发相应的调整策略。

在本平台中,thermal 系统会定期监测处理器的温度,一旦超过设定的温度阈值(如 95 ° C),系统会自动调低 CPU 的频率和电压,以降低功耗并防止温度过高。这个过程是自动进行的,无需用户手动干预。

在这个过程中,温度变化会触发动态的频率和电压调整,确保系统在不同的工作环境下能够自动适应,达到最佳的功耗表现。关于温度的动态调整详细内容可以参考 驱动平台 thermal 系统调试说明 章节。

其他动态调整策略

除了温度和负载, DVFS 系统还可能依据其他因素,如系统功耗需求、可用资源等,动态地调整频率和电压。在许多情况下,这些调整是由硬件或操作系统调度器自动执行的,无需用户干预。这种自动调整使得系统在低功耗和高性能之间保持动态平衡,既可以应对突发的高负载需求,又能在空闲时节省能源。

例如,使用以下命令切换到 schedutil governor 时,系统会结合 CPU 调度器的决策来动态调整频率:

echo schedutil >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

当前,系统默认使用的即为 schedutil governor:

root@buildroot:~# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
schedutil

另外, CPU core 在不使用时,可以将其拔出,也可以进一步降低功耗,除了 core0 不支持 hotpulg, core1~core7 均支持 hotplug。具体方式如下:

echo 0 >/sys/devices/system/cpu/cpu1/online  #disable cpu1
echo 1 >/sys/devices/system/cpu/cpu1/online  #enable cpu1

移植和开发

内核配置

在移植 Linux 内核到新的硬件平台时,需要确保内核配置中启用了 DVFS 关的功能。以下是一些常见的内核配置选项:

DVFS 支持:

  • CONFIG_CPU_FREQ:启用 CPU 频率调整。

  • CONFIG_CPU_FREQ_STAT:启用 CPU 频率统计功能。

  • CONFIG_CPU_FREQ_GOV_PERFORMANCE:启用性能 governor。

  • CONFIG_CPU_FREQ_GOV_ONDEMAND:启用按需 governor。

  • CONFIG_CPU_FREQ_GOV_USERSPACE:启用用户空间 governor。

  • CONFIG_CPU_FREQ_GOV_POWERSAVE:启用节能 governor。

  • CONFIG_CPU_FREQ_GOV_SCHEDUTIL:启用与调度器结合的 governor。

CPU hotplug 支持:

  • CONFIG_HOTPLUG_CPU:启用 CPU hotplug 功能。

设备电源管理:

  • CONFIG_PM:启用电源管理支持。

  • CONFIG_PM_DEBUG:启用电源管理调试。

  • CONFIG_PM_ADVANCED_DEBUG:启用更详细的电源管理调试信息。

  • CONFIG_PM_TEST_SUSPEND:启用电源管理挂起测试功能。

  • CONFIG_PM_DEVFREQ:启用设备频率管理(devfreq)。

  • CONFIG_PM_DEVFREQ_EVENT:启用设备频率管理事件支持。

用户可以根据需要,使用 ./bd.sh boot menuconfig 来选择上述功能,例如配置如下:

CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_PM_DEBUG=y
CONFIG_PM_ADVANCED_DEBUG=y
CONFIG_PM_TEST_SUSPEND=y
CONFIG_PM_DEVFREQ=y
CONFIG_PM_DEVFREQ_EVENT=y

Linux Power Management 核心框架

Linux 的电源管理框架有两个主要部分:系统级电源管理设备电源管理

  • 系统级电源管理(System Power Management):管理系统整体的功耗状态,包括对 CPU 的空闲状态( C-state)、系统挂起( suspend)、休眠( hibernate)等状态的控制。它确保在系统空闲时, CPU 和其他关键硬件进入低功耗状态。

  • 设备电源管理(Device Power Management):管理外部设备的功耗,包括驱动程序如何管理硬件设备的电源开关、挂起、恢复等行为。

Linux 内核通过 PM 框架和设备驱动程序接口来协同工作。每个设备驱动都可以注册电源管理接口,告诉内核在何时启用或关闭设备电源,如何进入低功耗状态等。 Linux PM 框架具体如下图所示:

low_power-Linux_Power_software_framework

上图中可以看到一些与 DVFS 相关的 Linux 关键组件:

  • cpufreq 子系统

    cpufreq 是 Linux 内核中专门用于 CPU 调频的子系统。它提供了一个统一的接口,允许内核或用户空间应用程序动态调整 CPU 的频率。

    • 调频驱动:不同的硬件平台通常需要不同的调频驱动来支持 CPU 的调频操作。常见的驱动包括 intel_pstate(适用于 Intel 处理器)和 acpi-cpufreq(适用于支持 ACPI 的系统)。

    • 调度策略cpufreq 提供了几种调度策略,例如 ondemandconservativeperformancepowersave,每种策略根据系统负载动态调整频率。

  • cpuidle 子系统

    cpuidle 子系统管理 CPU 的空闲状态。通过将 CPU 置于不同的空闲状态,系统能够进一步降低功耗。cpuidlecpufreq 协同工作,当 CPU 进入空闲状态时,频率和电压会降低,以减少功耗。

  • devfreq 子系统

    devfreq 是一个用于控制设备(如 GPU、内存等)频率的子系统。它允许设备根据负载调节其频率,以实现低功耗运行。

Linux 系统中的 DVFS 流程通过调节 CPU 和其他硬件组件的频率与电压,实现功耗和性能的优化。具体而言,内核通过 cpufreq、 cpuidle、 devfreq 等子系统来管理这一过程,同时用户可以利用相关工具和接口对 DVFS 进行配置和优化。通过采用合理的 DVFS 策略, Linux 系统能够在确保性能的前提下,有效降低功耗。

DVFS 测试

以基于温度的动态调整为例,板端系统可以通过以下方式进行测试:

查看当前 CPU 调频温度阈值(默认是 95 ° C 开始调频):

root@buildroot:~# cat /sys/devices/virtual/thermal/thermal_zone1/trip_point_1_temp
95000

查看当前系统的的温度频率信息,可以看到当前 CPU 的频率已经是 1500MHz、 1200MHz,温度为 45.7 ℃ :

root@buildroot:~# hrut_somstatus 
=====================1=====================
temperature-->
        DDR      : 46.9 (C)
        BPU      : 45.6 (C)
        CPU      : 45.7 (C)
cpu frequency-->
              min(M)    cur(M)  max(M)
        cpu0    : 300   1500    1500
        cpu1    : 300   1200    1500
        cpu2    : 300   300     1500
        cpu3    : 300   1200    1500
        cpu4    : 300   1200    1500
        cpu5    : 300   1200    1500
        cpu6    : 300   1200    1500
        cpu7    : 300   300     1500
bpu status information---->
              min(M)    cur(M)  max(M)  ratio
        bpu0    : 500   1000    1000    0
ddr frequency information---->
              min(M)    cur(M)  max(M)
        ddr     : 266   4266    4266
GPU gc8000 frequency information---->
              min(M)    cur(M)  max(M)
        gc8000  : 200   1000    1000

设置 CPU 调频温度阈值为 45 ℃,触发 CPU 的调频机制:

echo 45000 > /sys/devices/virtual/thermal/thermal_zone1/trip_point_1_temp

再次查看当前的温度频率信息,可以看到当前 CPU 的频率已经变成了 300MHz,明显降低了功耗。这表明系统成功地根据温度变化进行了频率调整,从而有效地避免了过热,同时降低了功耗:

root@buildroot:~# hrut_somstatus 
=====================1=====================
temperature-->
        DDR      : 47.6 (C)
        BPU      : 46.4 (C)
        CPU      : 46.4 (C)
cpu frequency-->
              min(M)    cur(M)  max(M)
        cpu0    : 300   1500    1500
        cpu1    : 300   1200    1500
        cpu2    : 300   1200    1500
        cpu3    : 300   1200    1500
        cpu4    : 300   300     1500
        cpu5    : 300   1200    1500
        cpu6    : 300   1200    1500
        cpu7    : 300   1200    1500
bpu status information---->
              min(M)    cur(M)  max(M)  ratio
        bpu0    : 500   1000    1000    0
ddr frequency information---->
              min(M)    cur(M)  max(M)
        ddr     : 266   4266    4266
GPU gc8000 frequency information---->
              min(M)    cur(M)  max(M)
        gc8000  : 200   1000    1000

上述过程展示了基于温度的 DVFS 功能。系统能够在温度变化时动态调整处理器频率,以适应不同的功耗需求。此外,在实际使用中,其他系统组件(如 BPU、 DDR、 GPU)也能够根据实际需求进行频率调节,进一步优化整体功耗。

注意: 测试本功能时,需依据当前CPU的实际温度设定新的温度阈值。为触发 DVFS 响应,应将新阈值设置为低于当前温度值,以便系统检测到温度下降并相应调整频率。

DVFS 调频调压常见问题

  • 问题:调整 CPU 频率后,系统性能下降明显。

    • 解决方法:检查调整的频率是否在 CPU 支持的范围内,避免设置过低的频率。同时,可以尝试使用不同的 governor,例如 ondemandschedutil,以根据系统负载动态调整频率。

  • 问题:调整 GPU 频率后,出现图形渲染问题。

    • 解决方法:确保 GPU 驱动程序支持动态频率调整,并且调整的频率在 GPU 支持的范围内。同时,可以检查 GPU 的电压是否与频率匹配,避免因电压不足导致的渲染问题。

  • 问题:禁用 CPU 核心后,系统响应变慢。

    • 解决方法:根据系统的实际负载情况,合理配置 CPU 核心的启用和禁用策略。例如,在高负载时启用更多的 CPU 核心,在低负载时禁用部分 CPU 核心。同时,可以使用 isolcpus 参数将关键任务绑定到特定的 CPU 核心,以保证系统的响应速度。

4.4.10.4. 休眠唤醒

休眠唤醒机制是另一个常见的低功耗管理手段,它与 DVFS 密切结合。在系统处于空闲状态时,硬件组件会进入休眠模式,关闭不必要的电源,以减少功耗。当有外部事件触发时,系统会快速唤醒,恢复到正常工作状态,并根据当前的负载自动调整频率和电压。

本系统支持多种休眠模式,以降低功耗并在需要时可以快速恢复。当前支持的唤醒源包括 RTC 唤醒, GPIO 唤醒和 DSP 语音唤醒等。

休眠唤醒方式

休眠命令

休眠命令如下:

echo mem > /sys/power/state

该命令将触发系统进入 内存休眠 (mem) 模式,系统会暂停所有非必要的硬件和进程,但会将当前的内存状态保存到物理内存中,然后关闭处理器和其他硬件组件,进入较低功耗状态。一般通过按键等外部设备恢复。

唤醒命令

  • RTC 唤醒命令

    rtcwake -s 2 -m mem
    
    • -s:休眠时间,单位为秒;

    • -m:休眠模式(如 suspend to ram)。

  • GPIO 唤醒

    只有 AON 的 GPIO 可以作为唤醒源,如在 EVB 上,使用了 AON GPIO2 作为唤醒源,拉低 AON GPIO2 唤醒系统,在 dts 中需要将其配置为唤醒源。

    在设备树( DTS )中配置 AON GPIO 为唤醒源,如下:

    	gpio-keys {
    		compatible = "gpio-keys";
    		autorepeat;
    		pinctrl-names = "default";
    		pinctrl-0 = <&aon_gpio_2>;
    
    		key-power {
    			debounce-interval = <100>;
    			gpios = <&aon_gpio_porta 2 GPIO_ACTIVE_LOW>;
    			label = "GPIO Key Power";
    			linux,code = <KEY_POWER>;
    			wakeup-source;
    		};
    	};
    

    拉低 AON GPIO2 即可唤醒系统。用户可以根据自身硬件设计,将对应的 GPIO 配置为唤醒源。

移植和开发

内核配置

在移植 Linux 内核到新的硬件平台时,需要确保内核配置中启用了休眠唤醒支持相关的功能。以下是所需的内核配置选项:

  • CONFIG_SUSPEND:启用系统休眠支持。

用户可以在编译时使用 ./bd.sh boot menuconfig 来选择和配置这些功能。

Linux 系统休眠 / 恢复流程概述

Linux 系统的休眠主要分为 挂起(Suspend)休眠(Hibernate) 两种模式。挂起模式将系统状态保存在内存中( STR, Suspend to RAM),硬件进入低功耗状态;休眠模式将系统状态保存到磁盘上,完全关闭电源,恢复时从磁盘加载系统状态。

系统休眠的基本流程包括以下几个步骤:

  1. 准备挂起

    • 调用 pm_suspend() 函数,将系统切换到挂起状态。

    • 在调用 pm_suspend() 之前, Linux 内核会执行一系列的准备工作,如停止正在运行的进程、关闭不必要的设备等。

  2. 保存系统状态

    • 系统调用 suspend_devices() 来挂起所有支持的设备。

    • 调用 platform_suspend() 保存平台特定的硬件状态。

  3. 进入低功耗状态

    • 一旦所有设备和系统状态都被保存, CPU 会进入低功耗状态。此时,系统大部分硬件都处于挂起状态,只有必要的硬件(如内存)保持工作。

  4. 恢复系统状态

    • 当系统从休眠或挂起状态恢复时,调用 resume_devices() 恢复所有设备的状态。

    • 内核会重新启动所有进程,并从内存或硬盘加载系统状态,恢复到休眠前的工作状态。

而在 Linux 系统从 挂起(Suspend)休眠(Hibernate) 状态恢复时,系统需要一系列的步骤来重新启动设备并恢复之前保存的状态。恢复流程的关键是从低功耗状态或磁盘中加载系统的工作状态,确保设备和进程能够如预期地恢复运行。

系统恢复的基本流程包括以下几个步骤:

  1. 准备恢复

    • 系统从低功耗状态或磁盘恢复后,首先会调用 pm_resume() 函数,开始恢复系统。

    • 在调用 pm_resume() 之前, Linux 内核会执行一系列准备工作,如重新激活需要的硬件、恢复系统状态等。

  2. 恢复系统状态

    • 系统调用 resume_devices() 来恢复所有设备的状态。此过程会根据设备的驱动程序恢复其工作状态。

    • 对于挂起( Suspend)模式,设备的状态保存在内存中,因此需要从内存中恢复设备的状态。

    • 对于休眠( Hibernate)模式,系统从硬盘读取保存的系统状态,并恢复到休眠前的状态。

  3. 恢复进程和内存状态

    • 系统从挂起或休眠状态恢复后,内核会恢复所有进程的状态,确保每个进程能够从暂停状态继续执行。

    • 对于休眠模式,内核会从磁盘上的休眠镜像中加载进程和内存的状态,恢复到系统休眠前的状态。

  4. 设备恢复和初始化

    • 恢复过程不仅仅是恢复内存和进程,所有硬件设备也需要重新初始化。具体而言:

      • 对于 PCI 设备、 USB 控制器等硬件设备,系统会通过调用设备的 resume 方法来重新启用设备。

      • 驱动程序会确保硬件设备恢复到正确的工作状态,例如重新启用中断、恢复数据传输等。

  5. 系统恢复完成

    • 恢复过程中,所有设备被恢复到正常工作状态,内存中的数据被恢复,进程重新启动并继续执行。

    • 系统恢复完成后,用户可以继续使用计算机,系统状态与休眠前基本相同。

系统的休眠与恢复流程如下图所示:

log_buf_size

Linux 系统中休眠的流程涉及到用户空间程序,内核空间, Secure Monitor 三个部分,三者之间相互配合完成休眠操作。该过程可以描述如下图:

low_power-Linux_Power_software_framework

从上图可以将休眠与唤醒中电源管理工作流程概括如下:

  • 应用程序通过特定的接口与 Linux PM 交互, Linux PM 通过 PM API 与设备驱动和核心服务交互,最终影响硬件的电源状态。

  • Secure Monitor 在整个过程中起到监控和保护的作用,确保电源管理的安全性。

以下是对图中各部分的说明:

  1. Hobot 软件(蓝色)

    • Power Manager Services:负责管理电源的软件服务。

    • App1 和 App2:应用程序,其中 App2 没有 CAP_BLOCK_SUSPEND 权限,因此不能调用 /sys/power/wake_unlock 接口。

  2. Linux 内核软件(绿色)

    • autosleep work:自动休眠的工作机制,可能用于在系统空闲时自动进入低功耗状态。

    • Linux PM(电源管理):核心的电源管理模块,负责协调系统的电源状态。

    • Driver1 和 Driver2:设备驱动程序,一般用于管理特定硬件的电源状态。

    • CPU Driver (PSCI): CPU 驱动,使用 PSCI( Power State Coordination Interface)接口来管理 CPU 的电源状态。

    • Others Core Services:其他核心服务,一般包括系统日志、安全监控等。

  3. 接口

    • /sys/power/autosleep:用于设置或查询自动休眠的接口。

    • /sys/power/wake_unlock:用于解锁唤醒源的接口, App2 由于权限问题无法使用。

  4. Secure Monitor(安全监控)

    • 负责监控和管理硬件层面的电源状态,确保系统的安全和稳定。

  5. Hardware(硬件)

    • 底层硬件,与软件层交互以实现电源管理功能。

系统休眠和唤醒测试

进行 GPIO 睡眠唤醒测试,测试命令如下:

# 准备打印日志
dmesg -w&
# 系统休眠
echo mem > /sys/power/state

输入以上指令时,系统将会进入休眠状态,在此时按下板端的 wakeup 按键即可唤醒。

在 X5 EVB 板端, wakeup 按键位置可以参考 功能模块布局 章节中查看“接口 6 复位功能按键”(以 EVB 1_b 为例)。

按下 wakeup 按键唤醒系统后,系统睡眠与唤醒过程的日志如下:

root@buildroot:~# dmesg -w&
root@buildroot:~# echo mem > /sys/power/state
NOTICE:  mmu enabled from [LIGHT] sleep, pll: 1:1:1:1:1:0 relock: 0:0:0:0:0:0
[   69.484694] hobot_gmac 35010000.horizon_tsn eth0: mac_config_rx_queues_routing, not support packet mode :
[   69.644730] usb usb1: root hub lost power or was reset
[   69.644736] usb usb2: root hub lost power or was reset
[   69.928800] random: crng reseeded on system resumption
[   69.145044] PM: suspend entry (deep)
[   69.148213] Filesystems sync: 0.003 seconds
[   69.149837] Freezing user space processes
[   69.150455] remoteproc remoteproc0: clr: 866
[   69.150475] remoteproc remoteproc0: clr: 866,  0   866
[   69.151679] Freezing user space processes completed (elapsed 0.001 seconds)
[   69.151699] OOM killer disabled.
[   69.151707] Freezing remaining freezable tasks
[   69.153204] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[   69.153223] printk: Suspending console(s) (use no_console_suspend to debug)
[   69.154767] HOBOT GDC 3d0c0000.gdc: hobot_gdc_suspend
[   69.154860] hobot-sif 3d050000.sif: cim_suspend
[   69.154874] hobot-sif 3d040000.sif: cim_suspend
[   69.154887] hobot-sif 3d030000.sif: cim_suspend
[   69.154900] hobot-sif 3d020000.sif: cim_suspend
[   69.154971] hobot_vpu_dev: [VPUDRV]vpu_suspend:7842: [-]vpu_suspend leave
[   69.154981] hobot_jpu_dev: [JPUDRV]jpu_suspend:3833: [+]jpu_suspend enter
[   69.154985] hobot_jpu_dev: [JPUDRV]jpu_suspend:3834: [-]jpu_suspend leave
[   69.195792] hobot-dsp dsp0: hobot_dsp_suspend dsp0
[   69.195884] vin mipi0: drivers/media/platform/horizon/camsys/mipi/hobot_mipi_host_ops.c:hobot_mipi_host_suspend_do enter suspend...
[   69.195893] vin mipi2: drivers/media/platform/horizon/camsys/mipi/hobot_mipi_host_ops.c:hobot_mipi_host_suspend_do enter suspend...
[   69.195900] vin mipi3: drivers/media/platform/horizon/camsys/mipi/hobot_mipi_host_ops.c:hobot_mipi_host_suspend_do enter suspend...
[   69.202999] CAM_SUBSYS soc:cam:cam_sys@0: camsys_suspend
[   69.203140] vin mipi1: drivers/media/platform/horizon/camsys/mipi/hobot_mipi_host_ops.c:hobot_mipi_host_suspend_do enter suspend...
[   69.203151] [INFO][HOBOT_OSD](hb_osd_suspend) done
[   69.203172] [CODEC_NODE]:[L731]hobot_codec_node_suspend 731
[   69.203281] PM: suspend devices took 0.050 seconds
[   69.205883] Disabling non-boot CPUs ...
[   69.206416] psci: CPU1 killed (polled 0 ms)
[   69.207251] psci: CPU2 killed (polled 0 ms)
[   69.208016] psci: CPU3 killed (polled 0 ms)
[   69.208612] psci: CPU4 killed (polled 0 ms)
[   69.209135] psci: CPU5 killed (polled 0 ms)
[   69.209687] psci: CPU6 killed (polled 0 ms)
[   69.211256] psci: CPU7 killed (polled 0 ms)
[   69.211484] Enabling non-boot CPUs ...
[   69.222647] Detected VIPT I-cache on CPU1
[   69.222707] GICv3: CPU1: found redistributor 100 region 0:0x0000000030160000
[   69.222741] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
[   69.223109] CPU1 is up
[   69.234201] Detected VIPT I-cache on CPU2
[   69.234235] GICv3: CPU2: found redistributor 200 region 0:0x0000000030180000
[   69.234259] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
[   69.234559] CPU2 is up
[   69.245647] Detected VIPT I-cache on CPU3
[   69.245679] GICv3: CPU3: found redistributor 300 region 0:0x00000000301a0000
[   69.245699] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
[   69.246028] CPU3 is up
[   69.257116] Detected VIPT I-cache on CPU4
[   69.257151] GICv3: CPU4: found redistributor 400 region 0:0x00000000301c0000
[   69.257174] CPU4: Booted secondary processor 0x0000000400 [0x412fd050]
[   69.257509] CPU4 is up
[   69.268597] Detected VIPT I-cache on CPU5
[   69.268645] GICv3: CPU5: found redistributor 500 region 0:0x00000000301e0000
[   69.268667] CPU5: Booted secondary processor 0x0000000500 [0x412fd050]
[   69.269009] CPU5 is up
[   69.280099] Detected VIPT I-cache on CPU6
[   69.280148] GICv3: CPU6: found redistributor 600 region 0:0x0000000030200000
[   69.280171] CPU6: Booted secondary processor 0x0000000600 [0x412fd050]
[   69.280538] CPU6 is up
[   69.291624] Detected VIPT I-cache on CPU7
[   69.291673] GICv3: CPU7: found redistributor 700 region 0:0x0000000030220000
[   69.291695] CPU7: Booted secondary processor 0x0000000700 [0x412fd050]
[   69.292097] CPU7 is up
[   69.306467] [CODEC_NODE]:[L751]hobot_codec_node_resume 751
[   69.306487] [INFO][HOBOT_OSD](hb_osd_resume) done
[   69.306494] vin mipi1: drivers/media/platform/horizon/camsys/mipi/hobot_mipi_host_ops.c:hobot_mipi_host_resume_do enter resume...
[   69.306575] CAM_SUBSYS soc:cam:cam_sys@0: camsys_resume
[   69.484694] hobot_gmac 35010000.horizon_tsn eth0: mac_config_rx_queues_routing, not support packet mode :\x02
[   69.484746] hobot_gmac 35010000.horizon_tsn eth0: configuring for phy/rgmii-id link mode
[   69.524503] vin mipi3: drivers/media/platform/horizon/camsys/mipi/hobot_mipi_host_ops.c:hobot_mipi_host_resume_do enter resume...
[   69.524512] vin mipi2: drivers/media/platform/horizon/camsys/mipi/hobot_mipi_host_ops.c:hobot_mipi_host_resume_do enter resume...
[   69.524518] vin mipi0: drivers/media/platform/horizon/camsys/mipi/hobot_mipi_host_ops.c:hobot_mipi_host_resume_do enter resume...
[   69.524826] hobot-dsp dsp0: hobot_dsp_resume dsp0
[   69.644730] usb usb1: root hub lost power or was reset
[   69.644736] usb usb2: root hub lost power or was reset
[   69.647123] hobot_jpu_dev: [JPUDRV]jpu_resume:3862: [+]jpu_resume enter
[   69.647129] hobot_jpu_dev: [JPUDRV]jpu_resume:3863: [-]jpu_resume leave
[   69.647137] hobot_vpu_dev: [VPUDRV]vpu_resume:7887: [+]vpu_resume enter
[   69.647141] hobot_vpu_dev: [VPUDRV]vpu_resume:8033: [-]vpu_resume leave
[   69.702201] hobot-sif 3d020000.sif: cim_resume
[   69.702213] hobot-sif 3d030000.sif: cim_resume
[   69.702224] hobot-sif 3d040000.sif: cim_resume
[   69.702234] hobot-sif 3d050000.sif: cim_resume
[   69.702299] HOBOT GDC 3d0c0000.gdc: hobot_gdc_resume
[   69.906154] PM: resume devices took 0.600 seconds
[   69.926659] OOM killer enabled.
[   69.926675] Restarting tasks ... done.
[   69.928800] random: crng reseeded on system resumption
[   69.934105] PM: suspend exit
[   69.968824] remoteproc remoteproc0: new: 866, 0   0

以下是对日志的详细分析:

1 ) 休眠过程

  • 进入休眠

    • echo mem > /sys/power/state:该命令将系统置于休眠状态,具体是“深度休眠”( deep sleep)。

    • PM: suspend entry:系统开始进入休眠状态。

  • 文件系统同步

    • Filesystems sync: 0.003 seconds:在进入休眠之前,系统进行了文件系统的同步,确保所有数据写入磁盘。

  • 冻结用户空间进程

    • Freezing user space processes:系统冻结用户空间进程,防止在休眠期间进程状态变化。

    • Freezing user space processes completed (elapsed 0.001 seconds):冻结过程完成。

  • 禁用非引导 CPU

    • Disabling non-boot CPUs ...:系统禁用非引导 CPU(即除了引导 CPU 以外的其他 CPU),以节省功耗。

2 ) 设备挂起

  • 设备挂起

    • 多个设备的挂起操作被记录,例如:

      • hobot_gdc_suspendcim_suspendvpu_suspendjpu_suspend 等,表明这些设备在进入休眠状态时被挂起。

    • PM: suspend devices took 0.050 seconds:设备挂起操作耗时 50 毫秒。

3 ) 恢复过程

  • 恢复设备

    • PM: resume devices took 0.600 seconds:恢复设备的过程耗时 600 毫秒。

    • 设备恢复的日志信息表明多个设备(如 hobot_gdc_resumecim_resumevpu_resumejpu_resume 等)被重新激活。

  • 重新启用非引导 CPU

    • Enabling non-boot CPUs ...:系统重新启用之前禁用的非引导 CPU。

    • 日志中显示每个 CPU 的启动信息,例如 CPU1 is up,表明 CPU 已成功恢复。

4 ) 其他事件

  • USB 设备状态

    • usb usb1: root hub lost power or was reset: USB 根集线器在休眠或恢复过程中失去电源或被重置,这可能影响 USB 设备的正常工作。

  • 随机数生成器

    • random: crng reseeded on system resumption:在系统恢复时,随机数生成器被重新播种,这是确保系统安全性的一部分。

  • OOM Killer

    • OOM killer disabledOOM killer enabled:在休眠期间禁用了 OOM( Out Of Memory)杀手,以防止在低内存情况下杀死进程,而在恢复后重新启用。

休眠唤醒常见问题

  • 问题:系统休眠后无法正常唤醒。

    • 解决方法:检查休眠唤醒源的配置是否正确,例如 RTC 唤醒的设置是否正确, GPIO 唤醒的 GPIO 引脚是否配置为唤醒源。同时,可以检查系统日志,查看休眠和唤醒过程中是否有错误信息或异常情况。

  • 问题:休眠唤醒后,系统性能下降。

    • 解决方法:在系统唤醒后,检查设备和驱动程序的状态是否正常,确保所有设备和驱动程序都正确地恢复了工作状态。同时,可以尝试调整休眠唤醒的策略,例如使用不同的休眠方式或调整休眠时间,以减少对系统性能的影响。

4.4.10.5. 典型场景功耗

以 X5 EVB 主板为例,以下是典型应用场景功耗数据

  • 硬件环境: X5 EVB 主板

  • 场景负载

    • 8x CPU @ 1.5G,负载 80%

    • 1x BPU @ 1.0G,负载 80%

    • LPDDR4 @ 3200MHz,带宽 100%

    • 双路 Camera 接入,负载 2x 1080p @ 30fps

  • 测试方法

    • 结温85度下,统计 X5 芯片各路电源的平均电流数据

  • 测试结果

    • X5芯片平均功耗最大值为 4335mW

Voltage Domains Voltage(V) Avg Current(mA) Avg Power(mW)
CH0 SOC_1V8 1.8 16 28.8
CH1 DDR_0V8 0.8 817 653.6
CH2 GPU_0V8 0.8 0 0
CH3 SOC_0V8 0.8 992 793.6
CH4 DSP_0V8 0.8 80 64
CH5 18_DSP 1.8 4 7.2
CH6 CSI_0V8 0.8 4 3.2
CH7 SOC_3V3 3.3 0 0
CH8 DSI_0V8 0.8 0 0
CH9 AON_0V8 0.8 7 5.6
CH10 AON_1V8 1.8 0 0
CH11 18_SOC 1.8 40 72
CH12 USB_3V3 3.3 28 92.4
CH13 CSI_1V8 1.8 4 7.2
CH14 USB_0V8 0.8 28 22.4
CH15 BPU_0V8 0.8 1033 826.4
CH16 DDR_1V1 1.1 639 702.9
CH17 CPU_0V8 0.8 1295 1036
CH18 VDDA_1V 1.8 4 7.2
CH19 DDR_PLL 1.8 4 7.2
CH20 DSI_1V8 1.8 0 0
CH21 ADC_1V8 1.8 3 5.4
Total Power 4335.1

注意事项

以上表格所列电源域,可通过 X5 EVB 原理图 PMIC 和 Power Combine 小节找到硬件对应位置,用户可将电流探头串入对应电路获取电流与功耗。

low_power-PMIC

low_power-Power_Combine