您的位置首页>企业动态>

linux CPU是这样动态调频

导读 大家好,我是极客范的本期栏目编辑小友,现在为大家讲解linux CPU是这样动态调频问题。针对sep4020的低功耗linux的研究已经进行了一段时间

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解linux CPU是这样动态调频问题。

针对sep4020的低功耗linux的研究已经进行了一段时间。基本上低功耗的实现方法都已经想清楚了(主要分为机制和策略),这期间的工作主要是在机制上。暂时需要实现的主要机制有:cpu级、设备驱动级和系统平台级。管理的粒度不断加大,形成三驾马车并驾齐驱的局面。

Cpu级:主要在系统处于频繁的、更高粒度的电源状态变化的目标时容易实现,主要实现方式是空闲,包括我今天要讲的动态主频。

设备驱动级:主要管理单个设备驱动(挂起、恢复等)。),通过系统监控空闲设备,从用户状态通过sys文件目录动态管理单个驱动设备。

,进入省电模式。

系统级:目标是管理大的、不寻常的重大电源状态变化,用于降低产品设备长期闲置后的功耗。主要实现方式是依靠linux内核支持的apm技术实现整个系统的休眠。

其实这些层面并不是相互独立的,而是都相互交叉的。比如系统平台级的休眠,必然会涉及到cpu的休眠模式和设备驱动的挂起。动态主频的实现除了需要cpu本身的支持外,还需要外围驱动随着主频的变化进行相应的适配活动。因此,这里的分类只是一种粗略的、逻辑的分层。

前段时间,我也调查了IBM和蒙他Vista做的DPM(动态电源管理)机制。看了很多论文和观点,总的感觉是太复杂了,不太实用。感觉噱头比实际效果更有效。(因此,这种机制始终无法进入内核的主线。)无论如何,让我们关注cpufreq技术。

1.为什么是cpufreq?

我也在纠结是否要实现cpufreq技术。一个原因是当时不知道内核是怎么提供这样的动态变频机制的,但我觉得应该很麻烦,因为涉及到外围驱动的参数更新。另一个原因是,在SEP4020的处理器上运行linux,即使它以最高频率运行,也可能没有足够的处理能力。降低它的频率有什么意义?挣扎过后,还是觉得想实现。我还为自己列举了几个理由:

虽然n cpu不再是板级的主要功耗,但它仍然占据着重要的地位。说到底,功耗机制就是几毫安的扣除。降频肯定能在一定程度上节省功耗。那我为什么不用呢?

n细化电源管理的粒度,为应用程序提供更多的节能机制。

n对于普通应用程序,系统可以以最低频率运行,以保持平台运行。当有处理任务时,变频机构会自动切换到合适的高频,并在任务结束时回到低频省电,从而解决了我之前的第二个疑问。

SEP4020以88 m运行时,电路板级功耗为:222mA。

SEP4020在56M下运行时的板级功耗为:190毫安,低14%。

SEP4020的板级功耗为:160毫安,比32M低28%。

N已经完成的一些工作,是我们一直需要去做却没有动力去做的事情。

变频将涉及大量模块参数的重新配置。作为cpu原厂,我们需要彻底掌握这些参数。

充分了解这些参数可以优化现有系统,提高整个系统的效率。比如有些参数还是太保守(sdram、nand),我们一般的配置在系统降低到32M的时候还是可以正常工作的。

可行性论证没有问题:偶然看到armkiller同志提供的nand驱动代码有变频的实现(这里非常感谢armkiller),网上关于这方面的文章很少,所以看了linux内核源代码附带的/documentaTIon/cpufreq后,对这个机制有了一定的了解(linux中的documentaTIon是个好东西),也看到了一些处理器厂商已经为自己的cpu实现的代码,比如sa1100。

内核所提供的这种cpufreq技术的机制

n      目的:

变频技术是指CPU硬件本身支持在不同的频率下运行,系统在运行过程中可以根据随时可能发生变化的系统负载情况动态在这些不同的运行频率之间进行切换,从而达到对性能和功耗做到二者兼顾的目的。

n      来源:

虽然多个处理器生产厂家都提供了对变频技术的支持,但是其硬件实现和使用方法必然存在着细微甚至巨大的差别。这就使得每个处理器生产厂家都需要按照其特殊的硬件实现和使用方法向内核中添加代码,从而让自己产品中的变频技术在Linux中得到支持和使用。然而,这种内核开发模式所导致的后果是各个厂家的实现代码散落在 Linux内核代码树的各个角落里,各种不同的实现之间没有任何代码是共享的,这给内核的维护以及将来添加对新的产品的支持都带来了巨大的开销,并直接导致了 cpufreq内核子系统的诞生。

n      管理策略:

Linux内部共有五种对频率的管理策略userspace,conservaTIve,ondemand,powersave和 performance

Ø         1.performance :CPU会固定工作在其支持的最高运行频率上;

Ø         2.powersave :CPU会固定工作在其支持的最低运行频率上。因此这两种 governors都属于静态 governor ,即在使用它们时 CPU的运行频率不会根据系统运行时负载的变化动态作出调整。这两种 governors对应的是两种极端的应用场景,使用 performance governor体现的是对系统高性能的最大追求,而使用 powersave governor则是对系统低功耗的最大追求。

Ø        3.Userspace:最早的 cpufreq子系统通过 userspace governor 为用户提供了这种灵活性。系统将变频策略的决策权交给了用户态应用程序,并提供了相应的接口供用户态应用程序调节CPU运行频率使用。(可以使用Dominik 等人开发了 cpufrequTIls工具包)

Ø        4.ondemand :userspace是内核态的检测,效率低。而ondemand正是人们长期以来希望看到的一个完全在内核态下工作并且能够以更加细粒度的时间间隔对系统负载情况进行采样分析的governor。

Ø        5.conservaTIve : ondemand governor的最初实现是在可选的频率范围内调低至下一个可用频率。这种降频策略的主导思想是尽量减小对系统性能的负面影响,从而不会使得系统性能在短时间内迅速降低以影响用户体验。但是在 ondemand governor的这种最初实现版本在社区发布后,大量用户的使用结果表明这种担心实际上是多余的, ondemand governor在降频时对于目标频率的选择完全可以更加激进。因此最新的 ondemand governor在降频时会在所有可选频率中一次性选择出可以保证 CPU 工作在 80% 以上负荷的频率,当然如果没有任何一个可选频率满足要求的话则会选择 CPU支持的最低运行频率。大量用户的测试结果表明这种新的算法可以在不影响系统性能的前提下做到更高效的节能。在算法改进后, ondemand governor的名字并没有改变,而 ondemand governor 最初的实现也保存了下来,并且由于其算法的保守性而得名 conservative。

Ondemand降频更加激进,conservative降频比较缓慢保守,事实使用ondemand的效果也是比较好的。

n      Cpufreq在用户态所呈现的接口:

Ø        cpuinfo_max_freq  cpuinfo_min_freq:分别给出了 CPU硬件所支持的最高运行频率及最低运行频率,

Ø        cpuinfo_cur_freq 则会从 CPU硬件寄存器中读取 CPU 当前所处的运行频率。

Ø        Governor在选择合适的运行频率时只会在 scaling_max_freq和 scaling_min_freq 所确定的频率范围内进行选择

Ø        scaling_cur_freq 返回的是 cpufreq模块缓存的 CPU 当前运行频率,而不会对 CPU硬件寄存器进行检查。

Ø        scaling_available_governors会告诉用户当前有哪些 governors 可供用户使用

Ø         scaling_driver 则会显示该 CPU所使用的变频驱动程序

Ø        Scaling_governor 则会显示当前的管理策略,往这个上echo其他类型会有相应的转变。

Ø        scaling_setspeed:需将governor类型切换为userspace,才会出现,往这个文件echo数值,会切换主频

以下是将governor切换为ondemand后生成的ondemand文件夹下出现的配置文件。(conservative就不说了,不准备使用)

Ø        sampling_rate:当前使用的采样间隔,单位:微秒

Ø        sampling_rate_min:允许使用的最短采样间隔

Ø        sampling_rate_max:允许使用的最长采样间隔

Ø        up_threshold :表明了系统负载超过什么百分比时 ondemand governor会自动提高 CPU 的运行频率

Ø        ignore_nice_load:ignore_nice_load文件可以设置为 0 或 1(0是默认设置)。当这个参数设置为 1 时,任何具有 “nice”值的处理器不计入总处理器利用率。在设置为 0 时,所有处理器都计入利用率。

Ø        sampling_down_factor:

n      使用方法:

Ø        cd sys/devices/system/cpu/cpu0/cpufreq/目录

echo 32000 >scaling_min_freq 设置最小工作频率(khz,32000~88000)

//若想使用userspace策略

# echo userspace >scaling_governor切换工作方式为userspace

echo 64000 >scaling_setspeed  设置成想要的工作频率(khz)

//若想使用ondemand策略

# echo ondemand >scaling_governor切换工作方式为ondemand

3.如何实现?

首先需要干一些杂活,修改kconfig makefile把系统屏蔽的cpufreq打开,对于我们来说主要的核心有两部分:

系统相关:主要有cpu,timer(变了频率一定要更新系统timer,否则系统时间就不准了),sdram等。

主要就是实现下面这个结构体:

static struct cpufreq_driver sep4020_driver =

{

.flags      = CPUFREQ_STICKY,

.verify     = sep4020_verify_speed,

.target     = sep4020_target,

.get         = sep4020_getspeed,

.init         = sep4020_cpu_init,

.name            ="SEP4020 Freq",

};

代码还是很简陋,很多细节都没考虑,所以具体的暂时先不讲了,大家可以先参考pxa和sa1100的实现。

然后就是收频率影响的驱动:

简单的来说就是:系统在变化cpu主频的时候会调用cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);函数,响挂载在这个cpu上所有的驱动发出一个信号,驱动接收到这个信号则调用相应的处理函数。

这里把串口部分的实现简化,如下:

#ifdef CONFIG_CPU_FREQ

static int sep4020_serial_cpufreq_transition(struct notifier_block *nb, unsigned long val, void *data)

{

//      printk("in the serial cpufreq_transition\n");

int pmcr_pre;

unsigned long cpu_clk,baud,baudh,baudl;

pmcr_pre = *(volatile unsigned long*)PMU_PMCR_V;

if(pmcr_pre >0x4000)

cpu_clk = (pmcr_pre-0x4000)*8000000;

else

cpu_clk = (pmcr_pre)*4000000;

baud = cpu_clk/16/115200;      

baudh = baud >>8;

baudl = baud&0xff;    

*(volatile unsigned char*)UART0_LCR_V |= (0x80);

*(volatile unsigned char*)UART0_DLBL_V   = baudl;

*(volatile unsigned char*)UART0_DLBH_V   = baudh;

*(volatile unsigned char*)UART0_LCR_V &= ~(0x80);

printk("in the serial cpufreq_transition\n");

return 0;

}

static inline int sep4020_serial_cpufreq_register(void)

{

sep4020_serial_freq_transition.notifier_call = sep4020_serial_cpufreq_transition;

return cpufreq_register_notifier(&sep4020_serial_freq_transition,

CPUFREQ_TRANSITION_NOTIFIER);

}

static inline void sep4020_serial_cpufreq_deregister(void)

{

cpufreq_unregister_notifier(&sep4020_serial_freq_transition,

CPUFREQ_TRANSITION_NOTIFIER);

}

#else

#endif

4.效果

在sys下开启ondeman模式,串上电流表:

1.      板级电流从220mA调至160mA(因为此时内核检测系统无负载,降频)

2.      执行一个nandflash的拷贝命令,拷贝一个5M左右的文件到其他文件夹,

3.      在拷贝执行时间在3秒时(我给内核设的扫描周期为2.5秒)系统发现有负载,升频,电流从160mA变为220mA(可见已是系统最高主频)

4.      此后的拷贝的整个过程中电流保持为220mA

5.      在拷贝结束后不久(2-3s内),系统电流又跳变至160mA。

 

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。