字元裝置驅動2 虛擬位址對映

2021-09-25 11:36:43 字數 3164 閱讀 9303

前言:驅動程式和應用程式一樣,在系統啟動之後都是執行在虛擬位址之中,每乙個程序單獨的享用4g的位址空間,那麼虛擬位址到底是怎麼建立的呢,在使用它進行硬體驅動的操作前有必要對其進行了解,下面將對靜態、動態虛擬位址的對映原理和使用方法做乙個分析和介紹。

1.靜態對映方法的特點:

(1)核心移植時以**的形式硬編碼,如果要更改必須改源**後重新編譯核心,核心移植完成之後對映方法一直存在;

(2)在核心啟動時建立靜態對映表,到核心關機時銷毀,中間一直有效。

2.cpu的主對映表:

以三星為s5pv210移植的核心為例,其主對映表位於:arch/arm/plat-s5p/include/plat/map-s5p.h,此檔案按照模組有序的將內部眾多的暫存器巨集定義為規定的虛擬位址。

#define s5p_va_chipid		s3c_addr(0x00700000)

#define s5p_va_gpio s3c_addr(0x00500000)

#define s5p_va_systimer s3c_addr(0x01200000)

#define s5p_va_sromc s3c_addr(0x01100000)

#define s5p_va_audss s3c_addr(0x01600000)

#define s5p_va_uart0 (s3c_va_uart + 0x0)

#define s5p_va_uart1 (s3c_va_uart + 0x400)

#define s5p_va_uart2 (s3c_va_uart + 0x800)

#define s5p_va_uart3 (s3c_va_uart + 0xc00)

#define s3c_uart_offset (0x400)

可以發現這些虛擬位址都是基位址+偏移位址構成的。

#define s3c_addr_base	(0xfd000000)

#ifndef __assembly__

#define s3c_addr(x) ((void __iomem __force *)s3c_addr_base + (x))

#else

#define s3c_addr(x) (s3c_addr_base + (x))

#endif

3.以gpio為例,繼續分析:

#define s5pv210_gpa0_base		(s5p_va_gpio + 0x000)

#define s5pv210_gpa1_base (s5p_va_gpio + 0x020)

#define s5pv210_gpb_base (s5p_va_gpio + 0x040)

#define s5pv210_gpc0_base (s5p_va_gpio + 0x060)

#define s5pv210_gpc1_base (s5p_va_gpio + 0x080)

#define s5pv210_gpd0_base (s5p_va_gpio + 0x0a0)

...............

每乙個gpio口的虛擬位址都是以這個位址+偏移位址得到,而這個基位址就是上一步中得到的s5p_va_gpio,也就是s5p_va_gpio=0xfd000000+0x005000000=0xfd500000。

(2)每個gpio口具體功能暫存器的定義位於:arch/arm/mach-s5pv210/include/mach/gpio-bank.h。同上同上基位址+偏移位址得到。這裡的基位址換成了每乙個gpio口的起始位址。

4.虛擬位址-->實體地址的對映

static struct map_desc s5p_iodesc __initdata = , , , , , , ,

};

再次以gpio為例:

.virtual= (unsigned long)s5p_va_gpio 代表 將轉換成的虛擬位址,也就是上面對映表中巨集定義的位址;

.pfn= __phys_to_pfn(s5p_pa_gpio) 代表實際的實體地址;

.length    = sz_4k  代表對映的記憶體長度;

.type = mt_device 代表記憶體的型別。

5.開機時進行對映表的建立

之前在分析核心的啟動時有分析過start_kernel()函式中先後兩次完成了虛擬位址的對映,的確,對映表的建立就是通過執行start_kernel()中多層包含的函式devicemaps_init()完成的。

start_kernel()

setup_arch(&command_line);

paging_init(mdesc);

devicemaps_init(mdesc);

if (mdesc->map_io)

mdesc->map_io();

至此開機後就可以使用虛擬位址。

1.動態對映方法的特點:

(1)驅動程式根據需要隨時動態的建立對映、使用、銷毀對映;

(2)對映是短期臨時的。

2.建立對映:

request_mem_region:先向核心申請需要申請的記憶體資源;

ioremap:再實現對映,傳給它實體地址,會返回對映返回的虛擬位址。

2.銷毀對映:

iounmap:先解除對映;

release_mem_region:再釋放申請。

注:建立對映和銷毀的步驟是倒影,順序不能錯。

總結:

(1)2種對映並不排他,可以同時使用(多個虛擬位址可以指向同乙個實體地址);

(2)靜態對映類似於c語言中全域性變數,在系統執行期間一直有效,動態方式類似於c語言中malloc堆記憶體,使用前需要進行申請;

(3)靜態對映的好處是執行效率高,壞處是始終占用虛擬位址空間;動態對映的好處是按需使用虛擬位址空間,壞處是每次使用前後都需要**去建立對映&銷毀對映(還得學會使用那些核心函式的使用)。

end。。。。。。

字元驅動裝置3(虛擬位址對映)

核心中有兩套虛擬位址對映方法 動態和靜態 靜態對映 核心移植時以 的形式硬編碼,如果需要改變需要更改源 後重新編譯核心,核心啟動時建立靜態對映表,內 核關機時銷毀,中間一直有效。動態對映 驅動程式根據需要隨時動態建立對映,使用 銷毀對映,對映的短期的 動態對映和靜態對映是可以同時使用的。靜態對映好處...

Linux虛擬位址對映

我們定義乙個區域性變數,然後列印出這個區域性變數的位址,那麼這個區域性變數的位址是線性位址?實體地址?還是邏輯位址?要明白這些,先來看看以下的知識吧。x86體系 指的是特定微cpu執行的有些 計算機語言 指令集,定義了 晶元的基本用規則 cpu的位數 alu一次性最多能處理的整數的位元組數,也即al...

HPS 虛擬位址對映

hps 如何對fpga外設進行操作?hardware 在qsys中將外設連線到axi bridge上 software 對映外設實體地址到到應用程式可以操作的虛擬位址,應用程式通過得到的虛擬位址入口控制外設。也就是說hps訪問fpga中的外設時,可以使用mpu來進行虛擬位址的分配 mpu將以有的外設...