王 瓊,朱正發
(重慶郵電大學 通信與信息工程學院,重慶 400065)
近年來,隨著消費類電子產業的高速發展,日益增長的嵌入式技術已經不能滿足人們對嵌入式產品功能和性能的需求[1]。虛擬機技術的產生加速了嵌入式應用領域的發展。嵌入式系統虛擬機可以在單芯片的硬件平臺上模擬多芯片的運行,允許一個平臺同時運行多個操作系統,并且應用程序可以在相互獨立的空間內運行而互不影響,從而顯著地提高設備的工作效率,縮短應用軟件的開發周期,并且減少系統工作的芯片數量和企業的開發成本[2-3]。
隨著硬件平臺性能的不斷提升,虛擬機被廣泛地引入到嵌入式系統中。通過構建嵌入式系統虛擬機,可以保證通用操作系統和實時操作系統的并行運行。虛擬機可以看成一個虛擬的硬件系統,該系統將一個真實的嵌入式CPU虛擬成兩個虛擬的CPU,兩個虛擬CPU上可以分別運行一個分時操作系統和一個(硬)實時操作系統(如圖1)[4]。
系統虛擬機的目的是在物理硬件和操作系統之間建立一層硬件抽象層,它將底層的物理硬件結構進行封裝,在操作系統移植過程中,操作系統就不需要了解底層物理信息,直接調用相應的軟件接口就可以完成相應的服務請求或設備配置[5]。

圖1 嵌入式虛擬機系統架構
本文提出了一種基于Hopen虛擬機在Android手機平臺上實現雙操作系統之間數據交互的解決方案——虛擬管道(Virtual Pipe,Vpipe)以及NVM參數存取。
虛擬管道指在Android手機虛擬機平臺中實現基帶子系統(RTOS)和應用子系統(Linux)之間數據交互的通道(如圖2)。主要功能是:讀寫數據(包括命令、狀態、控制數據等),在單CPU上完成雙操作系統間的信息傳遞等。

虛擬機提供32個雙向虛擬管道來實現雙操作系統的通信。每個虛擬管道都有對應的ID號,并且都可以分別指定各個方向緩存的大小。所有Vpipe共享一個Vpipe中斷,使用中斷狀態位來快速判斷哪一個Vpipe有中斷產生。
Vpipe包括輸入緩存和輸出緩存兩種緩存機制,并且必須在管道啟動前寫入相應的寄存器中。需要對Vpipe進行數據操作時,先將數據的地址寫入到地址寄存器中,然后將字節數和操作指令寫入到指令寄存器中。
每個Vpipe工作的3種數據傳輸方式:
1)字節流管道:管道中傳輸的是字節流,不區分數據包的邊界。發送方一次發送的數據可能被接收方分若干次取出,發送方多次發送的數據也可能被合并,從而被接收方一次取出。
2)定長數據包管道:管道中傳輸的是固定長度的數據包。發送方每次只能發送一個數據包,接收方每次只能接收一個數據包。
3)指針管道:管道中傳輸的是指針而不是數據內容。發送方每次只能發送一個指針,接收方每次只能接收一個指針。
目前只實現了往Vpipe里面讀寫數據的功能,管道通過Buffer來進行數據的存儲,分為Vpipe_Outbuf和Vpipe_Inbuf。在上下行數據傳輸的過程中盡量減少數據的拷貝:基帶到Android只有一次拷貝,Android到基帶沒有數據拷貝。
虛擬管道中參數:Command(命令);Status(狀態);Data(參數)。
通信過程中,Linux組裝好數據(主要包括AT指令、PSCS數據、URC、NV參數等)發送到Vpipe,并一直查詢,等待狀態完成。
RTOS從Vpipe中獲取Linux發送過來的數據并進行處理,處理完成后,需要先更新Status(操作成功,返回Success;否則,返回Fail);再根據命令的類型,有必要時也要更新Data;之后再更新Command;最后,通過Vpipe向Linux返回數據。
以前的通信過程是:Android通過Vpipe發送AT指令到基帶,Vpipe接收到AT指令后通過區分不同的數據類型進行函數封裝,然后給Android返回“OK”,Android收到“OK”后才能進行下一條AT指令的發送。
現在需要解決的問題:當Android給基帶發送AT指令后,還沒有收到“OK”響應又發送了一條或者多條AT指令,這樣從基帶返回的“OK”就有多個,Android如何區分返回的“OK”具體對應于哪條AT指令。解決方案:通過在AT指令前面增加一個byte的AT標識來區分不同的AT指令。
AT指令格式如圖3所示。

圖3 AT指令格式
Android和基帶之間AT指令的傳輸方式主要有并行傳輸和串行傳輸。并行傳輸:采用MUX標準協議,但是上下層目前都還沒有實現,所以不考慮這種方式。串行傳輸:適用于AT指令的數據量較小且傳輸不是很頻繁的情況。由于目前應用層采用的是串行傳輸方式,所以選擇串行傳輸方式。
Android讀寫AT指令的方式主要有同步讀寫和異步讀寫。異步讀寫:要在請求函數中實現狀態機,并且需要修改當前應用子系統的超時機制,改動較大。同步讀寫:當前應用層是通過線程信號來同步讀寫,為了實現并發,要根據上層可能發起的業務類型創建多個請求線程,同時往AT命令管道寫數據,當線程收到AT的返回后,根據自定義數據中的標志返回給對應的請求線程。
綜上兩方面的考慮,采用串行傳輸AT指令、多請求線程、同步讀寫AT指令的方式來實現并發。
在Android手機方案中,NVM參數僅在基帶內部使用,即虛擬機中的RTOS側使用,Linux不需要NVM參數。但NVM參數存放在Flash中,而Flash硬件的控制權又放于Linux中。所以,要實現基帶對NVM數據的存取,又不違背Flash硬件由Linux控制的原則,必須設計一套方案來實現基帶通過與Linux進行必要的交互,完成NVM數據的存取。
NVM數據分為兩塊,一塊為Static參數(7 k),主要記錄產品固定參數,出廠后不會再修改,但調試階段需要通過工程模式進行修改;一塊為Dynamic參數(2 k),用于記錄設備工作過程中必須記錄的信息,如當前小區相關信息,需要能夠在設備運行過程中進行動態保存。
該方案直接使用Android的Flash Yaffs文件系統,將其值保存到兩個特定文件中。這樣帶來的好處為:An?droid將數據維護交給Yaffs文件系統,不用擔心壞塊處理;NV文件更新方便,不需要使用工具燒寫,直接通過Android的文件系統通道就可以進行NV文件更換。兩個系統之間的數據交換使用Share Memory的方法,通知機制使用Vpipe。Init Process在啟動基帶之前就將NV文件中的數據讀出寫入到Share Memory中,在正常工作過程中,Init Process接收到Driver的Uevent后將Share Memory數據寫入到文件系統對應文件中。具體流程如圖4所示。

圖4 NVM數據存取流程圖
模塊之間的交互流程如圖5所示。在Android系統啟動以后,首先啟動Init Process,通過Android側的Vpipe Driver將Share Memory映射到用戶空間;然后將讀取文件系統中的NV文件數據寫入Share Memory;接著Android系統啟動基帶軟件。
當基帶側的NV Daemon Task需要將數據存入Flash時,通過RTOS側的Vpipe發送Request,攜帶信息需要指明更新Static NV還是Dynamic NV;Linux側的Vpipe Driver收到數據后發送Uevent到Init Process,根據請求讀取Share Memory數據寫入文件系統;完成后再通過Vpipe反饋ACK到基帶,NVM Daemon Task就完成一次寫操作。

圖5 Android手機虛擬機平臺NV數據存取流程圖
將DDR中一段區域(2 k+7 k,但要保證是4 k的整數倍,即必須分配12 k)固定指定為NV Share Memory,考慮到NV的數據交互不會很頻繁,可以使該區域不開啟Dchache,所以將其地址空間類型指定為設備空間,虛實地址映射固定,從而方便兩側直接使用。
共享內存必須考慮沖突的情況。在開機NV Dae?mon Thread第一次向Share Memory寫數據時,此時基帶還沒有加載,那么此時Memory一定是獨占的,這時沒有沖突。在接下來的流程中,Linux側只會去讀Memory,RTOS側只會去寫Memory。當RTOS在任務中寫Share Memory時,由于VM虛擬機保證RTOS任務的優先級高于Linux進程,所以整個過程都不會發生Daemon Thread讀動作,因此RTOS的寫流程一定是安全的。但當Linux在讀取時,RTOS可以打斷這個流程發起新的寫入Memory過程,導致最后Linux讀取前后不一致的數據寫入到了NV文件中。所以,這里必須有機制進行保護。
本方案提出的方法是:RTOS NVM Daemon Task向Linux側通過Vpipe發送請求以后,還必須關注響應,任務不需要等待,只需一次向Memory寫入,可以放棄CPU,等待一段時間再判斷。NV寫入對實時性要求不高,此處的延時可以接受。
為了應對Linux系統中對NV文件寫入過程掉電導致Flash上的文件損壞的情況,在Android文件系統內部維護4個NV bin文件,其中Static_nv_bak.bin與Dynam?ic_nv_bak.bin用于存放默認配置,這兩個文件永不寫入;Static_nv.bin與Dynamic_nv.bin用于實時記錄。在NV數據的結構體中用一個U16的字段來記錄數據的CRC校驗值,當讀取NV文件發現該校驗值不對時,讀取備份的NV文件并提供給基帶。同時,在基帶內部也有一套默認配置(與An?droid文件系統中的備份文件內容一致),當基帶從Android獲取的數據校驗不正確時,基帶使用自己的默認NV參數。
本方案的提出,解決了AT命令并發和NVM參數的存儲帶來的問題。采用串行傳輸和同步讀寫,提高了AT命令的處理效率,并且減少了時延。NVM數據存儲方案的提出,提高了NVM的讀寫速率,直接通過文件系統就可以快速地進行NV文件的更換。
AT并行處理流程的調試結果:Android組裝AT命令(0x06:AT標志;0x41542B4353510D:AT指令)并寫入到Vpipe(如圖6);通過中斷的方式觸發基帶Vpipe驅動去讀取AT指令,在MCD適配層進行記錄AT標志并且去AT標志,然后發送到協議棧(如圖7);協議棧收到AT指令后,返回“OK”,發送到MCD,再由MCD進行AT標志的填充,發送給Vpipe,最后發送到Android。


圖7 ARM log(截圖)
NVM數據存儲方案的調試結果(如圖8):基帶通過與Android交互實現對NVM參數的存取,此過程是通過Vpipe完成對Share Memory的操作。

圖8 NVM數據存儲基帶log(截圖)
本文通過引入虛擬管道技術,提出了高效的NV參數存取方案。虛擬管道技術,實現了Android和Nucleus的信息交互,包括AT指令、PSCS數據、URC數據等,完成了基帶和應用之間的一系列數據的交互。NV參數存取方案的提出,實現了基帶對NVM數據的存取,實現了基帶通過與Linux進行必要的交互,完成NVM數據的存取。
該方案的提出為實現單芯片上運行雙操作系統的嵌入式系統提供了很好的解決方案,具有很好的應用價值。
[1]英特爾開源軟件技術中心,復旦大學并行處理研究所.系統虛擬化原理與實現[M].北京:清華大學出版社,2009.
[2]張易知,徐國治.基于微內核架構的嵌入式系統虛擬化技術[J].電子產品世界,2009(4):47-49.
[3]MARTIN A,FLAKE J.嵌入式系統軟件調試跟蹤技術的發展趨勢[J].電子設計應用,2005(7):16-18.
[4]崔燁.基于Linux平臺的智能手機軟件設計與實現[D].成都:電子科技大學,2007.
[5]HU Xiao,CHEN Shuming.Applications of on-chip trace on debug?ging embedded processor[C]//Proc.Eighth ACIS International Confer?ence on Software Engineering,Artificial Intelligence,Networking,and Parallel/Distributed Computing.[S.l]:IEEE Press,2007:140-145.