5 對映的思考

2022-09-03 11:42:12 字數 3529 閱讀 9242

學習了 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_offset

= (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 writeb(unsigned value, address);   // 8位

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 越是相近的東西,越是容易混淆 反倒是不同的特徵,容易描述清楚。既如此,我就從簡到難,...