linux - ioread32 后跟 iowrite32 没有给出相同的值

标签 linux memory io linux-device-driver

我已经开始学习 linux 设备驱动程序。作为我学习的一部分,我正在做一些示例程序。为了理解内存映射 IO,我编写了以下代码。(此处仅显示 init)。没有硬件映射到基地址。

static unsigned long base = 0xfed00000;
unsigned long device_base=0;
unsigned long virtual_base=0;

static int __init sharedirqmodule_init(void) {
u32 register1=0;
u32 value=0x23456789;
device_base=base;
void *address=0;

if(!request_mem_region(device_base,8,"device"))
    return -ENODEV;

virtual_base = (unsigned long) ioremap(device_base, 8);
address=(void *)virtual_base;

printk(KERN_ERR "Sharedirq : Address value: %lx\n",address);

iowrite32(value,address);
wmb();

register1=(u32)ioread32(address);
rmb();

printk(KERN_ERR "Shared irq :value: %d \n",register1);

    return 0;
}

模块正在安装。但是我没有得到我在使用 ioread32 时写的正确值。 我得到以下输出,

[20441.627344] Sharedirq : Address value: ffffc900001ce000
[20441.627365] Shared irq :value: -1  

程序出了什么问题?如果错误是愚蠢的,我会很感激一个线索而不是一个直接的解决方案。(很抱歉为相同的值使用多个变量.. virtual_base 和地址)

最佳答案

There is no hardware mapped at the base address. ... What is going wrong in the program?

正如@AndreasBombe 指出的那样,写入然后读取没有硬件(既没有 RAM 也没有设备寄存器/内存)的内存位置将产生未定义的结果。

I just request_mem_region that region and did a ioremap to use that region. Shouldn't that work? I thought it kind of simulate the memory mapped IO usage.

在您不会从这些调用中收到任何错误的意义上,这应该“有效”。但由于这些物理位置没有硬件,因此访问这些虚拟地址没有任何意义。

The value should be saved in physical memory as the virtual address provided by ioremap would have mapped to a physical address.

这些例程并不像您认为的那样。您之前写过物理地址处没有硬件。调用这些例程后也不会再有。

request_mem_region() 本质上是“分配”给定的物理地址范围(也就是说,它被记录为“正在被该驱动程序使用”)。就这样;除了地址管理,别无其他。
ioremap() 是特定于体系结构的,目的是为物理地址区域提供虚拟地址映射。 Linux 代码只能使用虚拟地址来引用内存,所以现在那些设备寄存器/内存是可以访问的。
request_mem_region()ioremap() 实际上都不会提供任何物理内存供您的驱动程序使用。

I thought iowrite and ioread get converted to ordinary MOV instruction in memory mapped IO case.Is my understanding wrong?

内存映射 I/O 位置将作为虚拟内存操作访问。如果 CPU 的指令集使用 MOV 操作码来访问内存,那么你是对的。
但是为了正确执行您的程序,在那些可以响应存储和获取操作的位置必须有实际的硬件。

I understand it will fail in I/O mapped case

不存在“I/O 映射”这样的东西。
存在“端口映射 I/O”,其设备地址位于与内存不同的空间中,并使用输入输出 指令进行访问。

How does a driver written for a memory mapped IO device use the memory it requested using request_mem_region() & ioremap()?

从技术上讲,内存不是“请求的”。我会把它表述为“设备内存(或寄存器)被映射到虚拟内存(空间)”。

include/asm-generic/iomap.h 中,ioremap() 返回的值被描述为 cookie,因此不应用作虚拟内存地址由驱动程序,但通过访问函数,如 ioread*() & iowrite*():

 17 /*
 18  * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
 19  * access or a MMIO access, these functions don't care. The info is
 20  * encoded in the hardware mapping set up by the mapping functions
 21  * (or the cookie itself, depending on implementation and hw).
 22  *
 23  * The generic routines just encode the PIO/MMIO as part of the
 24  * cookie, and coldly assume that the MMIO IO mappings are not
 25  * in the low address range. Architectures for which this is not
 26  * true can't use this generic implementation.
 27  */
 28 

ioread*()iowrite*() 的通用版本通常被特定于体系结构的版本所取代。

Will ioread() and iowrite() automatically work in that case?

如果“自动”意味着“总是”,那么“不”。并非每个设备寄存器都是可读和/或可写的。
ioread*() 只应在可读的寄存器上执行。 iowrite*() 只应在可写的寄存器上执行。例如。设备状态寄存器当然是可读的,很可能是不可写的。

关于linux - ioread32 后跟 iowrite32 没有给出相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26831583/

相关文章:

linux - 强制 cli 实用程序在不提供配置选项且仅写入文件时写入 stdout

linux - ping "-n"标志如何工作?并且它会影响响应时间吗? (Linux)

Android SplashScreen 主题占用大量内存

assembly - 16 位 x86 汇编器,使用 8 位内存存储的颜色变量在屏幕上绘制蓝色时遇到问题吗?

c++ - 堆内存为何产生?

java - java中ObjectInputStream中的IOException

java - 在什么条件下对 lucene 索引(指南针)进行 I/O 操作(移动/替换)是安全的

linux - 在 RedHat Linux 脚本中使用 cd

linux - 从 Windows 下载 debian Neo4j 版本

c - 制作 Linux shell 时的流重定向和管道