Linux的cpufreq(動態變頻)技術

來源:互聯網
上載者:User

linux低功耗研究也有一段時間了,基本把低功耗的實現方式想清楚了(主要分成機制和策略),這段時間的工作主要在機制上。暫時想實現的主要的機制有:cpu級,裝置驅動級,系統平台級。管理顆粒度不斷遞增,形成三駕馬車齊驅的形勢。

 

cpu級:主要實現比較容易的在系統處於目標在於頻繁發生、更高粒度的電源狀態改變,主要的實現方式為idle,包括今天的主要想講的動態主頻。

裝置驅動級:主要實現對單個裝置驅動的管理(suspend,resume等),通過系統監測將閑置的裝置,通過從使用者態對sys檔案目錄動態進行單個驅動裝置的管理

,置於省電模式。

系統平台級:目標在於管理較大的、非常見的重大電源狀態改變,用於減少產品裝置在長時間的空閑之後,減少電源消耗 。主要實現方式是依託linux核心所支援的apm技術,實現整個系統的睡眠/恢複(sleep)

 

這幾個層次其實並不是相互獨立的,都是相互交叉的,比如系統平台級的睡眠不可避免會涉及到cpu的sleep模式和裝置驅動的掛起,而動態主頻的實現除了cpu本身的支援也需要外圍驅動隨著主頻變化做出相應的適應活動。因此這裡的分級只是一種粗範圍的,邏輯上的分層。

 

前段時間還調研了一下IBM和Monta Vista搞得那套DPM(Dynamic Power Management)機制,看了不少論文和觀點,總的感覺就是太過複雜而且也不是很實用,感覺噱頭大過實際功效,(因此這套機制始終還不能進入核心的mainline),言歸正傳,還是重點講述下cpufreq技術。

 

1.為什麼要cpufreq?

 

關於要不要實現cpufreq技術,我也糾結過,一個原因是:當時對核心如何提供這麼一套動態變頻的機制還不瞭解,只覺得應該非常麻煩,因為涉及到外圍驅動的參數更新,另外一個原因是:在SEP4020這種體量的處理器上跑linux,即使運行在最高頻率時的處理能力可能也不是很富餘,我再給它降頻還有沒有意義?掙紮之後還是覺得要實現它,我也給自己列了這麼幾條原因:

n      雖然cpu在板級中已不是主要的耗電源,但是仍然佔著舉足輕重的位置,功耗機制到最後就是幾毫安幾毫安的扣了,降頻肯定能在一定程式上節約功耗那我為什麼不採用?

n      細化功耗管理的顆粒度,為應用程式提供更多的功耗節省機制

n      對普通的應用,系統可以運行在維持平台運作的最低頻率,在有處理任務時,變頻機制會自動切換到合適的高主頻,並且在任務結束時重回省電的低主頻,這樣就解決了我之前的第二個疑惑。

Ø        SEP4020在運行在88M時板級功耗為:222mA

Ø        SEP4020在運行在56M時板級功耗為:190mA,降低14%

Ø        SEP4020在運行在32M時板級功耗為:160mA,降低28%

n      實現的一些工作是我們一直需要去做但是一直沒有動力做的

Ø        變頻會涉及到大量模組的參數的重新設定,作為cpu原廠,我們需要把這些參數徹底掌握

Ø        對這些參數的充分理解,能對現有系統進行最佳化,提升整體系統的效率,比如使用發現一些參數還是太過保守(sdram,nand),我們的通用配置在系統降為32M時仍能正常工作。

n      可行性論證沒有問題:偶然看到armkiller同志提供的nand驅動代碼中有變頻的實現(這裡非常感謝armkiller),網上這方面的文章很少,於是翻閱了linux核心源碼中內建的/documentation/cpufreq後,對這種機制大概有一定的瞭解(linux中的documentation是個好東東),也看到了一些處理器廠商為自己的cpu已經實現了的代碼,如sa1100,pxa系列。

 

2. 核心所提供的這種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。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.