睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接
這幾天一直在看MMU部分,現在有了基本的認識,還不深入,解決了初級問題,并且仿照vivi完成了一個測試實例,對深入理解和驗證推論的結果很有幫助。在學習的過程中,體會到幾種方法還是比較實用的:
· 從歷史的角度去了解技術,梳理清楚發展主線,效率更高。
· 采用軟硬件結合的方法分析,理解更為深入。
· 與同一愛好的朋友交流,可以發現認識的盲區,認識更為全面。
· 應該閱讀英文的Datasheet,中文翻譯往往有錯誤,有時候是致命的,以前在c8051F020的SPI的設計中就因為這個問題研究了一周,最后才發現中文翻譯有問題,這也足以說明還是原版更具有可信度。但是呢,不要絕對化,原版也可能有錯誤。在閱讀學習的過程中,
如果理解到設計的巧妙,那么很好,拿來使用。如果暫時不能理解,或者認為原版有錯誤,那么不妨持懷疑的態度進行學習,即使錯了,也能學到很多東西,甚至從錯誤中學到的東西更多。
· 充分利用網絡資源。站在巨人的肩上可以更高更遠!但是,你必須訓練讓自己具備找到巨人的能力!
下面開始MMU的探討。因為還只是處于初級階段,本文僅就MMU的基礎方面和應用作一下探討,其中還有沒有明確的地方,待解決。
一、MMU是什么?
MMU,英文名稱為Memory Manage Unit, 中文可以為“內存管理單元”,或者“存儲器管理單元”。MMU是硬件設備,它與virtual memory是緊密聯系在一起的。
看一下s3c2410 datasheet Appendix 1中關于ARM920T的介紹(因為s3c2410采用的是ARM920T的處理器)。對ARM9系列處理器有如下幾種:
--ARM9TDMI(ARM9TDMI Core) --ARM940T(ARM9TDMI core plus cache and protection unit) --ARM920T(ARM9TDMI core plus cache and MMU)
|
可見ARM920T具備了MMU功能部件。而且還有cache。它采用了一種變形的Harvard架構,擁有16KB的Instruction cache和16KB的Data cache,MMU和cache有密切的聯系,后面會談到。
總之,由于s3c2410這款SoC采用了ARM920T的處理器(處理器內核為ARM9TDMI,關于這些命名的區分在前面已經討論過了),所以擁有了MMU和cache。有了這個硬件基礎,軟件上才可能使用這個功能。那么,現在的問題是,s3c2410擁有MMU,那么MMU到底有什么用呢?還是從歷史發展的角度看一下。
二、從歷史發展的角度看MMU的作用
這一部分可結合蔡于清的講解【網址:
http://www.another-prj.com/viewthread.php?tid=28&extra=page%3D1】來看,下面的大部分內容轉載此處,針對自己的理解做了一些擴充性說明。只是需要注意的是,在蔡于清此部分的講解中,有幾處小的錯誤,完成此部分的講解后可以進行更正。
MMU功能部件是與虛擬內存技術(virtual memory)緊密聯系在一起的。
第一階段:最初,計算機內存很小,而且非常昂貴,大多數都是以KB為單位的。相應的,當時程序規模很小,不復雜,所以內存還是能夠滿足需求的。在看《Linkers and Loaders》的時候,也是從這個階段講解,不過此書的核心視角是從Linkers和Loaders的發展來看的。也就是,計算機剛剛出現時,還是比較簡陋的,各種復雜的技術是伴隨著人們需求的提高而出現的。把握住這一點,就可以從需求的角度入手探討技術,可以分析它如何滿足了這樣的需求。通過這種分析,理解上就比較簡單一些了。
第二階段:程序規模擴大,考慮到成本問題,出現了overlay技術,也就是內存覆蓋策略。基本的原理就是把程序分割成許多稱為“覆蓋塊”的片斷。覆蓋塊0首先加載運行,結束時調用另一個覆蓋塊。覆蓋塊的調度是由OS來完成的,但是
事先需要分割,這部分工作是程序員借助Linkers來完成的。但是畢竟枯燥,由此帶來的開銷也比較大。于是進入第三個階段。
第三階段:出現virtual memory。虛擬存儲器的基本思想是程序,數據,堆棧的總的大小可以超過物理存儲器的大小,操作系統把當前使用的部分保留在內存中,而把其他未被使用的部分保存在磁盤上。比如對一個16MB的程序和一個內存只有4MB的機器,OS通過選擇,可以決定各個時刻將哪4M的內容保留在內存中,并在需要時在內存和磁盤間交換程序片段,這樣就可以把這個16M的程序運行在一個只具有4M內存機器上了。而這個16M的程序在運行前不必由程序員進行分割。
伴隨著這種技術的出現,“virtual address,即VA”和“physical address, 即PA”也就出現了。一般來說,CPU看到的地址是VA,VA是由地址線來決定的。比如,s3c2410是32位的SoC,那么它的尋址空間為2^32=4GB,那么VA空間也就是4GB。但是在嵌入式系統中,物理存儲器是不會有這么大的。現在這塊s3c2410的實際內存SDRAM也就64MB,遠遠小于4GB。也就是說,VA是4GB,PA是64MB,PA的地址空間是VA地址空間的子集。既然PA沒有VA那么大,而且CPU只能看到VA,那么CPU如何找到PA呢?這也正是MMU的基本作用之一,就是提供VA到PA的轉換機制,除了硬件的支持外,軟件上實際就是維護一張表,表中的內容是VA到PA的轉換法則。由于有了MMU,那么就可以實現利用VA找到實際物理內存區域。
現在討論為什么要實現VA到PA的映射。就ARM而言,系統上電后,CPU的PC指向0x00000000(低端模式)或者0xffff0000(高端模式),這是由CPU的設計者決定的。在這個位置,一般安排非易失性存儲器地址空間,比如rom,flash等。但是flash等響應速度慢,這就稱為提高系統性能的一個瓶頸。而sdram則具有很高的響應速度,為了提高系統運行速度,可以把flash中的應用程序下載到sdram中執行,也就是一個簡單的loader的功能實現。這樣就出現一個問題,ARM響應exception時,程序指針指向固定的VA,比如,假設發生了IRQ中斷,那么PC執行0x00000018(如果是高端啟動,則指向0xffff0018處。)但是此處仍然為非易失性存儲器,也就是說,程序的一部分仍然在flash或者rom中執行。這時可以利用MMU,把sdram的地址映射到0x00000000起始的一片連續地址空間,而把原來flash映射到其他不相沖突的存儲空間位置。例如,flash的地址范圍0x00000000-0x00ffffff,sdram的地址范圍0x30000000-0x31ffffff。那么可以把sdram映射到0x00000000-0x1fffffff(此處地址空間未被占用)。映射完成后,如果處理器異常,假設依然為IRQ中斷,pc指向0x00000018,但是pc實際上是從物理地址0x30000018處讀取指令。通過mmu的映射,可以實現系統運行的加速。這個地方也可以說明bootloader中常見的中斷向量表的設置,為什么有些使用b,有些使用ldr了。【b的跳轉空間只能是+-32M,而ldr可以大的多了。】
在實際的應用過程中,還可能會把兩片不連續的物理地址空間分配給sdram,而在os中,習慣上把sdram的空間連續起來,方便實現動態內存管理。通過mmu可以實現不連續的物理地址空間映射為連續的虛擬地址空間。
另外一個需求就是,實現不同的運行級別,那么一些關鍵的代碼可以設定不被普通應用程序訪問。這也是通過mmu控制訪問權限來實現的。
綜上三個階段所述,可見MMU的作用主要就是兩個:
· 實現VA到PA的映射(可以因此實現方便的動態內存管理)
· 實現不同的訪問權限。
三、結合s3c2410來分析MMU的幾處硬件特點
首先看看ARM920T的框圖:

可以驗證前面的幾個概念:
·位于中心的ARM9TDMI Processor Core發出的地址有兩種,IVA和DVA,都是VA。其中I代表Instruction, D代表Data。也就是說,CPU核心看到的都是32bits的VA。
·Dcache、Icache、Dmmu、Immu看到的都是對應的MVA(modified virtual address),這個是比較復雜的地方,下面專門拿出這個來講解。
·MMU處理后的輸出地址都是對應的PA,通過AMBA Bus Interface連接到ASB總線上面。
這樣,從硬件上對地址的概念就比較清晰了。也可以很明顯的看出MMU的功能:將VA轉換成PA。但是現在存在的一個問題是,MVA是什么,為什么要用到MVA?
可以看CP15協處理器的register 13。這個寄存器是進程識別寄存器,主要的操作如下:
Reading from CP15 register 13 returns the value of the process identifier. Writing CP15register 13 updates the process identifier to the value in bits [31:25]. Bits [24:0] should be zero.
|
寄存器的字格式為:

很清晰,ProcID為7bits,剩下的25bits should be zero,也就是可以實現2^25=32M的地址對齊。從這個道理上講,每個進程擁有32M的MVA地址空間,而最多支持的進程數為2^7=128個。這樣,128*32M=4GB,正是全部的虛擬地址空間。但是,英文的datasheet上卻并非如此,寫的記錄數字為64個進程,同樣每個進程32M,怎么可能達到4GB?參看下圖:

我覺得上圖中的63應該改為127。因為這個63處不可能對應4GB,而應該對應2GB。判斷此處屬于datasheet的錯誤。
還有,這個procID是何時,有誰寫入的?有誰來維護?根據推斷,
在bootloader階段,只需要一個進程就可以了,所以,procID一直都是復位后默認的0,不需要改變。但是后面有了OS后,要想實現多進程,那么就需要對此維護了。所以procID的維護者是系統軟件OS。在創建一個新進程的時候,要把進程號寫入procID。
另外,關于MVA部分的轉換公式,實際上還是有疑問的。
Addresses issued by the ARM9TDMI core in the range 0 to 32MB are translated by CP15register 13, the ProcID register. Address A becomes A + (ProcID x 32MB). It is thistranslated address that is seen by both the Caches and MMU. Addresses above 32MB undergo no translation.
|
寫成偽代碼,可以參考《s3c2410完全開發》。
if VA < 32M then MVA = VA | (ProcID << 25) else MVA = VA
|
thisway.diy說利用PID來生成MVA的目的是為了減少切換進程時的代價:如果兩個進程占用的VA有重疊,不進行上述處理的話,當進行進程切換時必須進行VA到PA的重新映射,這就需要重新建立頁表,使無效cache和TLB等等,代價很大。但是如果進行上述處理的話,進程切換就省事多了:假設兩個進程1、2運行時的VA都是0-32M,則它們的MVA分別是(0x02000000-0x03ffffff)、(0x04000000-0x05ffffff),前面看到的MMU、cache使用MVA而不是使用VA,這樣就不必進行重建頁表等工作了。
但是這里帶來的一個問題是,如果進程運行時的VA小于32M,那么根據PID的不同,可以達到4GB空間的任意部分,也就是,雖然可以避免運行VA小于32M時的不同進程的“撞車”,但是同時帶來的是VA小于32M可能與VA大于32M的進程產生了“撞車”。這樣不是更為普遍嗎?現在從原理上還不能理解。翻看《ARM Architecture Reference Manual》,發現對于ARM核,如果采用MVA,那么進程切換實際上對應著Fast context switch extension,不知道原理是什么。對于研究bootloader來說,現在不設計到多進程,整個系統就是一個獨立的單進程,PID就是默認的0x0。這個問題可能要后推了。
四、提出幾個問題
1、在vivi中為什么使用了MMU?是否可以不用?
這個問題已經解決。實際上,在nand flash啟動的情況下,vivi中可以不使用MMU。因為一是中斷向量表是放在sram里,響應速度比sdram還要快。另外,在bootloader階段,只有一個進程,不存在多進程的內存空間重疊的問題。也因為一個進程,所以單純的PA就滿足需求,沒有必要用VA。開始時,也不需要區分訪問權限。大量的工作,比如進程切換、權限訪問等等,都是在EOS中處理的。所以,這種情況下,可以不使用MMU。我把vivi中關于MMU的部分去除,編譯下載,可以正常引導內核啟動,沒有問題。
那么,vivi為什么要開啟MMU呢?原因也是比較簡單的,就是追求系統運行的高效。因為s3c2410的Icache不受MMU的影響,而Dcache和write buffer則必須開啟了MMU功能之后,才能使用。而使用Dcache和write buffer后,對系統運行速度的提高是非常明顯的,后面還將通過實驗來驗證這一點。也就是說,在nand flash啟動時,vivi使用了MMU,主要是為了獲得Dcache和write buffer的使用權,借此提高系統運行的性能。
2、使用了MMU,那么軟硬件是如何分工協作的?
這個基本搞清楚了,但是還有一個遺留問題。針對于s3c2410,可以分為如下幾個階段:
· 第一階段 軟件準備
MMU在軟件上的實現過程,實際上就是一個查表映射的過程。建立頁表(translation table)是MMU功能的重要的一步。
頁表就是內存的一塊區域,由一個個固定格式的entry組成。其中每個entry對應一個VA到PA的轉換,每一項的長度是一個word,還可以完成訪問權限和緩沖特性的限定。在軟件上,就是要把這個表填好。重映射就是修改相應的entry,改變了原來的映射規則,很簡單。
這步工作是要軟件提前準備的。需要注意的是,明確如何找到這個頁表。對于表的查找,需要知道表的基地址和偏移地址,在cp15的register 2用于保存頁表的基地址,這樣就可以查找到相應的PA了。
· 第二階段 硬件完成VA-MVA
硬件根據ARM9TDMI發出的VA和CP15的register 13來自動生成MVA。
· 第三個階段
硬件自動實現cache查詢,如果沒有,則根據cp15的register 2和MVA找到translation table中的entry,實現相應的PA轉換,讀取內存,然后根據cache算法更新cache。也就是說,這個階段也是硬件實現的。不過軟件上對cache要進行相應的管理,這個地方的算法相對還是比較復雜的。
綜上,對單進程而言,軟件操作上就是維護translation table,并且處理好cache相關操作。
五、實驗
實驗內容比較簡單,綜合了前面的串口實驗,燈循環點亮實驗,中斷實驗,nand flash實驗,另外,加入了MMU功能。利用MMU功能的開啟,觀察燈循環點亮實驗,如果開啟了Dcache和write buffer,燈閃的速度明顯快的多,幾乎看不出間隔,而把其關閉,則還能夠看出間隔。這還是在12MHz的前提下,還沒有把PLL功能開啟。如果把PLL功能開啟,還需要進行相應的調整。
源代碼如下,完全仿照vivi的架構,另外,mmu部分基本是采用vivi的源代碼,具體的分析留待vivi源代碼分析時解決。其實,如果開啟了mmu,cache和write buffer是否能夠合理有效的使用還是一個問題。如果使用不當,帶來的問題可能會比較奇怪,而且難以解決。在這個過程中,需要對照現有的較好的代碼進行分析,總結規律,然后應用到自己的設計中去。
from:http://blog.csdn.net/liangkaiming/article/details/6310098
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成