海思3516A開發板調試整理(三)

第六部分 設備休眠

第一節 Linux休眠喚醒

設備休眠模式,是指設備通過固定的操作,或手動或自動地進入省電模式,掛起或者凍結程序、外設甚至cpu,從而進入一種待機狀態,使設備在這種待機狀態下儘可能少地消耗電量和功耗,從而滿足家用手持設備對待機時長的性能要求。設備在進入休眠狀態之後需要能夠通過固定的操作進行喚醒,這個喚醒操作使設備能快速地恢復到休眠之前的狀態,並正常工作。

首先,關於省電模式,Linux內核支持三種省電模式:standbySTR(suspendto ram)STD(suspendtodisk),幾乎所有的方案都只支持STR模式(也有同時支持standby模式的),但是在使用電池供電的手持設備時,由於STD模式需要有交換分區的支持,而我們的嵌入式設備一般文件系統中是不提供交換分區的,所以這類設備上的Linux都沒有支持STD省電模式。在設備中如果已經有對電源管理PM模塊的支持,我們就可以查看設備支持的省電模式類型,查看方法是輸入命令“cat/sys/power/state”

先從內核設置開始說起,關於內核的配置,在整個調測過程中是以海思Hi3516AV100R001C01SPC030SDK提供的內核版本爲基礎,內核版本號是3.4.35,內核源碼中有提供默認的配置文件:hi3516a_full_defconfig,在menuconfig中查看powermanagement options,配置中電源管理配置默認是打開的,其子項的配置如下圖所示:


6-1海思3516A電源管理配置


從以上配置我們可以看到,掛起方式支持RAMstandby兩種方式。除此之外,配置默認打開了snapshot快照功能,HiberanationSTD功能和DEBUG相關的功能。所以我們默認的休眠模式至少支持STRstandby兩種方式,這裏STD模式雖然打開了,但是由於對交換分區的限制,該功能是否能正常使用,我在後面有做調測和分析。

在如圖示的配置中,PowerManagement DebugSupport功能被打開,這個配置被打開之後在系統的/sys/power目錄下會多出一個pm_test文件,catpm_test後,列出的測試選項有:[none]core processors platform devicesfreezer。這裏有六個參數,代表pm調試的六個級別,跟蹤Linux內核裏面的相關代碼,我發現這六個參數代表了系統掛起的六個階段,所以,我們可以通過設置這個參數來分別對每一階段的掛起操作進行調試查看。其中,freezer是級別最低的,none是表示不進行pm_test,也就是完成所有的掛起操作。

有了以上內核的配置支持之後,我們就可以進行簡單的休眠喚醒調試了,只要在系統中輸入兩條命令即可:

  1. echoplatform > /sys/power/pm_test

  2. echomem > /sys/power/state

表示設置採用STR的方式進行休眠,休眠到platform階段爲止,後面的休眠操作不再進行。輸入命令之後在設備終端是可以看到相關的操作流程的打印信息的。


第二節 休眠流程

下圖爲目前內核代碼中的休眠的流程:

6-2海思3516A系統掛起流程


從整個掛起流程來看,系統最終需要在函數hi_pm_ops.enter回調函數中進行系統掛起,並設置喚醒方式,等待喚醒。enter函數的堵塞流程跳出之後,suspend_enter會繼續向下執行,這個時候就進入到resume喚醒流程了。所以,由於目前3516A的代碼中沒有實現enter函數的堵塞操作,suspend_enter函數就會在掛起完成之後直接進入到resume流程,系統自動被喚醒。

掛起流程在每個階段結束之後都會去檢測suspend_test的狀態,這個狀態就是我們在文件/sys/power/pm_test中設置的參數,如果檢測到用戶設置的級別跟當前級別一致了,就會直接等待5S,然後進入喚醒流程。那麼從整個流程來看,我們大概可以知道這5個級別都分別進行了哪些處理工作:

第一階段freezer:首先是suspend前的一些準備工作,比如同步文件系統(sys_sync)、給suspend分配一個虛擬終端來輸出信息,再廣播一個系統進入suspend的通報,關閉用戶態的helper進程,然後調用suspend_freeze_processes()來凍結進程,這些進程也包括也包括workqueue/kthread進程,最後會嘗試釋放一些內存附錄。

第二階段device:這個階段主要是用來休眠外設,調用suspend_devices_and_enter()進行操作,外設休眠的時候會調用所有外設的suspend函數。在這個函數中會調用mach-3516a/pm.csuspend_ops->begin()3516A方案中並沒有實現begin函數,然後driver/base/power/main.c中的 device_suspend()->dpm_suspend()會被調用,他們會依次調用驅動的suspend()回調來休眠掉所有的設備。

第三階段platform:這個階段主要是調用mach-3516a/pm.csuspend_ops->prepare ()函數中實現的一些平臺相關的準備工作,目前未實現該函數。

第四階段processors:這個階段只做了一件事,就是調用disable_nonboot_cpus()函數來關掉多核中非啓動的cpu

第五階段core:在這個階段就是真正的休眠階段了,這個時候會調用平臺註冊的enter函數來進行將cpu切換到省電狀態等操作,並需要將代碼執行停止在這裏。3516A平臺對此未做實現,需要我們去實現這個函數。


第三節 簡單測試

根據上面的流程,我做了一個簡單的測試,編寫一個pm的驅動模塊,去實現suspend_ops->enter()函數,在該函數中使用while循環將函數進行堵塞,並輪詢我指定的一個GPIO0bit3電平變化,GPIO0_3作爲輸入時通過電路設置常態爲高電平,通過該GPIO來模擬喚醒按鈕操作,需要喚醒時將該GPIO輸入低電平,enter函數中檢測到持續的低電平之後函數跳出,進入喚醒流程。

通過這個簡單的測試,來查看一下休眠喚醒機制的基本工作情況。

  1. 查看系統休眠前後的功耗變化:關於功耗的變化,測試了兩組數據,第一組數據是隻加載系統的時候,休眠前後的功耗變化,休眠前在系統完全運行起來之後電流爲0.12A,休眠後變成0.09A,喚醒之後恢復0.12A;第二組數據是加載CVBS實時視頻的時候,休眠前電流值爲0.22A,休眠後電流爲0.17A。兩種情況下,電流都有一定的跌幅,所以可以看出目前的休眠機制是有一定的省電作用。

  2. 查看休眠前後用戶態進程狀態:編寫一個簡單的測試程序,使程序一直循環打印累加的計數值,在休眠之後可以看到串口是沒有任何打印信息輸出了,並且在此之前通過測試發現設備休眠之後串口是沒有休眠的,仍然能輸出打印信息。那麼休眠一段時間之後,使用按鍵將系統喚醒,查看喚醒之後的狀態。設備喚醒之後,網卡會重新連接,測試程序的打印信息會在休眠前的狀態之下執行,因此說明,休眠時應用程序的狀態以及現場的保存都是正常的。同時,還發現喚醒後系統的時間和休眠前的系統時間幾乎是沒有差異的。但是,測試發現RTC時鐘還在正常運行,所以在實際開發的過程中在休眠喚醒之後還需要根據RTC時鐘的時間對系統進行對時。

  3. 視頻輸入輸出休眠測試:啓動VIO應用程序,並使開發板能正常顯示適時視頻,程序運行正常之後,將系統休眠,查看休眠之後的狀態以及休眠喚醒之後是否能正常顯示適時視頻。通過測試發現,休眠之後,適時視頻輸出端畫面被凍結,整個畫面已經處於靜止狀態,在被喚醒之後,視頻恢復正常,可適時顯示視頻變化。並且,針對在線模式和離線模式的測試都能正常通過。並且,我將休眠時間增加,測試經過長時間地休眠之後,系統是否還能正常被喚醒,目前的測試情況休眠2小時,系統能正常喚醒,但是到10小時以上之後會出現內核崩潰。

  4. 使用中斷源喚醒系統:在上面的這些測試中,我使用的喚醒機制是輪詢檢測GPIO的輸入電平,當電平由高變低的時候,觸發喚醒。但是,內核提供一種中斷喚醒源的方式對掛起的系統進行喚醒操作,這種操作的實現是需要將某個中斷註冊爲喚醒源,一旦該中斷被觸發,則進入喚醒流程。實現該操作的時候我仍然是用GPIO0bit3設置爲中斷方式,使用接口enable_irq_wake()來註冊該中斷爲喚醒源。測試結果是在中斷能正常檢測到的情況下,觸發該中斷之後並不能進入到喚醒流程。究其原因,在內核中每個平臺需要實現irq_set_wake的回調函數,在該函數中將註冊的中斷號保存到cpu的中斷喚醒掩碼中,這個中斷喚醒掩碼保存到寄存器中,當喚醒源中斷到來的時候,進行喚醒操作。從海思H3516A的代碼來看,並未實現這塊功能,所以目前的內核並不支持。


綜上所述,海思H3516A內核中已有的功能對休眠和喚醒支持地並不是很完善,那麼就需要做較多的內核編碼工作來完善這塊功能。最首要的是需要完善設備休眠時的低功耗省電模式的切換。


第四節 省電模式

海思3516A方案系統工作模式分爲兩種模式:正常工作模式和待機工作模式,待機工作模式對應系統運行模式控制中的SLOW模式和DOZE模式,待機工作模式工作系統在極低工作時鐘下,並且關閉了大部分不使用的模塊的時鐘,功耗較低,待機工作在SLOWDOZE模式下,可以通過關閉不工作模塊的電源來直接減少待機的功耗。

NORMAL模式:系統正常工作在NORMAL模式下。在此模式下,系統由片內PLL的輸出時鐘驅動。所有的模塊均能正常工作。

SLOW模式:LOW模式是一種慢速模式。在此模式下,系統由外接晶振時鐘驅動,只有部分片內外設(如系統控制器、TimerNANDCSFC等)可以工作。所有對高速時鐘有要求的模塊在此時鐘下無法工作,如DDRC等。

DOZE模式:DOZE模式是一種低速模式。只有少量片內外設可以工作於DOZE模式。在此模式下,系統由外接晶振分頻的46.875kHz低頻時鐘驅動。大部分片內外設無法工作,存儲器接口無法工作,CPU和少量模塊(如系統控制器、TimerIR等)可以工作於該模式。


第七部分 音頻編解碼

第一節 語音流程

海思的音頻編碼提供了設備端和pc端用於編解碼的庫文件,封裝了語音編解碼的接口。對於語音輸出入輸出海思引入了幾個概念:aiaencadecao,分別代碼輸入通道、編碼通道、解碼通道和輸出通道,應用程序通過對這幾個通道進行綁定來實現語音操作功能,綁定方式有以下幾種:

Aiao直接綁定:這種直接輸入輸出的綁定關係提供了設備端mic採樣,直接從spk輸出,中間不進行數據編碼壓縮,PCM幀進入PCM幀輸出。這種方式不太常用,也很簡單。

Aiaenc綁定、adecao綁定,這兩種綁定關係是相互依賴存在的,我們在對講中使用的這種方式,設備端採集PCM幀,然後發送到aenc,編碼完成之後發送到應用層,應用層進行解碼;應用層發送編碼幀,編碼庫將編碼幀發送到adecadec進行解碼然後發送到ao進行放音。


第二節 輸入輸出設備

Aiao要想正常工作,需要對其屬性參數進行配置,然後調用HI_MPI_AI_SetPubAttr接口設置其屬性並使能纔行,否則是無法正常接收到採樣中斷的。這些屬性參數具體內容可參考文檔中關於AIO_ATTR_S結構體的詳細說明。

設備屬性中的相關內容有采樣率、比特位寬、工作模式等,其中需要注意的是工作模式的配置,工作模式配置的是主從模式以及時序的選擇,AI/AO設備支持主模式和從模式,主模式即AI/AO設備提供時鐘,從模式即AudioCodec提供時鐘。主模式時,如果AI設備與AO設備同時對接同一個Codec,則時鐘供輸入和輸出共同使用,其他情況沒有此限制。而從模式時的輸入輸出時鐘可以分別由外圍AudioCodec提供。在AI/AO設備從模式下,先配置好對接的Codec,再配置AIAO設備;而在AI/AO設備主模式下,先配置好AIAO設備,再配置對接的Codec。目前對於3516A來說,使用的是一個內置的audiocodec,所以只支持I2S主模式。而且,aiao對接同一個內置codec時,時鐘要採用aiao複用。

調測的過程中,我們可以使用海思方案提供的通用調試方法來查看相關配置是否有效,通過cat/proc/umap/ai 等來分別查看通道綁定是否成功,是否有中斷到來之類的,詳細描述查看文檔《HiMPP用戶手冊》

第三節 語音幀結構

海思的編碼語音幀結構與之前我們在TI平臺中使用的語音幀結構有所區別,具體結構信息如下圖:

7-1編碼語音幀結構


如圖所示,圖中前4byte的數據信息爲海思獨有的幀頭,幀頭信息裏面實際有用的信息爲0:[15:8]= 011:[15:8]=幀長/2。其他位爲0,唯一需要在應用層中需要注意的是這個幀長爲編碼之後的語音幀的實際長度,如g711A編碼時,如果採樣數爲320,則每幀PCM長度爲640byte,編碼之後每幀長度爲320byte,這裏填充到數據頭裏面的長度則爲160,數據頭之後的320byte爲解碼數據。

第三節 編解碼協議

以下針對幾種編解碼方式在對接過程中的一些操作分別進行描述。

海思目前提供了幾種編解碼方式:G711(A律與µ)G726ADPCM(ADPCM_IMA4ADPCM_ORG_DVI4ADPCM_DVI),這三種編解碼的方式在海思的開發文檔裏面有詳細的比較,三種編碼方式壓縮率分別是:2:18~3.2:14:1

使用海思的編解碼庫時每種編碼方式都會在語音幀前面增加一個幀頭。

第一步 G711編碼

G.711提供A律與µ律壓縮編碼,適用於綜合業務網和大多數數字電話鏈路。北美與日本通常採用µ律編碼,歐洲和其他地區大都採用A律編碼。

G711編解碼和TI保持一致,這裏不詳述。


第二步 ADPCM編碼

ADPCM有三種編解碼方式,ADPCM_IMA4ADPCM_ORG_DVI4ADPCM_DVI。三種編碼方式的壓縮比率都是4:1,壓縮後碼率爲32kbps,關於這三種編碼方式的詳細介紹可以參考RFC3551.pdf文檔,有很明確的說明,總結起來,三種編碼方式的區別在於,預測值上面的差別,這裏簡單歸納一下:

  1. ADPCM_ORG_DVI4:這種編碼方式是不會把預測值保存在壓縮幀數據中的,編碼時,每次會將上一幀計算出來的值作爲預測值,解碼時,同樣將上一幀計算出來的值作爲預測值,在當前幀中用來解碼。這種方式存在的問題是:在網絡丟包時,可能會引起異常。所以不推薦使用這種方式。

  2. ADPCM_DVI:這種編碼方式會把預測值保存在編碼幀的頭四個字節,每一幀通過計算出來的值作爲下一幀的預測值,解碼時,通過傳過來的預測值進行解碼,這種方式就比較安全,不會因爲丟失幀而造成語音異常。這個預測值信息即爲算法中的adpcm_state結構體的內容。

  3. ADPCM_IMA4:這種編碼方式目前沒使用,這種編碼方式是將第一個採樣點作爲預測值,所以在進行採樣時,要多采一個,所以輸入採樣點個數爲81/161/241/321/481


我們在和TI平臺對接時使用ADPCM_DVI的方式。

附錄

  1. FAQ

對於調試過程中出現的一些現象在此做一個簡單的記錄:

1Q:運行load3516a時出現如下錯誤:

A:這個問題是前面提到的himm執行段錯誤的問題,按前面調到的方法進行修改。解決方法查看這裏。


2Q:運行load3516a時出現如下打印

A:系統運行會一直堵塞在這裏,等待I2C響應,這個錯誤就是前面提及的需要刪除sil9024驅動的問題。解決方法查看這裏。


  1. Q:運行load3516a時出現如下打印,設備掛死

A:系統運行在這裏會一直掛着,串口輸入也沒反應,必須要重新上電,這個是DDR時鐘配置的問題,需要按前面提到的方法進行配置。解決方法查看這裏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章