ZYNQ-Linux配置休眠(Suspend)和唤醒(wake-up)
Linux下配置zynq的休眠和唤醒
说明
Zynq-7000 SoC是针对⼤多数嵌⼊式应⽤的器件,凭借ARM处理与FPGA逻辑之间的⾼集成度以及I/O可编程性,借助Xilinx提供的开发⼯具试的软硬件⼯程师能够更好的协调⼯作,缩短开发时间。
借助Petalinux⼯具能够让zynq很⽅便的在Linux⼯作,在Linux下唯⼀不太友好的就是zynq的功耗⾼,芯⽚发热较⼤,所以让zynq合理的休眠显得尤为重要。
开发环境
1. PC:Windows 10;
2. 虚拟机:Ubuntu 16.04;
3. Vivado:2018.2;
4. PetaLinux:2018.2;
5. 硬件环境:zynq7010;
休眠和唤醒介绍
参照UG585资料⾥关于Sleep Mode 以及Wake-up介绍
关于Sleep Mode
Sleep Mode
Sleep mode is defined at the system level to include the APU in standby mode and multiple controllers being held in reset without a clock.
Going into sleep mode can greatly reduce power consumption. In sleep mode, most function clock groups are turned off or powered off. The only required active devices are one CPU, the snoop control unit (SCU), and a wake-up device.
Ideally, the only devices causing dynamic power consumption should be the SCU and the wake-up peripheral device.
The wake-up device can be UART, GPIO, or any device that can generate an interrupt.
If the wake-up device is an AXI bus master, which can start transactions targeting the DRAM,additional limitations apply. Because the whole interconnect and the DDR memory are in low power modes and inaccessible, it must be assured that the CPU goes through the full wake-up process before any transactions to the DRAM take place. This guarantees that potential transactions targeting the DRAM are served correctly.
⽂中提到进⼊休眠模式可以⼤⼤降低功耗, 在睡眠模式下,⼤多数功能时钟组均已关闭。 唯⼀需要的活动设备是⼀个CPU,侦听控制单元(SCU)和唤醒设备。 理想情况下,引起动态功耗的唯⼀设备应该是SCU和唤醒外围设备。 唤醒设备可以是UART,GPIO或任何可以产⽣中断的设备。
关于Wake-up
Setup Wake-up Events
Every interrupt signaled to the PS can be used as a wake-up event. To make this happen, the wanted interrupt must be enabled in the peripheral and the GIC. A wake-up device must be able to generate the interrupt in sleep mode, which means, that its clocks might not be gated off. See GPIO as Wake-up Event, page 389 for more information.
Refer to the respective chapter for information about available interrupts and how to configure the peripherals to generate them.
能够通知PS端的每个中断都可以⽤作唤醒事件。 为此,必须在外围设备和GIC中启⽤所需的中断。 唤醒设备必须能够在睡眠模式下产⽣中断,这意味着其时钟可能不会被关闭。
裸机下休眠和唤醒
Enter sleep mode
Enter Sleep Mode
A CPU must execute the following steps to enter sleep mode from normal run mode:
1. Disable interrupts. Execute cpsid if.
2. Configure wake-up device.
3. Enable L2 cache dynamic clock gating. 15_power_ctrl[dynamic_clk_gating_en] = 1.
4. Enable SCU standby mode. Set mpcore.SCU_CONTROL_REGISTER[SCU_standby_enable] = 1.
5. Enable topswitch clock stop. Set slcr.TOPSW_CLK_CTRL[CLK_DIS] = 1.
6. Enable Cortex-A9 dynamic clock gating. Set
cp15.power_control_register[dynamic_clock_gating] = 1.
7. Put the external DDR memory into self-refresh mode. Refer to section 10.9.6 DDR Power Reduction.
8. Put the PLLs into bypass mode. Set slcr.{ARM, DDR, IO}_PLL_CTRL[PLL_BYPASS_FORCE] = 1.
9. Shut down the PLLs. Set slcr.{ARM, DDR, IO}_PLL_CTRL[PLL_PWRDWN] = 1.
10. Increase the clock divisor to slow down the CPU clock. Set slcr.ARM_CLK_CTRL[DIVISOR] = 0x3f.
11. Execute the wfi instruction to enter WFI mode.
Exit sleep mode
Exiting sleep mode is triggered by the configured interrupt occurring. The interrupt wakes up the CPU which resumes execution. The newly starting activity also triggers the topswitch, SCU, and L2 cache controller to leave their idle states and continue normal operation. The procedure for waking up is outlined below.
To exit from sleep mode:
1. Restore CPU clock divisor setting. Set slcr.ARM_CLK_CTRL[DIVISOR] = original value.
2. Power on the PLLs. Set slcr.{ARM, DDR, IO}_PLL_CTRL[PLL_PWRDWN] = 0.
3. Wait for PLL power-on and lock. Wait for slcr.PLL_STATUS[{ARM, DDR, IO}_PLL_LOCK] = 1.
4. Disable PLL bypass mode. Set slcr.{ARM, DDR, IO}_PLL_CTRL[PLL_BYPASS_FORCE] = 0.
5. Disable L2 cache dynamic clock gating. 15_power_ctrl[dynamic_clk_gating_en] = 0.
6. Disable SCU standby mode. Set mpcore.SCU_CONTROL_REGISTER[SCU_standby_enable] = 0.
7. Disable Interconnect clock stop. Set slcr.TOPSW_CLK_CTRL[CLK_DIS] = 0.
8. Disable Cortex-A9 dynamic clock gating. Set cp15.power_control_register[dynamic_clock_gating] = 0.
9. Enable all required peripheral devices, including DDR controller clocks.
10. Re-enable and serve interrupts. Execute cpsie if.
裸机下进⼊休眠需要按照步骤配置各个寄存器的状态。显得⽐较繁琐,在linux下相对简单⼀些,通过正确配置内核,采⽤指令形式进⼊休眠状态。
linux下的sleep函数
Linux下休眠和唤醒
参照Xilinx的wiki⼿册,Linux下通过配置内核,很容易进⼊休眠状态。唤醒⽅式同上⾯⼀样,通过指定的Uart或者GPIO唤醒。
Linux下Suspend
通过配置内核命令
petalinux-config -c kernel
使能如下的内核选项配置
CONFIG_THERMAL
CONFIG_CPU_THERMAL
CONFIG_CPU_FREQ
CONFIG_CPU_FREQ_GOV_PERFORMANCE
CONFIG_CPU_FREQ_GOV_POWERSAVE
CONFIG_CPU_FREQ_GOV_USERSPACE
CONFIG_CPU_FREQ_GOV_ONDEMAND
CONFIG_CPU_FREQ_GOV_CONSERVATIVE
CONFIG_CPU_FREQ_STAT
CONFIG_CPU_FREQ_STAT_DETAILS
CONFIG_CPUFREQ_DT
CONFIG_CPU_IDLE
CONFIG_CPU_IDLE_GOV_LADDER
CONFIG_CPU_IDLE_GOV_MENU
CONFIG_PM_SLEEP
配置完成后保存退出。
执⾏petalinux-build编译⼯程,编译完成后,把BOOT.BIN和zynq_fsbl.elf⽂件烧写到⽬标板。
启动⽬标板,执⾏
echo mem > /sys/power/state
zynq进⼊休眠状态:
Linux下Wake-up
Wake on UART
先通过命令指定⼀路uart为唤醒设备,当指定的uart上有中断产⽣,zynq被唤醒。本⽂通过使能调试串⼝uart0为唤醒设备进⾏测试,正常休眠之后,因为uart0会有中断产⽣,zynq会马上被唤醒。
先使能uart0为唤醒设备:
echo enabled > /sys/devices/soc0/amba/e0000000.serial/tty/ttyPS0/power/wakeup
再执⾏休眠指令:
echo mem > /sys/power/state
看到zynq休眠后⽴即被唤醒。
Wake on GPIO
按照wiki上配置GPIO,发现没有wakeup的配置项
GPIO-Keys Driver
在wiki/Linux Drivers/Linux GPIO Driver下查到GPIO-Keys Driver,⾥⾯提到:
Using gpio-key,wakeup will enable the GPIO to wake the system from suspend.
可以通过在Device Tree⾥⾯添加GPIO-Keys的⽅式来使能GPIO唤醒zynq。
参照wiki往设备树⽂件(project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi)添加gpio-keys
gpio-keys {
compatible ="gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
autorepeat;
sw14 {
label ="sw14";
gpios =<&gpio0 390>;
linux,code =<108>;/* down */
gpio-key,wakeup;
autorepeat;
};
};
注: gpios = <&gpio0 39 0>;
第⼆个参数39表⽰配置MIO39为GPIO,本次测试在MIO39接⼊按键来测试。
修改完成后,执⾏petalinux-build命令编译⼯程,完成后烧写指定⽂件到⽬标板。
启动⽬标板,通过串⼝进⼊到设备树⽬录下,可以看到新添加的gpio-keys⽬录
指定gpio-keys为唤醒设备:
执⾏休眠指令,zynq进⼊休眠状态,同时通过接⼊MIO39的按键触发来唤醒zynq。
通过GPIO唤醒设备的功能基本上也完成了。
总结
实际测试加⼊休眠功能后,zynq的整体功耗有⼀定的下降,对嵌⼊式设备的发热有⼀定的改善,但相对于跑裸机⽽⾔,功耗还是要⾼不少,对嵌⼊式设备⽽⾔,zynq的导热⼀定要做好。同时测试过程中,发现PS在唤醒的瞬间,PL端的逻辑出现过紊乱现象,建议PS在唤醒之后,需要马上对PL进⾏复位操作,重新配置相关寄存器。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。