writel和readl,這兩個個函數實現在操作系統層,有內存保護的情況下,往一個寄存器或者內存地址寫一個數據。先說一下writel:
在arch/alpha/kernel/io.c中有
-
188 void writel(u32 b, volatile void __iomem *addr) 189 { 190 __raw_writel(b, addr); 191 mb(); 192 }
這樣一個writel函數的作用應該是向一個地址上寫一個值,我想知道這個函數底下具體實現的細節,於是往下繼續跟蹤代碼:__raw_writel(b, addr);(發現在同目錄下)
-
129 void __raw_writel(u32 b, volatile void __iomem *addr) 130 { 131 IO_CONCAT(__IO_PREFIX,writel)(b, addr); 132 }
再往下跟蹤 IO_CONCAT,在對應的io.h中的定義如下:
-
134 #define IO_CONCAT(a,b) _IO_CONCAT(a,b) 135 #define _IO_CONCAT(a,b) a ## _ ## b
這段代碼前幾天問過了,是標示將兩邊的字符串連接起來的意思。
跟蹤__IO_PREFIX 定義如下
-
501 #undef __IO_PREFIX 502 #define __IO_PREFIX apecs
繼續閱讀代碼,看看定義__IO_PREFIX之后緊接着包含了哪個頭文件。在哪個頭文
件里面尋找答案。對於你的apsec,看看以下代碼段(linux-2.6.28-rc4)
arch/alpha/include/asm/core_apecs.h
件里面尋找答案。對於你的apsec,看看以下代碼段(linux-2.6.28-rc4)
arch/alpha/include/asm/core_apecs.h
-
#undef __IO_PREFIX #define __IO_PREFIX apecs #define apecs_trivial_io_bw 0 #define apecs_trivial_io_lq 0 #define apecs_trivial_rw_bw 2 #define apecs_trivial_rw_lq 1 #define apecs_trivial_iounmap 1 #include <asm/io_trivial.h>
-
__EXTERN_INLINE void IO_CONCAT(__IO_PREFIX,writel)(u32 b, volatile void __iomem *a) { *(volatile u32 __force *)a = b; }
就是最終通過*(volatile u32 __force *)a = b;
來寫入數據的。
來寫入數據的。
同樣的readl讀取數據也和writel類似,這里就不重復了。
(如果在沒有os,沒有mmu的情況下,當開發板裸跑的時候,我們只需要一句話就一切ok:
-
*(unsigned long *)addr = value)