writel和readl,这两个个函数实现在操作系统层,有内存保护的情况下,往一个寄存器或者内存地址写一个数据。先说一下writel: 在arch/alpha/kernel/io.c中有 188 void writel(u32 b, volatile void __iomem *addr)
189 {
190__raw_writel(b, addr);
191mb();
192 }
这样一个writel函数的作用应该是向一个地址上写一个值,我想知道这个函数底下具体实现的细节,于是往下继续跟踪代码:__raw_writel(b, addr);
(发现在同目录下)
129 void __raw_writel(u32 b, volatile void __iomem *addr)
130 {
131IO_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_PREFIXapecs 继续阅读代码,看看定义__IO_PREFIX之后紧接着包含了哪个头文件。在哪个头文
件里面寻找答案。对于你的apsec,看看以下代码段(linux-2.6.28-rc4)
arch/alpha/include/asm/core_apecs.h
------------------------------------------
#undef __IO_PREFIX
#define __IO_PREFIXapecs
#define apecs_trivial_io_bw0
#define apecs_trivial_io_lq0
#define apecs_trivial_rw_bw2
#define apecs_trivial_rw_lq1
#define apecs_trivial_iounmap1
#include
------------------------------------------
前往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)
推荐阅读
- c语言|一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc
- 嵌入式-外设|DDR3基础详解
- ffmpeg|从零开始仿写一个抖音App——基于FFmpeg的极简视频播放器
- #|Multimedia
- USB转串口|USB转四串口芯片CH9344
- python|Python的DEBUG LOG
- ARM的C语言程序优化
- linux|【原创】ARM LINUX 外部RTC实时时钟驱动移植(RX8025)
- linux进程通信(一)--共享内存+信号量,代码示例
- C|堆和栈