在linux kernel 中,實體地址是不能直接使用的,arm9可以最大定址範圍為1g,其從0x00000000開始都是實體地址。。必須通過轉換才可以。
轉換分為兩種, 靜態和動態。
靜態就是下面那種,不過,靜態的位址轉換,還需要在kernel 初始化的時候作對映。
動態對映是使用 ioremap 函式 。
[cpp]view plain
copy
#define sl2312_gpio_base 0x4d000000
#define io_address(x) (((x)&0x0fffffff)+(((x)>>4)&0x0f000000)+0xf0000000)
#define gemini_gpio_base1 io_address(sl2312_gpio_base)
linux 有記憶體保護機制,無論是核心態還是使用者態。
靜態對映 :是在實體地址上加乙個偏移量, 所以虛擬位址是固定的。
動態對映 :系統會生成乙個虛擬位址對應到實體地址上,虛擬位址不是固定的。
linux在初始化執行時會根據乙個map_desc的陣列中的實體地址進行靜態對映,0x4d000000位址應該就是這樣對映的。
靜態對映的位址無須使用icoremap函式,只要知道在map_desc陣列中實體地址與虛擬位址的移仿就可以了。
至於驅動程式中關於實體地址是不是都要轉換呢,這個是當然的,linux是執行在虛擬位址的。
任何程式不能訪問實體地址,都必須轉換為實體地址才能訪問。只不過,在核心空間已經是轉換好了的(如前所述),可以隨便的訪問。
動態對映是由linux核心統一管理,當使用kmalloc(分配在核心空間)和malloc函式申請時,核心會找到一塊空餘的物理記憶體,並在頁表中動態地新增一項其與虛擬位址對應的表項。
靜態對映那應該就是linux在初始化階段讀取map_desc陣列進行的位址對映,map_desc中包括了一對對的實體地址和虛擬位址的對應關係,這個可以根據硬體修改,其中的虛擬位址必須是核心空間的,例如,sdram的物理是0x30000000 那麼可以將其對映為0xe0000000. 通過靜態對映後的位址一般之後就不會更改了的,除非你想辦法改掉。
#define arinc429_base 0x10000000//bank2的起始位址 (即定義真實的實體地址)
virt = (unsigned long)ioremap(arinc429_base,0x80); // virt是虛擬位址的首位址,128個位元組的虛擬位址
實體地址到虛擬位址的動態對映 0x10000000對的就是virt 對virt的操作就是對實際實體地址0x10000000的操作
ch1_ctr_reg = (unsigned long *)(virt + 0x14); 對實體地址0x00000014的對映
邏輯位址空間和實體地址空間
位址空間是乙個程序可用於定址記憶體的一套位址集合。1 程式經過編譯後,每個目標模組都是從0號單元開始編址,稱為該目標模組的相對位址 或邏輯位址 2 當鏈結程式將各個模組鏈結成乙個完整的可執行目標程式時,鏈結程式順序依次按各個模組的相對位址構成統一的從0號單元開始編址的邏輯位址空間。3 使用者程式和程...
Linux 核心空間虛擬位址和實體地址相互轉換
個人學習筆記,可能會有錯誤之處,敬請諒解。一直以來感覺虛擬位址和實體地址之間的相互轉換非常麻煩,虛擬位址到實體地址的轉換由cpu硬體完成,但實體地址到虛擬位址怎麼轉換啊?況且有時候在軟體上也希望通過乙個虛擬位址得到實體地址,這時候自然不能依賴cpu的硬體了,該怎麼轉換呢?define va x vo...
Linux中通過 dev mem操控實體地址
dev mem是物理記憶體的全映像,可以用來訪問物理記憶體,用mmap來訪問物理記憶體以及外設的io資源,是實現使用者空間驅動的一種方法 我們先用hexedit來看下 dev mem,hexedit dev mem 可以物理記憶體的資訊,當然肉眼是無法看的畢竟是16進製制。00000000 53 f...