Linux內核里mmu已經啟動,不能直接訪問物理地址。 mmu,全稱Memory Manage Unit, 中文名————存儲器管理單元。 地址範圍—— 電腦上的地址集合。(大小是由CPU的位數決定)32位——0 ~ 0xFFFFFFFF(4G), 64位——0~0xFFFFFFFFFFFFFFF ...
Linux內核里mmu已經啟動,不能直接訪問物理地址。
mmu,全稱Memory Manage Unit, 中文名————存儲器管理單元。
- 地址範圍—— 電腦上的地址集合。(大小是由CPU的位數決定)32位——0 ~ 0xFFFFFFFF(4G), 64位——0~0xFFFFFFFFFFFFFFFF(64T)。地址範圍也叫虛擬地址空間,該空間的某一個地址我們稱之為虛擬地址。
- 物理地址———真實地址空間。
MMU是如何工作?
進程X開始運行時,訪問到VPRN0,是虛擬地址。VPFN0是指向頁表(頁表分為page index(頁號索引),offset(偏移位)。頁表的詳細說明 http://blog.csdn.net/seanyxie/article/details/5728772)。通過頁表,會發現該部分的虛擬記憶體實際上是位於PFN0區域,所以程式實際上訪問的就是物理記憶體的PFN0區域。VPFN3----->PFN4。 當我的Y進程也在運行時 Y的虛擬記憶體VPFN1——>PFN4。
由此,我們得出以下結論:
- 物理地址,和虛擬地址沒什麼關係。
- 不同進程會被分配同一個物理記憶體
- 不同的進程的虛擬記憶體,其對應的物理記憶體實際上沒有多大關係
////////////////////////////////
Linux內核的MMU已經啟動,我們如何去直接訪問物理地址?
#include <asm/io.h>
void *ioremap(cookie,size) //該函數用於把指定的物理地址映射到一個虛擬地址上
//cookie 指定物理地址, size表示映射的大小範圍
//返回值為映射得到的虛擬地址
iounmap(void *addr) //用於取消虛擬地址的映射關係。
ioread8(地址)/readb() // 讀地址上的8位值, readb是比較老的函數 ioread16(地址)/readw()// 讀16位 ioread32(地址)/readl()//讀32位 iowrite8(值,地址)/writeb//寫8位,writeb是比較老的函數 iowrite16(值,地址)/writew//寫16位 iowrite32(值,地址)/writel//寫32位
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <asm/io.h> 4 5 #define BADDR 0x01c20800 6 u8 *vaddr; //用於記錄映射的虛擬地址 7 8 static int __init myinit(void) 9 { 10 u32 val; 11 vaddr = ioremap(BADDR, SZ_4K); 12 13 printk("myinit......."); 14 return 0; 15 } 16 17 static void __exit myexit(void) 18 { 19 printk("myexit"); 20 21 iounmap(vaddr); 22 } 23 24 module_init(myinit); 25 module_exit(myexit); 26 27 MODULE_ILCENSE("GPL");
Linux 內核提供gpio口的操作的函數
linux內核里有標準的GPIO操作方法. 其中有對晶元廠商的要求,晶元廠商需要在內核里實現相關的GPIO控制器的驅動配置, 讓內核里的gpiolib(drivers/gpio/目錄下)可以統一管理整個晶元的gpio口, 讓我們驅動人員可以用內核提供的gpio標準操作函數通過gpiolib來調用控制晶元的io口.
#include <linux/gpio.h> int gpio_request(unsigned gpio, const char *label);//用於io口申請,每個io只能一次 void gpio_free(unsigned gpio); //釋放已請求的io口 int gpio_direction_input(unsigned gpio);//把io作為輸入功能 int gpio_direction_output(unsigned gpio, int value);//作輸出,並根據value的值輸出高低電平 int gpio_get_value(unsigned gpio);//獲取指定io的電平 void gpio_set_value(unsigned gpio, int value);//設置io的電平 int gpio_to_irq(unsigned gpio);//獲取到gpio的中斷號
如何在內核里找到GPIO口的定義。有兩種方法:
- 一般情況下, io口的定義是在內核源碼arch/arm/mach-xxxx/include/mach/gpio.h.(mach-xxxx是和板有關)
- 我們可以反著來,查找誰在用GPIO口。例如:我們查gpio_request,看看GPIO口的定義。
我們可以不用看CPU的晶元手冊,直接控制GPIO。