本文共 2206 字,大约阅读时间需要 7 分钟。
转自:
readb(), readw(), readl()函数
功能: 从内存映射的 I/O 空间读取数据。 readb 从 I/O 读取 8 位数据 ( 1 字节 ); readw 从 I/O 读取 16 位数据 ( 2 字节 ); readl 从 I/O 读取 32 位数据 ( 4 字节 )。 原型: #include <asm/io.h> unsigned char readb (unsigned int addr ) unsigned char readw (unsigned int addr ) unsigned char readl (unsigned int addr ) 变量: addr I/O 地址。 返回值: 从 I/O 空间读取的数值。 writeb(), writew(), writel() 宏函数 功能: 往内存映射的 I/O 空间上写数据。 writeb() I/O 上写入 8 位数据 (1字节) writew() I/O 上写入 16 位数据 (2字节) wirtel() I/O 上写入 32 位数据 (4字节) 原型: 引用 #include <asm/io.h> void writeb (unsigned char data, unsigned short addr) void writew (unsigned char data, unsigned short addr) void writel (unsigned char data, unsigned short addr) 变量: data I/O 地址;data 数据。
内核里面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)
本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/4905198.html,如需转载请自行联系原作者