首先是关于我正在使用的机器的一些背景信息(它是一个带有 SoC 的 SOM,其中包括一个 FPGA 和两个 CPU,其中一个运行着一个 linux 操作系统)。
特征:
- 板 : Microzed
- 系统芯片:Zynq 7020
- 操作系统:Petalinux 2019.2
- 内核版本:4.19.0-xilinx-v2019.2
- 处理器类型:ARMv7 处理器 rev 0 v7l (armv7l)
我在 FPGA 上实现了一个自定义外设,它为 BRAM 存储器提供标准 AXI4 接口(感谢这个组件)。该外围设备已在我的设备树中注册,并且可以通过内核的 generic-uio 驱动程序访问(有关此的更多文档)。
BRAM 内存的大小为 32kB。以下是出现在 中的映射特征/sys/class/uio/uioX/maps/map0/
:
- 地址 = 0x40000000
- 偏移量 = 0x0
- 大小 = 0x00008000
我正在编写一个 C 代码,其目的只是为了读取这个 BRAM 内存并将里面的内容记录在一个文本文件中。为了做到这一点,我使用mmap
(这里是它的手册页)来创建位于/dev/uioX
(对应于我的设备)中的文件的一些内存投影。
我只想使用我需要的文件页面,更精确地映射每页的文件页面。这是我用来创建一页映射的函数:
/**
* @brief Get a pointer to the corresponding file page
*
* @param filePage file page number
* @param fd pointer where the file descriptor will be stored
* @return int*
*/
int *getFilePagePointer(int *fd, unsigned int filePage)
{
// open driver file
*fd = open("/dev/uio1", O_RDWR);
if (*fd == -1)
{
int errsv = errno;
fprintf(stderr, "Error while opening /dev/uio1 : errno %d (%s).\n", errsv, strerror(errsv));
exit(EXIT_FAILURE);
}
// choose projection parameters
int length = sysconf(_SC_PAGE_SIZE);
int offset = filePage * sysconf(_SC_PAGE_SIZE);
// create mapping
void *filePagePointer = mmap((void *)NULL, (size_t)length, PROT_READ, MAP_PRIVATE, *fd, (off_t)offset);
if (filePagePointer == MAP_FAILED)
{
int errsv = errno;
fprintf(stderr, "Error while mapping file page : errno %d (%s).\n", errsv, strerror(errsv));
exit(EXIT_FAILURE);
}
return (int *)filePagePointer;
}
filePage
然后是问题:如果(即偏移)是,它工作得非常好,0
但如果它是严格正数,它会失败,并且errno = 22
.
除非我错过了手册页中的某些内容,否则所有参数都是有效的(offset
是 的倍数sysconf(_SC_PAGE_SIZE)
,addr
是NULL
,length
严格为正且不太大,并且标志是正确的)。那么,为什么是 EINVAL ?...