用uio正确映射读写内存mmap
在 OpenLunar 系统中,要通过 UIO 映射出可读写的内存,可以按照以下步骤确保正确配置和使用 `UIO`,以便映射后的内存具有读写权限。
### 1. 配置设备树 (DTS) 文件
在 OpenLunar 系统中,通常通过设备树(DTS)文件为 `UIO` 设备定义内存区域和访问权限。需要确保在 DTS 中定义的 `reg` 属性范围内的内存是可读写的。
#### DTS 配置示例
假设要创建一个 `UIO` 设备节点,以下是一个示例设备树片段:
```dts
uio_device@0 {
compatible = "generic-uio";
reg = <0x40000000 0x1000>; // 假设内存起始地址和大小
interrupts = <0 32 4>; // 设备中断配置,视需要而定
};
```
确保该 `reg` 地址范围内的内存支持读写。如果硬件设计将这部分内存设置为只读,那么需要调整硬件配置。
### 2. 加载 UIO 驱动
确保内核已启用 `UIO` 支持,或者使用 `uio_pdrv_genirq` 驱动绑定设备。可以通过以下命令来绑定驱动:
```bash
modprobe uio
modprobe uio_pdrv_genirq
```
然后,将设备节点与 `uio_pdrv_genirq` 绑定:
```bash
echo "generic-uio" > /sys/bus/platform/devices/uio_device@0/driver_override
echo "uio_pdrv_genirq" > /sys/bus/platform/drivers/uio_pdrv_genirq/bind
```
### 3. 使用 `mmap` 映射内存
在应用程序中,通过 `/dev/uioX` 设备文件访问 `UIO` 内存,并使用 `mmap` 映射为用户空间内存。
确保 `mmap` 使用了 `PROT_READ | PROT_WRITE` 权限,并且映射模式为 `MAP_SHARED`。以下是一个 `mmap` 映射的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#define UIO_DEV "/dev/uio0" // 假设设备文件为 /dev/uio0
#define MEM_SIZE 0x1000 // 映射内存大小,与 DTS 配置保持一致
int main() {
int uio_fd;
void *mapped_mem;
// 打开 UIO 设备文件
uio_fd = open(UIO_DEV, O_RDWR);
if (uio_fd < 0) {
perror("Failed to open UIO device");
return -1;
}
// 使用 mmap 映射内存
mapped_mem = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, uio_fd, 0);
if (mapped_mem == MAP_FAILED) {
perror("mmap failed");
close(uio_fd);
return -1;
}
// 写操作示例
*((volatile int *)mapped_mem) = 0x12345678;
// 读操作示例
int read_value = *((volatile int *)mapped_mem);
printf("Read value: 0x%x\n", read_value);
// 解除映射并关闭文件
munmap(mapped_mem, MEM_SIZE);
close(uio_fd);
return 0;
}
```
#### 代码说明
1. **打开 UIO 设备文件**:通过 `/dev/uioX`(如 `/dev/uio0`)访问设备。
2. **mmap 映射**:`PROT_READ | PROT_WRITE` 和 `MAP_SHARED` 确保内存映射支持读写且可以被多个进程共享。
3. **读写操作**:通过指针直接访问映射内存区域,进行读写操作。
4. **清理资源**:使用 `munmap` 解除映射,并关闭设备文件。
### 4. 检查内存权限
如果在上述步骤完成后仍无法写入,可能是硬件或系统设置中限制了内存写入权限。可以通过以下步骤检查内存是否可写:
- 使用 `devmem` 工具在物理地址上直接写入,验证是否能正常写入。
- 确保映射区域不受内存保护机制影响,避免写保护设置。
### 5. 确保内存一致性
对于某些内存映射,可能需要调用 `msync` 以确保缓存一致性:
```c
msync(mapped_mem, MEM_SIZE, MS_SYNC);
```
### 总结
1. **正确配置 DTS** 以确保 `UIO` 设备支持可读写内存区域。
2. **加载 UIO 驱动** 并使用 `uio_pdrv_genirq` 驱动绑定设备。
3. **使用 mmap** 时设置 `PROT_READ | PROT_WRITE` 权限。
4. **验证内存权限**,确保硬件和系统不限制写操作。
5. **保持缓存一致性**,确保写入立即生效。