學習了 gpio_newbule 之後,一血關於對映上面的問題總結。io_address : 靜態對映,一般是暫存器資源對映上,對映的時間是,當系統啟動的時候,就完成對映的操作,
實體地址 = 基址 + 偏移位址,所以使用 io_address 進行位址對映的時候,存在兩種對映,既直接使用物理位址對映和先對基址對映之後,再加上偏移位址,這兩種對映的最終位址,都是一樣的。方法一:
#define ioconfig io_address(0x200f0000) //io復用暫存器
#define hw_reg(reg) *((volatile unsigned int *)(reg))
hw_reg(ioconfig + 0x138) = 0;
上面的**,是實現 200f_0000 基址位址的對映之後,再加上偏移位址。
方法二:writel(0, io_address(0x200f0138));
實現是對實體地址做完對映之後,進行寫入 0 的操作。
兩種方法,經過驗證,最終得到的虛擬位址是完全一樣的,本平台使用的是 海思的 hi3518平台,所以關於 io_address 的定義是位於io.h (arch\arm\mach-hi3518\include\mach) 這裡,裡面看到 io_address 定義為:
#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
#define hi3518_ioch1_phys 0x10000000 /* 0x1000_0000 ~ 0x1020_0000 */
#define hi3518_ioch2_phys 0x20000000 /* 0x2000_0000 ~ 0x2020_0000 */
#define hi3518_ioch1_size 0x200000
#define hi3518_ioch2_size 0x700000
#define hi3518_ioch1_virt 0xfe000000
#define hi3518_ioch2_virt (hi3518_ioch1_virt + hi3518_ioch1_size)
/*
* physical addr <---> virtual addr
* [0x1000_0000 ~ 0x1020_0000) <---> [0xfe00_0000 ~ 0xfe20_0000)
* [0x2000_0000 ~ 0x2070_0000) <---> [0xfe20_0000 ~ 0xfe90_0000)
*/
#define io_ioch1_offset (hi3518_ioch1_virt - hi3518_ioch1_phys)
#define io_ioch2_offset (hi3518_ioch2_virt - hi3518_ioch2_phys)
#define io_address(x) ((x) >= hi3518_ioch2_phys ? (x) + io_ioch2_offset\
: (x) + io_ioch1_offset)
當io_address(0x200f0000) = (0x200f0000) + io_ioch2_offsetvoid writeb(unsigned value, address); // 8位= (0x200f0000) + (hi3518_ioch2_virt - hi3518_ioch2_phys)
= (0x200f0000) + (hi3518_ioch2_virt - 0x20000000)
= (0x200f0000) + (0xfe000000 + 0x200000) - 0x20000000
= fe2f0000
所以,io_address(0x200f0000) + 0x138 = fe2f0138
噹噹io_address(200f0138) = (200f0138) + io_ioch2_offset
= 200f0138 + (hi3518_ioch2_virt - hi3518_ioch2_phys)
= 200f0138 + (hi3518_ioch1_virt + hi3518_ioch1_size) - 0x20000000
= 200f0138 + 0xfe000000 + 0x200000 - 0x20000000
= fe2f0138
可見最終的虛擬位址,都一樣的。
void writew(unsigned value, address); // 16 位
void writel(unsigned value, address); // 32 位
這些寫入函式,完成寫 value 到 address 的位址,address 位址都是已經完成對映的虛擬位址
unsigned readb(address);
unsigned readw(address);
unsigned readl(address);
讀出函式,是將虛擬位址 address 處,讀出暫存器的值。
#define hw_reg(reg) *((volatile unsigned int *)(reg))
hw_reg(ioconfig + 0x138) = 0;
通過,巨集**的方法實現暫存器的寫入
#define gpio0_6_dir io_address(0x20140000+ 0x400)
flag = hw_reg(gpio0_6_dir);
完成暫存器資料的讀出。
筆者,想尋找關於 io_address 是在那個標頭檔案定義的,經過朋友指點才找到,但是還有通過重複定義的方法,編譯器會提供相關的資訊,其實就可以找到。在函式裡面,自己定義 io_address ,而標頭檔案包含的地方,也是存在 io_address 的,所以就出現了重複定義的錯誤,當編譯的時候,就會報錯:
/home/carlos/3516c/driver/gpio_newblue/gpio.c:168: warning: "io_address" redefined
arch/arm/mach-hi3518/include/mach/io.h:25: note: this is the location of the previous definition 可見,與真正的標頭檔案是在,arch/arm/mach-hi3518/include/mach/io.h,達到我們的目的
ZF框架資料物件對映模式的思考
最近學了zf框架,對手冊中db這一節zend db table row的介紹中說,使用了zend db table find 或 findrow 方法可以返回乙個zend db table row的物件,該物件自動對映到表中的這一行記錄,欄位和類屬性完全關聯在一起 欄位名是下劃線分隔的,屬性名由首個...
每日思考記錄(5)
1 調整狀態 1 盡量不要去看相關的東西和事情 2 轉移注意力,把注意力集中到測試題上 3 控制情緒,要發火或是很那受就扇自己一耳光,打醒自己 4 調整作息,因為失眠導致睡眠狀態不好,很影響做題效率,中午要午休,睡半個小時 6 累了就閉上眼睛,眼睛腫了可以消,但一直腫就不行,強制閉上休息會 2 針對...
CE 5記憶體對映
rel file list href file c 5cdocume 7e1 5cadmini 7e1 5clocals 7e1 5ctemp 5cmsohtml1 5c03 5cclip filelist.xml 越是相近的東西,越是容易混淆 反倒是不同的特徵,容易描述清楚。既如此,我就從簡到難,...