針對sep4020的linux低功耗研究也有一段時間了,基本把低功耗的實現(xiàn)方式想清楚了(主要分成機制和策略),這段時間的工作主要在機制上。暫時想實現(xiàn)的主要的機制有:cpu級,設(shè)備驅(qū)動級,系統(tǒng)平臺級。管理顆粒度不斷遞增,形成三駕馬車齊驅(qū)的形勢。
cpu級:主要實現(xiàn)比較容易的在系統(tǒng)處于目標在于頻繁發(fā)生、更高粒度的電源狀態(tài)改變,主要的實現(xiàn)方式為idle,包括今天的主要想講的動態(tài)主頻。
設(shè)備驅(qū)動級:主要實現(xiàn)對單個設(shè)備驅(qū)動的管理(suspend,resume等),通過系統(tǒng)監(jiān)測將閑置的設(shè)備,通過從用戶態(tài)對sys文件目錄動態(tài)進行單個驅(qū)動設(shè)備的管理
,置于省電模式。
系統(tǒng)平臺級:目標在于管理較大的、非常見的重大電源狀態(tài)改變,用于減少產(chǎn)品設(shè)備在長時間的空閑之后,減少電源消耗。主要實現(xiàn)方式是依托l(wèi)inux內(nèi)核所支持的apm技術(shù),實現(xiàn)整個系統(tǒng)的睡眠/恢復(fù)(sleep)
這幾個層次其實并不是相互獨立的,都是相互交叉的,比如系統(tǒng)平臺級的睡眠不可避免會涉及到cpu的sleep模式和設(shè)備驅(qū)動的掛起,而動態(tài)主頻的實現(xiàn)除了cpu本身的支持也需要外圍驅(qū)動隨著主頻變化做出相應(yīng)的適應(yīng)活動。因此這里的分級只是一種粗范圍的,邏輯上的分層。
前段時間還調(diào)研了一下IBM和Monta Vista搞得那套DPM(Dynamic Power Management)機制,看了不少論文和觀點,總的感覺就是太過復(fù)雜而且也不是很實用,感覺噱頭大過實際功效,(因此這套機制始終還不能進入內(nèi)核的mainline),言歸正傳,還是重點講述下cpufreq技術(shù)。
1.為什么要cpufreq?
關(guān)于要不要實現(xiàn)cpufreq技術(shù),我也糾結(jié)過,一個原因是:當時對內(nèi)核如何提供這么一套動態(tài)變頻的機制還不了解,只覺得應(yīng)該非常麻煩,因為涉及到外圍驅(qū)動的參數(shù)更新,另外一個原因是:在SEP4020這種體量的處理器上跑linux,即使運行在最高頻率時的處理能力可能也不是很富余,我再給它降頻還有沒有意義?掙扎之后還是覺得要實現(xiàn)它,我也給自己列了這么幾條原因:
n????? 雖然cpu在板級中已不是主要的耗電源,但是仍然占著舉足輕重的位置,功耗機制到最后就是幾毫安幾毫安的扣了,降頻肯定能在一定程序上節(jié)約功耗那我為什么不采用?
n????? 細化功耗管理的顆粒度,為應(yīng)用程序提供更多的功耗節(jié)省機制
n????? 對普通的應(yīng)用,系統(tǒng)可以運行在維持平臺運作的最低頻率,在有處理任務(wù)時,變頻機制會自動切換到合適的高主頻,并且在任務(wù)結(jié)束時重回省電的低主頻,這樣就解決了我之前的第二個疑惑。
?????????SEP4020在運行在88M時板級功耗為:222mA
?????????SEP4020在運行在56M時板級功耗為:190mA,降低14%
?????????SEP4020在運行在32M時板級功耗為:160mA,降低28%
n????? 實現(xiàn)的一些工作是我們一直需要去做但是一直沒有動力做的
???????? 變頻會涉及到大量模塊的參數(shù)的重新配置,作為cpu原廠,我們需要把這些參數(shù)徹底掌握
???????? 對這些參數(shù)的充分理解,能對現(xiàn)有系統(tǒng)進行優(yōu)化,提升整體系統(tǒng)的效率,比如使用發(fā)現(xiàn)一些參數(shù)還是太過保守(sdram,nand),我們的通用配置在系統(tǒng)降為32M時仍能正常工作。
n????? 可行性論證沒有問題:偶然看到armkiller同志提供的nand驅(qū)動代碼中有變頻的實現(xiàn)(這里非常感謝armkiller),網(wǎng)上這方面的文章很少,于是翻閱了linux內(nèi)核源碼中自帶的/documentation/cpufreq后,對這種機制大概有一定的了解(linux中的documentation是個好東東),也看到了一些處理器廠商為自己的cpu已經(jīng)實現(xiàn)了的代碼,如sa1100,pxa系列。
2.?內(nèi)核所提供的這種cpufreq技術(shù)的機制
n????? 目的:
變頻技術(shù)是指CPU硬件本身支持在不同的頻率下運行,系統(tǒng)在運行過程中可以根據(jù)隨時可能發(fā)生變化的系統(tǒng)負載情況動態(tài)在這些不同的運行頻率之間進行切換,從而達到對性能和功耗做到二者兼顧的目的。
n????? 來源:
雖然多個處理器生產(chǎn)廠家都提供了對變頻技術(shù)的支持,但是其硬件實現(xiàn)和使用方法必然存在著細微甚至巨大的差別。這就使得每個處理器生產(chǎn)廠家都需要按照其特殊的硬件實現(xiàn)和使用方法向內(nèi)核中添加代碼,從而讓自己產(chǎn)品中的變頻技術(shù)在Linux
中得到支持和使用。然而,這種內(nèi)核開發(fā)模式所導(dǎo)致的后果是各個廠家的實現(xiàn)代碼散落在?Linux
內(nèi)核代碼樹的各個角落里,各種不同的實現(xiàn)之間沒有任何代碼是共享的,這給內(nèi)核的維護以及將來添加對新的產(chǎn)品的支持都帶來了巨大的開銷,并直接導(dǎo)致了?cpufreq
內(nèi)核子系統(tǒng)的誕生。
n????? 管理策略:
Linux內(nèi)部共有五種對頻率的管理策略userspace,conservative,ondemand,powersave
和?performance
??????????1.performance?:CPU會固定工作在其支持的最高運行頻率上;
??????????2.powersave?:CPU會固定工作在其支持的最低運行頻率上。因此這兩種?governors
都屬于靜態(tài)?governor?,即在使用它們時?CPU
的運行頻率不會根據(jù)系統(tǒng)運行時負載的變化動態(tài)作出調(diào)整。這兩種?governors
對應(yīng)的是兩種極端的應(yīng)用場景,使用?performance governor
體現(xiàn)的是對系統(tǒng)高性能的最大追求,而使用?powersave governor
則是對系統(tǒng)低功耗的最大追求。
?????????3.Userspace:最早的?cpufreq
子系統(tǒng)通過?userspace governor?
為用戶提供了這種靈活性。系統(tǒng)將變頻策略的決策權(quán)交給了用戶態(tài)應(yīng)用程序,并提供了相應(yīng)的接口供用戶態(tài)應(yīng)用程序調(diào)節(jié)CPU
運行頻率使用。(可以使用Dominik?等人開發(fā)了?cpufrequtils
工具包)
?????????4.ondemand?:userspace是內(nèi)核態(tài)的檢測,效率低。而ondemand正是人們長期以來希望看到的一個完全在內(nèi)核態(tài)下工作并且能夠以更加細粒度的時間間隔對系統(tǒng)負載情況進行采樣分析的
governor。
?????????5.conservative?:?ondemand governor
的最初實現(xiàn)是在可選的頻率范圍內(nèi)調(diào)低至下一個可用頻率。這種降頻策略的主導(dǎo)思想是盡量減小對系統(tǒng)性能的負面影響,從而不會使得系統(tǒng)性能在短時間內(nèi)迅速降低以影響用戶體驗。但是在?ondemand governor
的這種最初實現(xiàn)版本在社區(qū)發(fā)布后,大量用戶的使用結(jié)果表明這種擔心實際上是多余的,?ondemand governor
在降頻時對于目標頻率的選擇完全可以更加激進。因此最新的?ondemand governor
在降頻時會在所有可選頻率中一次性選擇出可以保證?CPU?
工作在?80%?以上負荷的頻率,當然如果沒有任何一個可選頻率滿足要求的話則會選擇?CPU
支持的最低運行頻率。大量用戶的測試結(jié)果表明這種新的算法可以在不影響系統(tǒng)性能的前提下做到更高效的節(jié)能。在算法改進后,?ondemand governor
的名字并沒有改變,而?ondemand governor?
最初的實現(xiàn)也保存了下來,并且由于其算法的保守性而得名?conservative
。
Ondemand降頻更加激進,conservative降頻比較緩慢保守,事實使用ondemand的效果也是比較好的。
n??????Cpufreq在用戶態(tài)所呈現(xiàn)的接口:
?????????cpuinfo_max_freq? cpuinfo_min_freq:分別給出了?CPU
硬件所支持的最高運行頻率及最低運行頻率,
?????????cpuinfo_cur_freq?則會從?CPU
硬件寄存器中讀取?CPU?當前所處的運行頻率。
?????????Governor在選擇合適的運行頻率時只會在?scaling_max_freq
和?scaling_min_freq?所確定的頻率范圍內(nèi)進行選擇
?????????scaling_cur_freq?返回的是?cpufreq
模塊緩存的?CPU?當前運行頻率,而不會對?CPU
硬件寄存器進行檢查。
?????????scaling_available_governors
會告訴用戶當前有哪些?governors?可供用戶使用
??????????scaling_driver?則會顯示該?CPU
所使用的變頻驅(qū)動程序
?????????Scaling_governor?則會顯示當前的管理策略,往這個上echo其他類型會有相應(yīng)的轉(zhuǎn)變。
?????????scaling_setspeed:需將governor類型切換為userspace,才會出現(xiàn),往這個文件echo數(shù)值,會切換主頻
以下是將governor切換為ondemand后生成的ondemand文件夾下出現(xiàn)的配置文件。(conservative就不說了,不準備使用)
?????????sampling_rate:當前使用的采樣間隔,單位:微秒
?????????sampling_rate_min:允許使用的最短采樣間隔
?????????sampling_rate_max:允許使用的最長采樣間隔
?????????up_threshold?:表明了系統(tǒng)負載超過什么百分比時?ondemand governor
會自動提高?CPU?的運行頻率
?????????ignore_nice_load:ignore_nice_load
文件可以設(shè)置為?0?或?1(0
是默認設(shè)置)。當這個參數(shù)設(shè)置為?1?時,任何具有?“nice”
值的處理器不計入總處理器利用率。在設(shè)置為?0?時,所有處理器都計入利用率。
?????????sampling_down_factor:
n????? 使用方法:
?????????cd sys/devices/system/cpu/cpu0/cpufreq/目錄
echo 32000 > scaling_min_freq?
設(shè)置最小工作頻率(khz,32000~88000)
//若想使用userspace策略
# echo userspace > scaling_governor切換工作方式為userspace
echo 64000 > scaling_setspeed??
設(shè)置成想要的工作頻率(khz)
//若想使用ondemand策略
# echo ondemand > scaling_governor切換工作方式為ondemand
3.如何實現(xiàn)?
首先需要干一些雜活,修改kconfig makefile把系統(tǒng)屏蔽的cpufreq打開,對于我們來說主要的核心有兩部分:
系統(tǒng)相關(guān):主要有cpu,timer(變了頻率一定要更新系統(tǒng)timer,否則系統(tǒng)時間就不準了),sdram等。
主要就是實現(xiàn)下面這個結(jié)構(gòu)體:
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",
};
代碼還是很簡陋,很多細節(jié)都沒考慮,所以具體的暫時先不講了,大家可以先參考pxa和sa1100的實現(xiàn)。
然后就是收頻率影響的驅(qū)動:
簡單的來說就是:系統(tǒng)在變化cpu主頻的時候會調(diào)用cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);函數(shù),響掛載在這個cpu上所有的驅(qū)動發(fā)出一個信號,驅(qū)動接收到這個信號則調(diào)用相應(yīng)的處理函數(shù)。
這里把串口部分的實現(xiàn)簡化,如下:
#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 ");
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 ");
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調(diào)至160mA(因為此時內(nèi)核檢測系統(tǒng)無負載,降頻)
2.??????執(zhí)行一個nandflash的拷貝命令,拷貝一個5M左右的文件到其他文件夾,
3.??????在拷貝執(zhí)行時間在3秒時(我給內(nèi)核設(shè)的掃描周期為2.5秒)系統(tǒng)發(fā)現(xiàn)有負載,升頻,電流從160mA變?yōu)?20mA(可見已是系統(tǒng)最高主頻)
4.??????此后的拷貝的整個過程中電流保持為220mA
5.??????在拷貝結(jié)束后不久(2-3s內(nèi)),系統(tǒng)電流又跳變至160mA。
?
評論
查看更多