一:當我們開啓了MMU之後,使用的都是虛擬地址,這時就需要考慮物理地址到虛擬地址的映射問題。建立映射表的三個關鍵部分是:
(1)映射表
(2)映射表建立函數
(3)映射表建立函數被調用
1:映射表
(1)映射表是具體的物理地址和虛擬地址的起始地址定義,在我們前面使用靜態映射來操作LED時有介紹,三星版本的移植的內核,其主映射表在arch/arm/plat-s5p/include/plat/map-s5p.h和arch/arm/plat-samsung/include/plat/map-base.h中
arch/arm/plat-s5p/include/plat/map-s5p.h的主要內容如下
arch/arm/plat-samsung/include/plat/map-base.h的主要內容如下:
在這裏,我們指定了虛擬地址的基地址,也就是宏S3C_ADDR_BASE 0XFD000000,在我們開啓了MMU之後,其映射的虛擬地址都是根據這個基地址+偏移量來得到的某個具體的寄存器的,這樣當我們建立了映射之後,就可以直接操作虛擬地址來操作我們對應的寄存器,在這裏,也只是映射了需要用到的寄存器的虛擬地址,假如要添加,則只需在map-s5p.h中添加相應的映射即可。
(2)GPIO相關的主映射表位於:arch/arm/machs5pv210/include/mach/regs-gpio.h
GPIO的具體寄存器定義位於:arch/arm/mach-s5pv210/include/mach/gpio-bank.h
需要注意的是,不同版本的內核其映射表的位置是不同的,,但是一般都在arch/arm/xxx/map_xx.h文件中
2:映射表的建立過程
上面,我們介紹了內核通過宏定義定義了很多寄存器對應虛擬地址的基地址,那麼這些宏是在哪被調用的呢,映射表又是如何被調用的呢。
答案就是kernel/arch/arm/mach-s5pv210/mach-smdkc110.c中的smdkc110_map_io函數。它的調用層級如下:
smdkc110_map_io
s5p_init_io
iotable_init
iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
iotable_init函數就是最終實現建立虛擬地址映射的函數。其中S5P_iodesc是一個數組,它裏面包括了我們上面用大量的宏定義得到的映射表。也就是說我們上面創建的宏都在這裏被使用到了。
所以當我們需要添加新的虛擬地址映射時只需要做兩步
(1)在我們的map-s5p.h或者是map-base.h中添加相應的宏定義
(2)在我們的s5p_iodesc中添加相應的數組元素
3:映射表建立函數的調用過程