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

本文详细解析了操作系统中的writel与readl函数,包括它们如何实现内存映射设备的读写操作,以及底层的具体实现细节。这些函数用于32位数据的写入和读取,对于理解操作系统内存管理至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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)


 readX/writeX() are used to access memory mapped devices. On some

 architectures the memory mapped IO stuff needs to be accessed

 differently. On the simple architectures, we just read/write the

 memory location directly.

writel() 往内存映射的 I/O 空间上写数据,wirtel()  I/O 上写入 32 位数据 (4字节)。

 

 原型:

#include  

void writel (unsigned char data unsigned short addr )

 

 

readl() 从内存映射的 I/O 空间读取数据,readl 从 I/O 读取 32 位数据 字节 )

 

原型:

#include  

unsigned char readl (unsigned int addr )

 

变量    addr  是 I/O 地址。

返回值  从 I/O 空间读取的数值。

 

定义

#define readb __raw_readb

#define readw(addr) __le16_to_cpu(__raw_readw(addr))

#define readl(addr) __le32_to_cpu(__raw_readl(addr))

#ifndef __raw_readb

static inline u8 __raw_readb(const volatile void __iomem *addr)

{

    return *(const volatile u8 __force *) addr;

}

#endif

 

#ifndef __raw_readw

static inline u16 __raw_readw(const volatile void __iomem *addr)

{

    return *(const volatile u16 __force *) addr;

}

#endif

 

#ifndef __raw_readl

static inline u32 __raw_readl(const volatile void __iomem *addr)

{

    return *(const volatile u32 __force *) addr;

}

#endif

 

#define writeb __raw_writeb

#define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr)

#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值