您的位置:首页 > 其它

内核里面writel(readl)是如何实现的

2012-09-05 09:30 288 查看
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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: