內核里面writel(readl)是如何實現的


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
  • #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>
前往arch/alpha/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)

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM