2. Linux 環境中各種位址 Physical address、Bus address、virtual address 之間的轉換
3. memory mapping
4. 控制硬體的方式—I/O port、
MMIO 5. PCI 裝置
6. PNX1005 的 memory apertures 7. 如何讀取 memory apertures 資訊 8. 程序並行控制
9. 中斷機制
研究主題
第三章 控制 PNX1005 的 Linux 驅動程式 1. Linux 驅動程式功能與操作介面 的設計架構
2. 驅動程式的啟動
3. 利用 linux 驅動程式設計架構來 實作 TMMan 驅動程式功能 4. 設計 user mode library 作為驅
動程式與應用程式的界面 第四章 ARM 與 DSP 端底層溝通機制與架
構
詳細說明分散式處理應用的 CPU 如 何藉由底層的共享記憶體、中斷機制 傳送訊息,再搭配 client-server 的 架構完成溝通
第五章 指令溝通—
C Runtime Service
說明 DSP 如何利用第四章的溝通架 構來傳遞指令,並以 ARM 為 server,
由負責檔案管理的 ARM 提供的 CRT 應 用服務完成檔案輸出入
第六章 實驗—
DSP 端人臉擷取指令設計
在 ARM 端以 CRT 服務為基礎,設計一 個可以接收 DSP 端偵測出的人臉位
4
址,將人臉從 DSP 端 RAM 複製到 ARM 端記憶體的指令設計
第七章 結論
附錄 Appendix
A PNX1005 暫存器
B DSP 端各種指令對應的 ID C 於 linux 環境開發主機中編譯
tmman 驅動程式、ARM 端應用程 式的環境設定
D TMMan 驅動程式辨別多個相同 類型的 PNX1005 的機制 E user library 初始化所需的廣
域結構
F 函式庫應用實例:tmload 中下載 DSP 端可執行檔的運作
G copy_from_user/copy_to_user H 使用 termination_handler 重新
請求 ARM 端服務(讀檔)
5
第二章 Linux 驅動程式設計環境
DVR 平台上的 ARM CPU 與 DSP 端 PNX1005 裝置是透過 PCI 匯流排來進行資料的傳遞,
其中 ARM 為一個中控系統(host),負責處理與 DSP 端還有與開發主機之間的溝通,對 ARM 來說,PNX1005 就是一個 PCI 裝置,我們便在 ARM 端設計一個可以控制 PNX1005 的驅動程 式。
因為 ARM 端的 OS 是 linux,所以我們就以 linux 驅動程式的設計架構與環境來開發 這個驅動程式,由於驅動程式必頇以軟體來控制硬體,期間會牽涉很多 physical memory 與 virtual memory 的議題,所以 2-1 節會介紹 linux 對 physical memory 與 virtual memory 的管理與對應,讓讀者知道兩者間的映射關係,做為第三章設計 linux 驅動程式中設計 mmap handler 的重要背景知識, 2-2 節則會介紹負責將 physical memory 映射到 virtual memory 的映射種類與負責的函式,而 2-3 節另會探討 physical memory 與 virtual memory 位址 轉換的關係,於第四章提到的 shared memory 劃分提供位址轉換觀念,了解記憶體映射與 位址轉換觀念後,2-4 節 MMIO 控制硬體的機制其實就會透過虛擬記憶體使用到實體記憶體,
然後由實體記憶體的設定對裝置上暫存器作控制。
接下來 2-4、2-5 提供第四章兩端 CPU 使用共享記憶體進行溝通時,除了驅動程式對 記憶體基本的操作外,還需要使用到的操作機制。2-5 節會介紹設計 linux 驅動程式的中 斷機制,以硬體中斷來通知對方接收訊息,而且由於溝通時使用的共享記憶體,程式設計 者在軟體上會使用許多結構來操作這塊硬體,為了避免兩個 process 同時去修改共享記憶 體中的資料,所以 2-6 節會介紹一般 linux 環境下如何在程序中保護 critical section,
還有中斷機制在 linux 環境中存在的意義與使用方式。
最後,由於 ARM 與 PNX1005 是以 PCI 匯流排連接,所以對 ARM 來說 PNX1005 晶片就是 一個 PCI 裝置,為了控制 PCI 裝置,2-7 節會介紹一般 linux 下 PCI 裝置會提供哪些重要 的記憶體位址資訊與硬體資訊給驅動程式,而驅動程式又是用什麼樣的方式來獲取 PCI 裝 置所給的資訊,讓驅動程式可以從這些資訊去操作它。2-8、2-9 節則會介紹 PNX1005 這個 PCI 裝置究竟提供了什麼樣的資訊給 ARM 的驅動程式,ARM 的驅動程式又使用了 2-7 節哪 些函式來讀取這些資訊。
2-1 physical memory 與 virtual memory
一般程式設計者都只在 virtual memory 中進行設計,但由於驅動程式不只是寫軟體,
還需要控制硬體,因此在必要的時候驅動程式必頇負責作 phsical memory 映射 virtual
6
memory 的動作,這在一般程式設計是很少見的,所以本節會介紹基本的 phsical memory 與 virtual memory 存在的意義,還有 linux 對記憶體的管理與兩種記憶體之間的映射關 係。
由於 CPU 運算所需資料或程式碼都必頇先載入到實體記憶體後才能由 CPU 取用,但是 為了讓使用者感覺上有很大的記憶體空間可以用來設計程式,而且讓 physical memory 可 以被有效利用,於是使用者便在 virtual memory 環境設計程式,真正運作的時候系統才 會把需要運作的部分載入到 physical memory 上執行。雖然在運作的時候系統會自動載入 需要運行的部分到 physical memory 上,但是在設計驅動程式時,因為控制硬體的方式可 能會希望藉由實體記憶體的操作就可以反應到裝置上(MMIO 的方式),或是說希望在 user space 就可以藉由特定的 physical 與 virtual memory 的映射關係(mmap)將檔案或實體記 憶體空間映射到 virtual memory 後,直接在使用者空間做檔案複製的動作,所以我們還 必頇知道 linux 如何管理 physical memory 與 virtual memory、它們之間的 memory mapping,
以及環境中各種記憶體位址的轉換關係,才能在設計驅動程式時做好 virtual memory 與 physical memory 的對應。
在使用 MMU 的 CPU 架構下,系統設計者可以利用的虛擬記憶體約 4GB。因為一般 user 或驅動程式開發者在開發程式的時候,都是在虛擬記憶體裡運作的,為了讓 user 不能隨 便更改重要的硬體設定與系統運作機制,以預防嚴重的系統錯誤或是惡意傷害系統的行為,
又把虛擬記憶體空間分為 user space 與 kernel space。在 kernel space 中運作的程式,
可以讓 kernel 來掌管重要的系統運作行為,所以驅動程式開發者便在 kernel space 設計 驅動程式;如果使用者想要使用硬體或利用系統中的重要資源時,則必頇使用系統呼叫請 求 kernel 的許可與協助,因此如果 user 想要驅動程式做控制硬體的動作,就需要一個與 驅動程式連接的系統呼叫來請求 kernel 中的驅動程式協助,因此我們還必頇要注意資料 如何在 user space 與 kernel space 做複製或交換(3-1-3 的 ioctl handler)。
通常,每個 user process 可以使用的虛擬記憶體空間為 0~3GB,我們把這段空間稱為 user space;由於以前只能在實體記憶體內運作的 kernel 程式現在也可以利用虛擬記憶 體來運作了,所以我們把虛擬記憶體的 3G~4G 分配給 kernel 程式,這段空間就像是每個 process 都會擁有的相同區段,我們稱為 kernel space,因此,就算實體記憶體有 4GB,
CPU 也看得到 4GB 的物理記憶體空間,但 user process 永遠看得到的使用空間就是 3GB。
另外,虛擬記憶體空間裡 1G 的 kernel space 又可分成實體記憶體映射區、vmalloc 分配器區、高階記憶體映射區、專用頁面映射區及保留區(圖 2.1),一般情況下,實體記 憶體映射區最大長度為 896MB,此區以 1:1 linear mapping 的方式依序將系統的實體記憶 體映射到虛擬記憶體的 kernel space 去,而未超過實體記憶體映射區所對應的實體記憶
7
體也另外稱為常規記憶體;當系統實體記憶體大於 896M 時,超過此界限以上的實體記憶 體稱為高階記憶體,會被映射到虛擬記憶體 kernel space 的高階記憶體映射區。
(表 2.1)詳細說明了 linux kernel 2.6.22.18 如何劃分 kernel space 的每個區塊,
從 3G 開始到最大 3G+896M(high_memory)的範圍為實體記憶體映射區,通常 high_memory 以上的空間就是高階記憶體映射區,只是還可以藉由 VMALLOC_START 與 VMALLOC_END-1 位 址空間定義出 vmalloc 分配器區,另外還有其它的專用頁面或保留區供 OS 或未來開發使 用。通常驅動程式運作時作 kmalloc 動作分配出的虛擬記憶體空間以及變數,會位於實體 記憶體映射區(PAGE_OFFSET~high_memory-1),當 kernel 使用 vmalloc 配置連續的虛擬記 憶體空間(但實體記憶體不一定連續)或是利用 ioremap 將實體記憶體空間映射到虛擬記憶 體的 kernel space 時,這塊 kernel space 虛擬空間區段會位於 vmalloc 分配器區內 (VMALLOC_START~VMALLOC_END-1);如果像我們使用的平台,為了在 ARM 端創建一塊與 DSP 端溝通的 shared memory 時,使用到 dma_alloc_coherent 函式在實體記憶體中分配連續 且 nocache 的記憶體時,則會同時將這塊實體記憶體映射到 kernel space 的 DMA memory mapping region;如果使用者呼叫 mmap 這個系統呼叫,則會將實體記憶體映射到虛擬記 憶體的 user space 去。因此,未來我們設計的驅動程式,大部分會運作在 kernel space 的實體記憶體映射區、vmalloc 分配器區與高階記憶體映射區。
Virtual memory physical memory
3G 4G
0 User space
kernel space
4G
3G
0 896M Kernel space 的
Virtual memory 3G
4G
實體記憶體映射區 kmalloc(_get_free_pages)
vmalloc 分配器區 高階記憶體映射區 專用頁面映射區
保留區
MMIO
(圖 2.1)虛擬記憶體與實體記憶體的映射關係以及 kernel space 的管理狀況
8
(表 2.1)kernel 2.6.22.18 在 virtual memory 的分配狀況:
Start End Use
ffff8000 ffffffff copy_user_page / clear_user_page use.
For SA11xx and Xscale, this is used to setup a minicache mapping.
ffff1000 ffff7fff Reserved.
Platforms must not use this address range
ffff0000 ffff0fff CPU vector page.
The CPU vectors are mapped here if the CPU supports vector relocation (control register V bit.)
ffc00000 fffeffff DMA memory mapping region.
Memory returned by the dma_alloc_xxx functions will be dynamically mapped here.
ff000000 ffbfffff Reserved for future expansion of DMA mapping region.
VMALLOC_END feffffff Free for platform use,recommended. VMALLOC_END must be aligned to a 2MB boundary.
VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space.
Memory returned by vmalloc/ioremap will be dynamically placed in this region.VMALLOC_START may be based upon the value of the high_memory variable.
PAGE_OFFSET (3G)
high_memory-1 (3G+ 896M)
Kernel direct-mapped RAM region.
This maps the platforms RAM, and typically maps all platform RAM in a 1:1 relationship.
TASK_SIZE PAGE_OFFSET-1
Kernel module space Kernel modules inserted via insmod are placed here using dynamic mappings.
00001000 TASK_SIZE-1
User space mappings
實體記憶體
9
Per-thread mappings are placed here viathe mmap()
00000000 00000fff CPU vector page / null pointer trap
CPUs which do not support vector remapping place their vector page here. NULL pointer
dereferences by both the kernel and user space are also caught via this mapping.
(資料來源:linux kernel 2.6.22.18 的 document) 從虛擬記憶體對應到實體記憶體
為了讓實體記憶體的使用更有效率,避免因 contiguous memory 配置記憶體的方式造 成的記憶體浪費,linux 因此基於 paging 系統來做實體記憶體管理。當程式開始運作的 時候,CPU 必頇從實體記憶體中讀取 instruction 並 decode 它,在解這個 instruction 的 時候可能還需要到實體記憶體中去 fetch 其他 instruction 或是將資料從實體記憶體 load 到 CPU 去,然而這些資料或是 instruction 的位址一開始可能都在 virtual system 裡面,所以會以 virtual address 表示資料或 instruction 所在位址。因此,CPU 必頇將
為了讓實體記憶體的使用更有效率,避免因 contiguous memory 配置記憶體的方式造 成的記憶體浪費,linux 因此基於 paging 系統來做實體記憶體管理。當程式開始運作的 時候,CPU 必頇從實體記憶體中讀取 instruction 並 decode 它,在解這個 instruction 的 時候可能還需要到實體記憶體中去 fetch 其他 instruction 或是將資料從實體記憶體 load 到 CPU 去,然而這些資料或是 instruction 的位址一開始可能都在 virtual system 裡面,所以會以 virtual address 表示資料或 instruction 所在位址。因此,CPU 必頇將